התקנת Docker Compose על Ubuntu 24.04: מדריך מעשי
למדו להתקין Docker Engine ו-Compose v2 על Ubuntu 24.04. המדריך מסביר כיצד להגדיר שירותים עם PostgreSQL, למנוע עקיפת חוקי ufw בפורטים, ולבצע גיבוי בטוח לכרכי הנתונים.
מה אתם בונים
Docker Compose הוא התשתית שעליה מבוסס כמעט כל דבר באתר זה. Nextcloud, Vaultwarden, n8n, Immich, Rocket.Chat – כל אחד מהמדריכים הללו נפתח בהנחיה "כתבו את קובץ ה-compose הזה", וזהו הדף שמסביר מה המשמעות האמיתית של הקובץ. אתם תתקינו את Docker Engine ואת התוסף Compose v2 מתוך מאגר ה-apt הרשמי של Docker על גבי Ubuntu 24.04, ולאחר מכן תקימו stack אמיתי של שני שירותים: Miniflux, קורא RSS קל, ו-PostgreSQL. צמד זה מתרגל את כל התבניות שבהן משתמשים היישומים הגדולים יותר: תמונות (images) בגרסה נעולה, מסד נתונים עם בדיקת תקינות (healthcheck), כרך (volume) בעל שם, סודות (secrets) בקובץ .env, ופורט שחשוף ל-localhost בלבד.
ההתקנה אורכת חמש דקות. שאר המדריך עוסק בחלקים שעלולים להכאיב בהמשך: העובדה שקבוצת ה-docker היא למעשה הרשאות root בשם אחר, פורטים חשופים שעוקפים ישירות את חוקי ה-ufw שלכם, והדגל האחד ב-docker compose down שמוחק את מסד הנתונים שלכם ללא בקשת אישור.
דרישות קדם: שרת VPS מסוג KVM עם Ubuntu 24.04 בהתקנה נקייה, משתמש עם הרשאות sudo, וזיכרון RAM בנפח גיגה-בייט אחד או יותר. התקנה קיימת של Docker גם היא תקינה; החלק הראשון מסביר מה יש להסיר.
התקנה ממאגר הנתונים של Docker, לא של Ubuntu
יש להימנע משתי טעויות נפוצות לפני הרצת הפקודה הראשונה. החבילה docker.io של Ubuntu עובדת, אך היא מפגרת אחרי הגרסאות של Docker וחסר בה מבנה ה-plugin שכל שאר הרכיבים מצפים לו. כמו כן, הקובץ הבינארי העצמאי docker-compose, זה עם המקף, הוא Compose v1: מבוסס Python, הגיע לסוף חייו ב-2023, והוא הסיבה לכך שמדריכים ישנים נכשלים. כיום, Compose הוא docker compose עם רווח, תוסף CLI המותקן מאותו מאגר נתונים של ה-engine.
אם אחד מאלה כבר מותקן על השרת, יש להסיר אותו תחילה, כולל docker-compose-v2, חבילת ה-plugin של Ubuntu, כדי שכל הרכיבים יגיעו מאותו מאגר נתונים:
sudo apt remove -y docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runcPackage 'docker.io' is not installed, so not removed הוא הפלט התקין ב-VPS חדש. לאחר מכן, יש להוסיף את מאגר הנתונים של Docker ולהתקין:
sudo apt update
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginיש לוודא את תקינות כל שלוש השכבות:
docker --version
docker compose version
sudo docker run --rm hello-worldשתי הפקודות הראשונות מדפיסות מחרוזות גרסה, ו-Docker Compose version v2.x.x מאשרת שיש ברשותך את ה-plugin ולא את הקובץ הבינארי הישן (v1). הפקודה hello-world אמורה להסתיים עם Hello from Docker!. החבילה מפעילה את השירות בעת עליית המערכת; systemctl is-enabled docker מדפיס enabled.
קבוצת docker היא root, החליטו בעיניים פקוחות
כרגע, כל פקודת docker מחייבת sudo, כיוון שה-socket של ה-daemon בנתיב /var/run/docker.sock נמצא בבעלות המשתמש root וקבוצת docker. ללא חברות בקבוצה זו, תקבלו את שגיאת ה-Docker הנפוצה ביותר בחיפושי גוגל:
permission denied while trying to connect to the Docker daemon socket at
unix:///var/run/docker.sockהפתרון הסטנדרטי:
sudo usermod -aG docker $USERחברות בקבוצה נכנסת לתוקף בעת התחברות (login), לכן השגיאה תמשיך להופיע ב-shell הנוכחי שלכם. הריצו את newgrp docker עבור סשן זה, או התנתקו והתחברו מחדש; לאחר מכן, הפקודה id אמורה להציג את docker ברשימת הקבוצות שלכם.
כעת לחלק הכנה, שנאמר בצורה ברורה: חברות בקבוצת docker שקולה ל-root על המארח (host). לא "דמוי root", לא "הרשאות מורחבות", אלא root. כל מי שנמצא בקבוצה זו יכול להריץ docker run --rm -it -v /:/host alpine chroot /host ולהשתלט על כל מערכת הקבצים, ללא צורך בסיסמה. הקבוצה קיימת לנוחות, לא לצורך בידוד.
מצב rootless של Docker הוא החלופה האמיתית; ה-daemon עצמו רץ כמשתמש ללא הרשאות מיוחדות. המחיר לכך: פורטים מתחת ל-1024 דורשים הגדרה נוספת, התקשורת עוברת דרך userspace shim עם תקורה (overhead) מדידה, וחלק מה-images לא פועלים כשורה ללא root אמיתי. בשרת VPS עם מנהל מערכת יחיד שגם כך מחזיק בהרשאות sudo, השינוי בקבוצה אינו משנה דבר בפועל, וזהו המצב שכל מדריך כאן מניח – רק לעולם אל תחלקו הרשאה זו כאילו היא פחותה מ-sudo.
אנטומיה של קובץ compose
הקצו לכל stack ספרייה משלו. שם הספרייה הופך לשם הפרויקט, ומשמש כתחילית לשמות המכולות, הרשתות והווליומים:
sudo mkdir -p /opt/miniflux && sudo chown $USER /opt/miniflux && cd /opt/minifluxצרו קובץ compose.yml (זהו השם המודרני; docker-compose.yml עדיין עובד). דלגו על המפתח הישן version:, הוא מיושן ו-Compose מציג אזהרה אם הוא מופיע.
services:
miniflux:
image: miniflux/miniflux:2.2.9
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080"
environment:
- DATABASE_URL=postgres://miniflux:${POSTGRES_PASSWORD}@db/miniflux?sslmode=disable
- RUN_MIGRATIONS=1
- CREATE_ADMIN=1
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=${ADMIN_PASSWORD}
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=miniflux
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=miniflux
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "miniflux", "-d", "miniflux"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-data:כל שורה לעיל היא החלטה. בצעו אותן אחת אחת.
קיבוע גרסאות image, כי :latest עם pull הוא שדרוג לא מבוקר
השתמשו ב-postgres:16-alpine, לא ב-postgres:latest. תגית אינה מצב קפוא: :latest מתרגם מחדש למה שהמפתח דחף לאחרונה, בכל פעם שמבצעים pull. אם משלבים זאת עם הרגל השדרוג השגרתי שאתם עומדים ללמוד, docker compose pull && docker compose up -d, הרי ש-:latest גורם לקפיצות גרסה ראשיות להתרחש ברגע שהן משוחררות, ולא כשאתם בוחרים בכך. ב-PostgreSQL זה אינו תרחיש היפותטי: קפיצה מפתיעה מ-16 ל-17 תשאיר את המכולה בלולאת קריסה בגלל ספריית נתונים לא תואמת, שכן שדרוגי גרסה ראשית ב-Postgres דורשים dump ו-restore, לא רק הפעלה מחדש.
קבעו לפחות את הגרסה הראשית (postgres:16-alpine עוקב אחר גרסאות תיקון 16.x), וקבעו יישומים לגרסה מדויקת כמו miniflux/miniflux:2.2.9. בדקו את דף ה-releases של הפרויקט והשתמשו במה שעדכני בעת כתיבת הקובץ. שדרוג יהפוך אז לעריכה של שורה אחת שביצעתם בכוונה, ושתהיה גלויה ב-git diff.
פרסום ל-127.0.0.1, כי Docker עוקף את ufw
המבנה הוא "127.0.0.1:8080:8080", כתובת מארח, פורט מארח, פורט מכולה. רוב המדריכים כותבים "8080:8080", שזה קיצור ל-0.0.0.0:8080:8080: האזנה בכל הממשקים, כולל הציבורי.
כאן טמון המלכוד, וכולם נתקלים בו פעם אחת. Docker מפרסם פורט על ידי כתיבת חוק DNAT שמשכתב את יעד החבילה ל-IP הפנימי של המכולה לפני הסינון. לכן החבילה עוברת בנתיב FORWARD ולעולם לא מגיעה ל-INPUT, היכן שחוקי ה-ufw שלכם נמצאים. sudo ufw deny 8080 מדווח על הצלחה, ufw status מראה שהפורט חסום, והשירות עדיין עונה לכל האינטרנט. ה-firewall שלכם לא תקול; הוא נעקף כחלק מהתכנון. מדוע Docker עוקף את ufw, וכיצד לסנן תעבורת מכולות באמת מסביר את המנגנון ואת התיקון DOCKER-USER עבור פורטים שחייבים להישאר ציבוריים.
ההרגל שגורם לבעיה להיעלם: קשרו פורטים מפורסמים ל-127.0.0.1 אלא אם יש לכם סיבה ספציפית לא לעשות זאת, והציבו reverse proxy בחזית עבור כל מה שצריך לפנות לעולם. זה בדיוק מה ש-מדריך ה-reverse proxy של Traefik בונה כשלב הבא אחרי דף זה: מכולה אחת שמחזיקה בפורטים 80 ו-443 ומנתבת לכל השאר לפי שם מתחם, עם TLS. (מגיעים מהגדרת Traefik v2 ישנה? ה-מדריך הגירה מ-Traefik v2 ל-v3 מכסה את שינויי השמות והחוקים.)
אמתו את הקישור לאחר הפעלת ה-stack: sudo ss -tlnp | grep 8080 אמור להציג 127.0.0.1:8080, לא 0.0.0.0:8080 או *:8080.
ווליומים בעלי שם לעומת bind mounts
db-data:/var/lib/postgresql/data הוא ווליום בעל שם: Docker יוצר ומנהל ספרייה תחת /var/lib/docker/volumes/ ומעגן אותה לתוך המכולה. החלופה היא bind mount, ./data:/var/lib/postgresql/data, שממפה נתיב שבחרתם במארח.
ההפרדה שעובדת בפועל: ווליומים בעלי שם עבור נתונים שרק מכולות נוגעות בהם, בראש ובראשונה מסדי נתונים, מכיוון ש-Docker מאתחל את הווליום עם הבעלות שה-image מצפה לה והרשאות הקבצים פשוט עובדות. Bind mounts עבור קבצים שאתם נוגעים בהם מהמארח, קובצי תצורה שאתם עורכים עם עורך טקסט, ספריית מדיה שאתם מסנכרנים עם rsync, או כל דבר שהנתיב שלו חשוב לכם. הכשל הקלאסי ב-bind-mount הוא בעלות: המכולה רצה כ-UID 999, ספריית המארח שלכם בבעלות UID 1000, והיישום קורס בהפעלה עם permission denied בלוגים. ווליומים בעלי שם גורמים לסוג זה של באגים להיעלם ברובם, במחיר של אחסון הנתונים בנתיב שמנוהל על ידי Docker, כפי שמוסבר להלן.
environment ו-.env, שמרו סודות מחוץ ל-git
${POSTGRES_PASSWORD} לא נקרא מה-shell שלכם; Compose מבצע אינטרפולציה מקובץ בשם .env שנמצא לצד compose.yml. צרו אותו:
cat > .env <<'EOF'
POSTGRES_PASSWORD=change-me-to-something-long
ADMIN_PASSWORD=change-me-too
EOF
chmod 600 .env
echo ".env" >> .gitignoreצרו ערכים אמיתיים עם openssl rand -hex 24. הקפידו על Hex, לא base64: סיסמה זו נוחתת בתוך מחרוזת החיבור DATABASE_URL, והתווים /, + ו-= ש-base64 מייצר שוברים ניתוח URL. זהו כשל שמופיע כשגיאת אימות, לא כשגיאת תחביר, ועולה בערב שלם של עבודה. שורת ה-.gitignore צריכה להיכנס לפני ה-commit הראשון: קובץ ה-compose בטוח לפרסום ולניהול גרסאות, קובץ ה-.env לעולם לא, וסוד שנגע בהיסטוריית ה-git הוא סוד שצריך להחליף. אם תפעילו את ה-stack כשמשתנה חסר, Compose יזהיר בקול וימשיך עם מחרוזת ריקה, מה שעבור סיסמת Postgres אומר פריסה שבורה:
WARN[0000] The "POSTGRES_PASSWORD" variable is not set. Defaulting to a blank string.docker compose config מדפיס את הקובץ לאחר האינטרפולציה, הדרך המהירה ביותר לבדוק מה המכולות יקבלו בפועל; זכרו שהפלט כולל את הסודות שלכם.
depends_on לא מחכה לכלום, אלא אם מוסיפים healthcheck
depends_on: [db] חשוף שולט רק בסדר ההפעלה: Compose מפעיל את Postgres ראשון ואת היישום רגע אחרי, בזמן ש-Postgres עדיין רחוק שניות מקבלת חיבורים. היישום פונה למסד הנתונים, נכשל, וקורס או מנסה שוב, תלוי באיכות הכתיבה שלו.
הגרסה האמינה היא זו שבה משתמש הקובץ לעיל: שירות ה-db מגדיר healthcheck (Postgres מספק pg_isready בדיוק בשביל זה), והיישום מצהיר על depends_on עם condition: service_healthy. Compose מפעיל את מסד הנתונים, בודק את ה-check כל 10 שניות, ורק אז מפעיל את Miniflux ברגע שהבדיקה עוברת. אם מסד הנתונים לעולם לא הופך ל-healthy (סיסמה שגויה, ווליום פגום), היישום לעולם לא יופעל ו-Compose יגיד לכם איזו תלות נכשלה:
dependency failed to start: container miniflux-db-1 is unhealthyהודעה זו מצביעה על docker compose logs db, שם נמצאת השגיאה האמיתית.
restart: unless-stopped
restart: unless-stopped בשני השירותים אומר שהמכולות יחזרו לאחר קריסה ולאחר אתחול ה-VPS, אך יישארו כבויות אם הרצתם בכוונה docker compose stop. החלופה always מקימה לתחייה מכולות גם לאחר עצירה ידנית, מה שבדרך כלל אינו מה שהתכוונתם אליו. ללא מדיניות restart, אתחול עקב עדכון kernel ב-4 לפנות בוקר יכבה את השירותים שלכם בשקט עד שתבחינו בכך.
הפעלת פקודות יומיומיות
כל הפעולות השוטפות מתבצעות באמצעות חמש פקודות, אותן מריצים מתוך תיקיית הפרויקט.
docker compose up -d # create and start; idempotent, recreates only what changed
docker compose ps # status, ports, and health of this project's containers
docker compose logs -f miniflux # follow one service's logs; --tail 100 for recent history
docker compose pull && docker compose up -d # upgrade to the pinned tags
docker compose down # stop and remove containers and the networkהפקודה up -d בטוחה להרצה חוזרת; היא משווה את קובץ התצורה למצב הקיים ומבצעת שינויים רק בשירותים שהתצורה או ה-image שלהם השתנו. צמד פקודות השדרוג מושך את הגרסאות העדכניות ביותר שאליהן מצביעים ה-tags המוגדרים: עדכוני patch תחת postgres:16-alpine, בעוד שגרסאות עם תיוג מדויק לא ישתנו עד שתעדכנו אותן ידנית – וזו בדיוק המטרה. לאחר שדרוגים מצטברים images ישנים; ניתן לפנות שטח דיסק באמצעות docker image prune -f.
כעת לפקודה ההרסנית, שיש להתייחס אליה בזהירות: docker compose down בטוחה לשימוש, שכן המכולות והרשת ניתנות להקמה מחדש והנתונים שלכם נשמרים ב-volume. הפקודה docker compose down -v מוחקת גם את ה-volumes בעלי השם. המשמעות היא שהמסד הנתונים שלכם יימחק באופן מיידי, ללא בקשת אישור וללא אפשרות שחזור. הדגל -v נועד לפירוק סביבות ניסיוניות; בסטאק שמכיל נתונים אמיתיים, התייחסו אליו כפי שאתם מתייחסים ל-rm -rf. ב-/var/lib/docker/volumes/ אין סל מחזור.
לצורך פתיחת shell חד-פעמי בתוך מכולה רצה: docker compose exec db psql -U miniflux תעביר אתכם למסד הנתונים, ו-docker compose exec miniflux sh תפתח עבורכם shell בתוך היישום.
היכן הנתונים שלכם באמת נמצאים
נפחים בעלי שם (Named volumes) מקבלים את תחילית הפרויקט, כך ש-db-data בתוך תיקייה ששמה miniflux הופך ל-miniflux_db-data:
docker volume ls
docker volume inspect miniflux_db-dataהפלט של inspect כולל את השורה החשובה:
"Mountpoint": "/var/lib/docker/volumes/miniflux_db-data/_data"תיקייה זו היא מסד הנתונים, היא בבעלות root, היא נמצאת על מערכת הקבצים של המארח (host), והיא שורדת down, שדרוגים ובנייה מחדש של מכולות. זהו גם בדיוק המיקום שגיבויים שלכם חייבים לתפוס.
גיבוי של volume בעל שם
התבנית הסטנדרטית היא שימוש במכולה זמנית (throwaway container) הממפה את ה-volume במצב קריאה בלבד (read-only) לצד תיקייה במערכת המארחת, וביצוע ארכיון באמצעות tar:
docker run --rm \
-v miniflux_db-data:/data:ro \
-v "$PWD":/backup \
alpine:3.22 tar czf /backup/miniflux-db-$(date +%F).tar.gz -C /data .אין צורך בהתקנה, שום תהליך לא נשאר רץ, והשחזור הוא פעולת מראה, תוך שימוש ב-tar xzf לתוך volume חדש וריק עם אותם המיפויים בסדר הפוך.
סייג אחד עבור מסדי נתונים: יצירת tar של ספריית נתונים של Postgres בזמן שהיא רצה עלולה לתפוס מצב של כתיבה באמצע, מה שימנע עלייה תקינה של מסד הנתונים. יש לבצע docker compose stop למשך השניות שבהן ה-tar מתבצע, או עדיף מכך, לבצע dump לוגי, שהוא עקבי מעצם הגדרתו:
docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gzהדגל -T מבטל את ה-pseudo-terminal ש-Compose מקצה כברירת מחדל, שכן הזרמת פלט ה-dump דרך TTY עלולה להשחית אותו. הגדירו אחת מפקודות אלו ב-cron והעתיקו את התוצאה מחוץ ל-VPS; גיבוי שנמצא על אותו דיסק של הנתונים שהוא אמור להגן עליהם הוא העתק בלבד, לא גיבוי. ה-מדריך Nextcloud בונה שגרת גיבוי מתוזמנת מלאה המבוססת בדיוק על שתי תבניות אלו.
מצבי כשל והודעות השגיאה הנלוות
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock, אינך חבר בקבוצת docker עדיין, או שאתה חבר בה אך הסשן הנוכחי נפתח לפני העדכון. הפקודה id מציגה את הקבוצות הפעילות שלך; newgrp docker מתקנת את ה-shell הנוכחי, וביצוע logout ו-login מחדש פותר את הבעיה באופן גורף.
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?, בעיה שונה: ה-daemon עצמו אינו פעיל. הפקודות sudo systemctl status docker ו-sudo journalctl -u docker -n 50 יסבירו מדוע. בשרת VPS, הסיבה הקלאסית היא דיסק מלא; בדוק זאת עם df -h /var/lib/docker תחילה.
Bind for 127.0.0.1:8080 failed: port is already allocated, מכולה אחרת כבר תפסה את הפורט המבוקש במארח. הפקודה docker ps תציג איזו מכולה; לעיתים קרובות מדובר במכולה ישנה מניסוי שבוצע לפני docker run שבועות. אם docker ps מציגה רשימה ריקה, ייתכן שתהליך שאינו Docker מחזיק בפורט: sudo ss -tlnp | grep 8080 תציג את שם התהליך.
yaml: line 14: did not find expected key, שגיאת הזחה (indentation) בשורה המצוינת או מעט מעליה. קובצי Compose הם בפורמט YAML: נדרשת הזחה של שני רווחים, שימוש ברווחים בלבד, וכל תו tab בכל מקום בקובץ יגרום לקריסה. הפקודה docker compose config מאמתת את תקינות הקובץ מבלי להפעיל דבר; הרצתה לאחר כל עריכה היא הרגל מומלץ.
ההפתעה של ufw אינה מציגה שגיאה כלל, וזה מה שהופך אותה למסוכנת: הפריסה מצליחה, ufw status נראה תקין, אך סריקת פורטים מבחוץ תחשוף את מסד הנתונים שלך בכל זאת. קרא שוב את סעיף הפורטים לעיל, בדוק כל רשומה ב-ports: עבור קידומת 127.0.0.1: חסרה, ואמת ממכונה אחרת באמצעות curl http://your-vps-ip:8080; התשובה הרצויה היא connection refused.
מכאן, ה-מדריך ל-Traefik יהפוך את ה-stack הבודד הזה למערך של יישומים רבים מאחורי נקודת כניסה אחת ב-HTTPS, ו-מה כדאי לארח עצמאית ב-2026 היא רשימת הקניות להרצה דרכו. ברגע שרצים כמה stack-ים כאלו וכל אחד מהם המציא טופס התחברות משלו, שרת SSO לאירוח עצמי כמו Authentik יאחד אותם חזרה לחשבון אחד מאחורי אותו ה-proxy.
שרת משחק כגון שרת Minecraft על VPS הוא פרויקט Compose ראשון ונוח לתרגול. אם אתם מעדיפים ללמוד באמצעות משהו שאתם פותחים מדי יום, openGym, מעקב אימונים באירוח עצמי הוא stack קטן שמוצמד ל־git tag ולא ל־image tag. לפני רישום ה־passkey הראשון, הוא דורש TLS מלפנים. תמונות הן בדרך כלל הדבר הראשון שאנשים רוצים להחזיר מענן של ספק אחר, ו־השוואה בין PhotoPrism ל־Immich מבהירה מהי כמות ה־RAM המינימלית ומהו נוהל הגיבוי שתאמצו, לפני שתקבעו volume עבור אחד מהם. כאשר שני שירותים כבר אינם מספיקים, הקמת AFFiNE כ־workspace בסגנון Notion משתמשת באותם דפוסים בארבעה containers. זהו מבחן הוגן לשאלה אם הצמדת ה־tags, בדיקות ה־health וה־volumes בעלי השמות שהוזכרו לעיל כבר הפכו להרגל.
FAQ
מדוע אני מקבל את השגיאה "permission denied while trying to connect to the Docker daemon socket"?
המשתמש שלך אינו חבר בקבוצה docker, או שהתווסף אליה לאחר תחילת הסשן הנוכחי; החברות בקבוצה מתעדכנת רק בעת התחברות (login). הרץ את הפקודה sudo usermod -aG docker $USER, לאחר מכן את newgrp docker, או התנתק והתחבר מחדש למערכת, ואמת את השינוי בעזרת id. חברות בקבוצה זו מעניקה הרשאות שוות ערך ל-root על המארח, לכן הוסף רק משתמשים שאתה סומך עליהם ברמת sudo.
האם הפקודה docker compose down מוחקת את הנתונים שלי?
הפקודה docker compose down כשלעצמה אינה מוחקת נתונים; היא מסירה מכולות (containers) ואת רשת הפרויקט. כרכים (volumes) בעלי שם נשמרים, והפקודה up -d הבאה תחבר אותם מחדש. הפקודה docker compose down -v היא הגרסה ההרסנית: היא מוחקת את הכרכים בעלי השם, כלומר את מסד הנתונים שלך, ללא בקשת אישור וללא אפשרות שחזור. לעולם אל תריץ -v על סביבה עם נתונים אמיתיים אלא אם יש בידך גיבוי מאומת.
מה ההבדל בין docker-compose לבין docker compose?
הפקודה docker-compose (עם מקף) היא Compose v1, קובץ בינארי עצמאי מבוסס Python שהגיע לסוף חייו בשנת 2023 ואין להתקין אותו על שרתים חדשים. הפקודה docker compose (עם רווח) היא Compose v2, תוסף Go עבור ה-CLI של Docker, המותקן כחבילת docker-compose-plugin ממאגר ה-apt הרשמי של Docker. הפקודות וקובצי ה-YAML תואמים כמעט לחלוטין, לכן כאשר מדריך ישן מציין docker-compose up, הקלד docker compose up.
מדוע אני יכול לגשת למכולת Docker מהאינטרנט למרות ש-ufw חוסם את הפורט?
מכיוון ש-Docker מפרסם פורטים באמצעות חוקי DNAT בשרשרת PREROUTING של iptables, והחבילות שעברו שינוי עוברות בנתיב FORWARD דרך השרשראות הפנימיות של Docker, הן לעולם לא מגיעות לשרשרת INPUT שבה חלים החוקים של ufw. לכן, ufw deny 8080 אינו משפיע על פורט של מכולה שפורסם. פתור זאת במקור: פרסם פורטים ל-127.0.0.1: בלבד, וחשוף שירותים דרך reverse proxy.
האם עלי להשתמש ב-named volume או ב-bind mount?
השתמש ב-named volumes עבור נתונים שהמכולה ניגשת אליהם בלבד, ובמיוחד עבור מסדי נתונים, כיוון ש-Docker מגדיר את הבעלות כפי שה-image מצפה וההרשאות פועלות ללא הגדרה נוספת. השתמש ב-bind mounts עבור קבצים שאתה מנהל גם מהמארח: קובצי תצורה שאתה עורך, מדיה שאתה מעלה, וכל דבר שהנתיב שלו חשוב לך. אם מכולה נכשלת בעלייה עם שגיאת permission denied ב-bind mount, הדבר הראשון שיש לבדוק הוא אי-התאמה בין ה-UID של המארח לבין זה של המכולה.