SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-08-31

Podman לעומת Docker ב-VPS: מה ההבדלים בפועל?

מה משתנה כשעוברים ל-Podman בשרת VPS? המדריך מסביר איך לעבוד ללא daemon, ניהול הרשאות rootless, הגדרת volumes, שימוש ב-systemd וטיפול בפורטים מתחת ל-1024 ללא Docker.

מה ההבדל בפועל בין Podman לבין Docker

‏Podman ו־Docker מריצים את אותם images בתקן OCI (Open Container Initiative) על גבי VPS, לכן הבחירה אינה נוגעת לתוכנה שניתן להריץ. ההבדל טמון במודל התהליכים. Docker מריץ daemon עם הרשאות root שבבעלותו כל המכולות, והפקודה docker היא לקוח קטן המבקש מאותו daemon לבצע את העבודה. ל־Podman אין daemon: הפקודה podman run מפעילה את המכולה כתהליך בן של מי שקרא לה, תחת המשתמש חסר ההרשאות שלך.

כל השאר נובע מעובדה יחידה זו. הפעלה אוטומטית (auto-start) הופכת למשימה של systemd במקום של ה־daemon. הבעלות על volumes עוברת דרך user namespace, כך שהבעלים שרואים עם ls -l במארח אינם הבעלים שהמכולה רואה. פורטים מתחת ל־1024 יסרבו להיקשר (bind) עד לשינוי הגדרת kernel. ממשק ה־CLI של docker ממשיך לעבוד דרך wrapper, עד לנקודה שבה נדרש ה־socket של Docker.

ללא daemon: מה באמת רץ כשמפעילים מכולה

במארח Docker, הפקודה pstree -a מציגה את dockerd כמשתמש root, את containerd לצידו, ואת containerd-shim-runc-v2 אחד עבור כל מכולה פעילה. היישום שלכם הוא תהליך בן של אותו shim, וה־shim הוא תהליך בן של PID 1. שום דבר לא מחבר את המכולה ל־shell שהפעיל אותה. עצירת ה־daemon גורמת לאובדן מישור הבקרה (control plane) עבור כל המכולות במכונה, וכאשר הגדרת live-restore כבויה, הפקודה systemctl restart docker תפסיק גם את המכולות שלכם.

ל־Podman אין תהליך מקביל. הפעלת מכולה יוצרת תהליך conmon (מנטר מכולה) אחד שמחזיק את התהליך הראשי של המכולה, בבעלות המשתמש שהריץ את הפקודה.

podman run -d --name web -p 8080:80 docker.io/library/caddy:2
ps -o user,pid,ppid,args -C conmon
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080

הפקודה ps אמורה להציג את conmon רץ כמשתמש המחובר שלכם ולא כ־root, והפקודה curl אמורה להדפיס 200. מכיוון שאין שירות מרכזי שבבעלותו המכולה, הפקודה sudo apt upgrade podman לא עוצרת שום דבר שכבר רץ, וקריסה של מנטר מכולה אחד לא יכולה להפיל את האחרות יחד איתו.

היעדר ה־daemon כרוך גם במחיר. שום דבר לא מפעיל את המכולות שלכם לאחר אתחול (reboot). ההגדרה --restart=always של Docker היא הבטחה שה־daemon מקיים בעת העלייה, ו־Podman מחליפה זאת ב־systemd, וזהו הייעוד של סעיף ה-quadlet להלן.

ה־socket הוא החצי השני של הסיפור. /var/run/docker.sock הוא נקודת קצה של API (ממשק תכנות יישומים) בבעלות root, וכל תהליך שיכול לכתוב אליו יכול להפעיל מכולה בעלת הרשאות שמעגנת (mount) את מערכת הקבצים של המארח. הוספת משתמש לקבוצת docker מעניקה לאותו משתמש הרשאות root בדרך עקיפה, נושא שכדאי לקרוא עליו בהרחבה ב-מתן גישה מינימלית לכל חשבון שירות. Podman לא חושפת socket אלא אם תבקשו זאת, וה־socket שתקבלו שייך למשתמש יחיד בנתיב /run/user/<uid>/podman/podman.sock.

התקנת Podman על Ubuntu 24.04 ואימות מצב rootless

sudo apt update
sudo apt install -y podman uidmap
podman --version
podman info | grep -i rootless

החבילה uidmap מספקת את newuidmap ואת newgidmap. אלו הם רכיבי ה-setuid המאפשרים למשתמש רגיל לתבוע טווח של מזהים משניים (subordinate IDs), ובלעדיהם מכולות במצב rootless לא יפעלו. הפקודה podman info אמורה להדפיס rootless: true.

הפצת Ubuntu 24.04 כוללת את Podman 4.9, בעוד Debian 13 כוללת את Podman 5.x, נכון לאוגוסט 2026. לפער זה יש משמעות, כיוון שקבצי quadlet דורשים גרסה 4.4 ומעלה, וקבצי quadlet מסוג .pod דורשים גרסה 5.0. הריצו את podman --version לפני העתקת דוגמאות מתיעוד רשמי.

כל משתמש במצב rootless זקוק לטווח מזהים משניים:

grep "$USER" /etc/subuid /etc/subgid

משתמש שנוצר באמצעות adduser ב-Ubuntu מקבל טווח באופן אוטומטי. משתמש שנוצר באמצעות useradd -M או באמצעות כלי תצורה לעיתים קרובות אינו מקבל טווח כזה, והכשל ידווח בהתאם:

Error: cannot find UID/GID for user deploy: no subuid ranges found for user "deploy" in /etc/subuid - check rootless mode in man pages.

הקצו טווח, ולאחר מכן בצעו איפוס לאחסון של אותו משתמש כדי שהמיפוי החדש ייכנס לתוקף:

sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 deploy
podman system migrate

הפתעה נוספת בהרצה ראשונה: Podman אינו מניח שימוש ב-Docker Hub כברירת מחדל. שם תמונה קצר נפתר מול unqualified-search-registries בתוך /etc/containers/registries.conf, ובסקריפט ללא מסוף (terminal) פעולת ה-pull תיכשל עם short-name resolution enforced but cannot prompt without a TTY. ציינו את השם המלא בכל פעם. השתמשו ב-docker.io/library/nginx:1.27 במקום ב-nginx.

מה באמת משיגים באמצעות מכולות (containers) ללא הרשאות root בשרת שכור

מכולה שרצה ללא הרשאות root פועלת בתוך user namespace, תכונת ליבה (kernel) המעניקה לתהליך מיפוי פרטי משלו של מזהי משתמשים (UID). בתוך ה-namespace, משתמש ה-superuser של המכולה הוא UID 0. מחוצה לו, על גבי ה-VPS שלכם, אותו תהליך הוא משתמש ה-login הרגיל שלכם. משתמש root בתוך המכולה אינו root במערכת המארחת.

זהו היקף היתרון האמיתי. image שמתעקש לרוץ כ-root, יישום אינטרנט עם באג של הרצת קוד מרחוק (RCE), או פריצה (escape) שתלויה בהיותה UID 0 מחוץ למכולה: כל אלו מסתיימים בהחזקת הרשאות המשתמש הלא-מורשה שלכם במקום הרשאות המכונה כולה. מה ש-rootless לא עושה הוא להגן עליכם מפני באגים בליבה, והוא לא מגן על הקבצים שלכם, כיוון שהתהליך שפרץ רץ תחת המשתמש שלכם ויכול לקרוא כל מה שאתם יכולים לקרוא. היחידה שעוברת בידוד חשובה לפחות כמו מיפוי ה-UID, דבר שקל יותר לראות בהשוואה ל-FreeBSD jail, שעוטף סביבת משתמש שלמה שאתם מנהלים כמכונה קטנה ולא כ-image מדורג שנמשך מ-registry.

גם Docker יכול לרוץ ללא הרשאות root. dockerd-rootless-setuptool.sh install מגדיר daemon לכל משתמש וזה עובד היטב. ההבדל הוא לאן מצביעה ברירת המחדל. עם Podman אתם מקבלים rootless ללא בקשה מיוחדת, כך שהכשל הראשון שלכם יהיה מכולה שלא מצליחה לבצע bind לפורט 80, במקום שירות שרץ בשקט כ-root במשך שנתיים.

מדוע קובצי ה-volume שלי שייכים ל-UID 100999?

הסיבה לכך היא אותו מרחב שמות של משתמשים (user namespace). ה-UID 0 של המכולה ממופה ל-UID של המארח. ה-UID 1 של המכולה ממופה למזהה הראשון בטווח ה-subuid שלכם, ומשם הוא עולה בהדרגה. עם טווח שמתחיל ב-100000, ה-UID 1000 של המכולה מופיע על המארח כ-100999.

mkdir -p "$PWD/data"
podman run --rm --user 1000 -v "$PWD/data:/data" docker.io/library/alpine:3 sh -c 'id -u; touch /data/f'
ls -ln "$PWD/data"

המכולה מציגה 1000. רשימת הקבצים במארח מציגה את הבעלים 100999, כיוון ש-100000 ועוד 1000 פחות 1 שווים 100999. שום דבר אינו תקול, ופקודת chown רגילה לא תפתור זאת, כיוון שמשתמש ללא הרשאות root אינו יכול לשנות בעלות על קבצים מחוץ למרחב השמות.

ארבע דרכים לפתרון:

  • podman unshare chown 1000:1000 "$PWD/data" מריצה את ה-chown בתוך אותו מרחב שמות של משתמשים, שבו המספרים מייצגים את מה שהם מייצגים עבור המכולה.
  • -v "$PWD/data:/data:U" מבקשת מ-Podman לתקן עבורכם את הבעלות על תיקיית המקור. השתמשו בה על תיקייה חדשה, לא על נתונים שחשובים לכם.
  • --userns=keep-id ממפה את ה-UID של המארח שלכם לאותו UID בתוך המכולה, כך שקבצים חדשים ייווצרו עם הבעלות שלכם.
  • volume בעל שם כמו -v appdata:/data מונע את הבעיה, כיוון ש-Podman יוצר אותו בתוך האחסון שלכם עם בעלות תקינה מראש.

אם נתקלתם בבעיה זו ב-Docker, מדובר באותה בעיה בשכבה אחת מעל. משתני PUID ו-PGID שדימויים רבים חושפים מגדירים את ה-UID שבו משתמש התהליך בתוך המכולה, ותחת Podman ללא root, ה-UID הזה ממופה פעם שנייה. PUID=1000 בתוך מכולה ללא root עדיין כותב קבצים למארח עם בעלות של 100999. בחרו את המספרים תוך התחשבות במיפוי השני הזה, או העבירו את הנתונים ל-volume בעל שם והפסיקו לעסוק בכך.

שתי הערות נוספות על mount. הדגלים :z ו-:Z שאתם רואים בדוגמאות של Fedora ו-RHEL הם אפשרויות לסימון מחדש של SELinux, ו-Ubuntu משתמשת ב-AppArmor, לכן הם אינם עושים דבר במערכות אלו. בנוסף, Podman ללא root אינו יכול לבצע mount לתיקיית מארח שהמשתמש שלכם אינו יכול לקרוא, וזוהי המטרה ולא תקלה.

מדוע Podman במצב rootless מסרב לפרסם את פורט 80?

מכיוון שקישור (binding) לפורט הנמוך מ-1024 דורש הרשאות שאין למשתמש רגיל. הודעת השגיאה מציינת את הפתרון:

Error: rootlessport cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or choose a larger port number (>= 1024): listen tcp 0.0.0.0:80: bind: permission denied

קיימים שני פתרונות אפשריים. ניתן להנמיך את רף ההרשאות עבור כל השרת:

echo 'net.ipv4.ip_unprivileged_port_start=80' | sudo tee /etc/sysctl.d/99-podman.conf
sudo sysctl --system
sysctl net.ipv4.ip_unprivileged_port_start

הפקודה האחרונה אמורה להחזיר את הערך 80. חשוב להבין את משמעות ההגדרה הזו: כל משתמש במכונה יוכל כעת לבצע bind לפורטים 80 ו-443, ולא רק המשתמש שמריץ את המכולות. בשרת VPS עם מנהל מערכת יחיד, זהו פשרה מקובלת. בשרת שבו קיימים חשבונות משתמשים נוספים, הדבר אינו מומלץ. הפתרון השני הוא לפרסם את השירות בפורט 8080 ולהציב לפניו reverse proxy, שזהו המקום שבו תרצו ממילא להנפיק ולחדש תעודות באמצעות certbot ב-nginx.

פרסום במצב rootless משנה גם את מה שהיישום שלכם רואה. Podman בגרסה 4.x משתמש כברירת מחדל ב-slirp4netns עם ה-port handler של rootlesskit, ולכן חיבורים מועברים מגיעים עם כתובת מקור שעברה שינוי, מה שגורם ללוג הגישה לתעד כל מבקר כ-10.0.2.100. ב-Podman 5.0 שונתה ברירת המחדל ל-pasta, ששומרת על כתובת הלקוח האמיתית. בגרסה 4.x, השימוש ב---network slirp4netns:port_handler=slirp4netns משחזר את כתובת המקור האמיתית, אך במחיר מסוים של ירידה בביצועי התעבורה.

יש כאן הפתעה חיובית אחת. פורט שפורסם במצב rootless הוא socket האזנה רגיל בבעלות תהליך רגיל, ולכן חוקי ה-firewall שלכם חלים עליו. Docker מפרסם פורטים על ידי כתיבת חוקי NAT (תרגום כתובות רשת) בנוסף לחוקי ה-forwarding שלו, וזו בדיוק הסיבה לכך ש-פורט שפורסם ב-Docker מתעלם מחוק ה-ufw שחשבתם שחוסם אותו. Podman עם הרשאות root משתמש במנגנונים דומים ויורש את אותה מלכודת. במצב rootless זה לא קורה.

האם קובצי ה-Docker Compose שלי עדיין עובדים תחת Podman?

ברוב המקרים כן, בשתי דרכים שונות. הראשונה היא podman-compose, מימוש נפרד שקורא את אותו הקובץ ומפעיל את ה-CLI של Podman:

sudo apt install -y podman-compose
podman-compose up -d
podman ps

הדרך השנייה היא שימוש ב-Docker Compose האמיתי, המתקשר עם ה-API התואם-Docker של Podman דרך socket של משתמש:

systemctl --user enable --now podman.socket
export DOCKER_HOST="unix:///run/user/$(id -u)/podman/podman.sock"
docker compose up -d
podman ps

הפקודות docker compose ps ו-podman ps אמורות להציג את אותם המכולות, כיוון שקיימת קבוצה אחת בלבד שלהן. גם פתרון שמות עובד: מנגנון ה-network המובנה של Podman, שנקרא netavark, מריץ את aardvark-dns, כך שמכולות ברשת המוגדרת על ידי המשתמש מוצאות זו את זו לפי שם.

ישנם קצוות מחוספסים. כל מה שמבצע mount ל-/var/run/docker.sock חייב להיות מופנה ל-socket של Podman או להיות מוסר. הפקודה network_mode: host מתנהגת אחרת תחת user namespace. השימוש ב-depends_on עם condition: service_healthy נתמך בצורה לא אחידה בגרסאות השונות של podman-compose. הפקודה restart: always אינה שורדת reboot באופן עצמאי, וזהו נושא שהסעיף הבא פותר. Compose נותר דרך טובה לתאר מערך מכולות מרובה בקובץ יחיד, ותחת Podman הוא משמש כשכבת תרגום. עבור מערך שאתם מתכננים לתחזק במשך שנים, מומלץ להמיר אותו ל-quadlets ולתחזק הפשטה אחת במקום שתיים.

Pods: הרעיון שאין לו מענה ב-Docker

Pod הוא קבוצת מכולות (containers) החולקות מרחב שמות (namespace) רשת יחיד. Podman מפעיל מכולת infra קטנה כדי להחזיק את מרחב השמות הזה פתוח, והחברים בקבוצה ניגשים זה לזה דרך 127.0.0.1 ללא צורך ברשת המוגדרת על ידי המשתמש או במנגנון גילוי שירותים.

podman pod create --name app -p 8080:80
podman run -d --pod app --name app-cache docker.io/library/redis:7
podman run -d --pod app --name app-web docker.io/library/nginx:1.27
podman pod ps
podman ps --pod

הפקודה podman pod ps אמורה להציג את ה-Pod ב-Running עם שלוש מכולות, כולל מכולת התשתית (infra container). כעת, מכולת ה-web ניגשת ל-Redis בכתובת 127.0.0.1:6379 במקום ב-app-cache:6379. שני כללים נובעים ממרחב השמות המשותף: פרסום פורטים מתבצע ברמת ה-Pod ולא ברמת חבר בודד, ואסור לשני חברים להאזין על אותו פורט.

זהו המודל של Kubernetes, ו-Podman מאמץ אותו. הפקודה podman kube generate app > app.yaml כותבת מניפסט של Kubernetes מתוך מה שרץ כרגע (בחבילות ישנות יותר הפקודה היא podman generate kube), והפקודה podman kube play app.yaml משחזרת אותו על מארח אחר. ל-Quadlet יש סוג יחידה .kube שמריץ קובץ כזה כשירות systemd. זוהי דרך שונה מהותית לקבץ שירותים, והיא הסיבה המשכנעת ביותר לבחור ב-Podman אם Kubernetes נמצא בתוכניות העתידיות שלכם.

הפעלה אוטומטית ללא daemon: יחידות Quadlet

Quadlet הוא מחולל עבור systemd. הוא הופך קובץ קצר המתאר מכולה לשירות systemd אמיתי בזמן האתחול. יש למקם את הקבצים ב-~/.config/containers/systemd/ עבור משתמש ללא הרשאות root, או ב-/etc/containers/systemd/ עבור משתמש root.

~/.config/containers/systemd/caddy.container:

[Unit]
Description=Caddy web server
After=network-online.target

[Container]
Image=docker.io/library/caddy:2
ContainerName=caddy
PublishPort=8080:80
Volume=caddy-data.volume:/data
Environment=TZ=UTC
AutoUpdate=registry

[Service]
Restart=always
MemoryMax=512M

[Install]
WantedBy=default.target

~/.config/containers/systemd/caddy-data.volume יכול להיות כמעט ריק, שכן כותרת ה-section היא זו שיוצרת את ה-volume:

[Volume]
systemctl --user daemon-reload
systemctl --user start caddy
systemctl --user status caddy
journalctl --user -u caddy -n 50

שם השירות נגזר משם הקובץ: caddy.container הופך ל-caddy.service. אין להריץ את systemctl --user enable caddy. לא ניתן להפעיל (enable) יחידות שנוצרו באופן זה, ו-systemd ישיב Failed to enable unit: Unit /run/user/1000/systemd/generator/caddy.service is transient or generated.. ה-section מסוג [Install] הוא זה שמפעיל את המכולה בזמן האתחול, ו-daemon-reload הוא הפקודה שמייצרת מחדש את היחידה לאחר עריכת הקובץ.

כעת, ההגדרה שתופסת כמעט את כולם:

sudo loginctl enable-linger deploy
loginctl show-user deploy --property=Linger

צפו ל-Linger=yes. ללא הגדרת linger,‏ systemd מפרק את כל ה-session של המשתמש ברגע שחיבור ה-SSH האחרון נסגר, ולכן כל מכולה שרצה ללא הרשאות root נעצרת יחד איתו ואף אחת מהן לא עולה מחדש באתחול. מכולות שנעלמות בעת התנתקות (logout) הן תמיד תוצאה של הגדרה זו.

מכיוון שהמכולה היא התהליך הראשי של יחידת שירות רגילה, הבקרות של systemd חלות עליה ישירות. MemoryMax= ו-CPUQuota= בתוך ה-section מסוג [Service] מתנהגים בדיוק כפי שהם מתנהגים עבור כל שירות אחר שאתם מנהלים עם systemd. הדבר דורש cgroup v2 (גרסה 2 של control group), שבה משתמשת Ubuntu כברירת מחדל החל מגרסה 22.04. ניתן לאמת זאת עם podman info | grep -i cgroup.

לעדכונים קיים מנגנון תואם. AutoUpdate=registry בצירוף systemctl --user enable --now podman-auto-update.timer בודק מול ה-registry אם קיימת תמונה (image) חדשה יותר באותו ה-tag, מבצע הפעלה מחדש ליחידה, ומבצע rollback לתמונה הקודמת אם המכולה החדשה נכשלת בעלייה. הריצו תחילה את podman auto-update --dry-run כדי לראות אילו שינויים יבוצעו. הפקודה הישנה יותר podman generate systemd עדיין קיימת אך היא מוגדרת כ-deprecated, לכן השתמשו ב-quadlets עבור כל פיתוח חדש.

היכן ה-alias של Docker תקף, והיכן לא

sudo apt install -y podman-docker
sudo touch /etc/containers/nodocker
docker ps

podman-docker מתקין wrapper מסוג /usr/bin/docker שמפעיל את Podman. ללא הקובץ nodocker, כל פקודה תדפיס תחילה Emulate Docker CLI using podman. Create /etc/containers/nodocker to quiet msg.. ה-wrapper מכסה את הפקודות שבהן אתם משתמשים ביומיום: run, ps, logs, exec, build, pull, push, inspect, cp, volume, network.

מה שלא עובר הוא רשימה קצרה יותר, אך חדה יותר. ל-Swarm mode אין מקבילה, לכן ל-stack של Swarm אין לאן להגיע. כלים שמתקשרים עם ה-socket של Docker זקוקים לייצוא של ה-socket של Podman, וחלקם עדיין מבחינים בהבדל; ה-provider של Docker ב-Traefik עובד כאשר מפנים אותו ל-/run/user/<uid>/podman/podman.sock, בעוד של-Watchtower אין תפקיד, כיוון ש-podman auto-update מבצע את העבודה הזו. האחסון נפרד, לכן Podman לא יכול לראות אימג'ים שכבר משכתם עם Docker, והפקודה podman images על מארח Docker עמוס תתחיל ריקה.

הגירה של stack פעיל, צעד אחר צעד

  1. צרו או בחרו משתמש ללא הרשאות root שיחזיק במכולות, וודאו שיש לו טווח ב-/etc/subuid.
  2. משכו מחדש כל רכיב שמגיע מ-registry, תוך שימוש בשמות מלאים. ל-Podman יש מאגר תמונות משלו והוא לא יקרא את זה של Docker.
  3. העבירו תמונות שנבנו מקומית באמצעות docker save app:1.4 | podman load.
  4. עצרו את מכולת ה-Docker, העתיקו את תוכן כל volume מתוך /var/lib/docker/volumes/<name>/_data, ולאחר מכן תקנו את הבעלות על הקבצים באמצעות podman unshare chown -R 1000:1000 <path>.
  5. הכריעו בסוגיית הפורטים: בצעו פרסום בפורט גבוה מ-1024 מאחורי reverse proxy, או הגדירו את net.ipv4.ip_unprivileged_port_start.
  6. כתבו קובץ Quadlet אחד לכל מכולה, הריצו את systemctl --user daemon-reload, והפעילו כל שירות.
  7. הריצו את sudo loginctl enable-linger <user>, בצעו reboot ל-VPS, התחברו מחדש וודאו ש-podman ps מציג את כל השירותים שוב.

שני המנועים אינם חולקים דבר: אחסון התמונות והרשתות נפרדים לחלוטין. לכן ניתן להריץ את שניהם במקביל במהלך ההגירה, והדבר היחיד שהם עלולים להתנגש עליו הוא מספר פורט מארח. העבירו שירות אחד, נטרו אותו במשך יום, ולאחר מכן עברו לשירות הבא.

Podman לעומת Docker: מה מתאים ל-VPS שלך?

הישארו עם Docker אם ה-stack שלכם מבוסס על קובצי compose שאנשים אחרים מתחזקים, או אם אתם תלויים בכלים שמתקשרים עם ה-Docker socket. תאימות למה שכולם כותבים היא תכונה משמעותית, ול-Docker יש יתרון בתחום זה. צוות שכל המחשבים הניידים שלו מריצים Docker מרוויח יתרון מוחשי מהרצת אותו מנוע גם בסביבת ה-production.

עברו ל-Podman אם ה-VPS מריץ מספר מצומצם של שירותים שאתם שולטים בהם מקצה לקצה, או אם אתם מעוניינים שכל יישום ירוץ תחת משתמש ללא הרשאות (unprivileged) ללא קבוצת docker על השרת כלל. גם להתאמה להפצה יש משקל: RHEL והגרסאות המבוססות עליה מספקות את Podman כמנוע הנתמך, ולכן במערכות אלו Podman הוא המסלול עם פחות הפתעות. אם בכל זאת תרצו Docker באחד מהמארחים הללו, נתיב ה-dnf ב-Rocky Linux וב-AlmaLinux מתחיל בהסרת ה-wrapper בשם podman-docker שכבר תופס את הפקודה docker שם. אם אתם כבר מנהלים את כל השאר באמצעות יחידות systemd, ה-quadlets ירגישו כמו חלק חסר שנמצא ולא כמו כלי חדש ללמידה.

אפשרות ביניים אחת ראויה לציון. Podman במצב rootful מתנהג בדומה ל-Docker, שומר על הפקודה docker דרך ה-wrapper, ועדיין מסיר את ה-daemon שרץ תמיד. עם זאת, הוא מוותר על היכולת לרוץ ללא root, שהיא החלק שמשנה את רמת האבטחה שלכם, לכן התייחסו אליו כתחנת מעבר בלבד.

אם אתם עדיין בונים את מארח ה-container הראשון שלכם, נתיב ההתקנה והקשחת ה-Docker ב-VPS חדש הוא הדרך הקצרה יותר, וכל הידע הזה לא ירד לטמיון. Images ו-volumes הם אותם אובייקטים בשני המנועים, כך שמעבר מאוחר יותר ישנה רק את אופן הניהול של השירותים שלכם ולא הרבה מעבר לכך.

FAQ

האם Podman הוא תחליף מלא ל-Docker?

עבור הפקודות שאתם מריצים, הוא קרוב לכך. התקנת podman-docker מספקת מעטפת /usr/bin/docker, והפקודות run, ps, build, logs ו-exec מתנהגות באותו אופן. עם זאת, הוא אינו תחליף ל-daemon. ל-Swarm אין מקבילה, כלים שמתחברים ל-/var/run/docker.sock חייבים להיות מופנים ל-socket של Podman ברמת המשתמש, ותמונות (images) שנמשכו על ידי Docker נשארות בלתי נראות ל-Podman מכיוון ששניהם מנהלים אחסון נפרד.

מדוע מכולות (containers) ב-Podman ללא הרשאות root נעצרות כשאני מתנתק מ-SSH?

מכיוון ש-systemd עוצר את סשן המשתמש, ואיתו את כל שירותי המשתמש, ברגע שההתחברות האחרונה נסגרת. הריצו את sudo loginctl enable-linger <user>, ולאחר מכן ודאו ש-loginctl show-user <user> --property=Linger מציג Linger=yes. הפקודה Linger שומרת על מופע ה-systemd של המשתמש פעיל גם ללא סשן פעיל, וזה גם מה שמאפשר למכולות לעלות מחדש לאחר reboot.

מדוע קבצים ב-volume שלי שייכים ל-UID 100999?

Podman ללא הרשאות root ממפה את UID 0 של המכולה למשתמש המארח שלכם, ואז ממפה את UID 1 ומעלה לטווח ה-subuid שלכם. עם טווח שמתחיל ב-100000, ה-UID 1000 של המכולה הופך ל-100999 במערכת המארחת. תקנו זאת מתוך ה-namespace בעזרת podman unshare chown 1000:1000 /path/to/data, בצעו mount עם הדגל :U בהרצה הראשונה, או השתמשו ב---userns=keep-id כדי ש-UID של המכולה יתאים לשלכם.

האם אני יכול להמשיך להשתמש ב-docker-compose.yml עם Podman?

כן, בשתי דרכים. podman-compose קורא את הקובץ ומפעיל את ה-CLI של Podman ישירות. לחלופין, הפעילו את ה-socket התואם בעזרת systemctl --user enable --now podman.socket, הגדירו את DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock, והריצו docker compose אמיתי מולו. צפו לקשיים ב-network_mode: host, בשירותים שמבצעים mount ל-socket של Docker, וב-restart: always, שדורש יחידת quadlet ו-linger כדי לשרוד reboot.

האם הרצה ללא root באמת הופכת מכולות למאובטחות יותר?

זה מסיר סיכון ספציפי אחד: תהליך שפורץ מתוך מכולה ללא הרשאות root מחזיק בהרשאות המשתמש הבלתי-מורשה שלכם במקום בהרשאות root. זהו יתרון משמעותי, וזו הסיבה שלקבוצת docker, המקבילה ל-root, אין מקבילה ב-Podman ללא הרשאות root. זה לא מונע פגיעויות ב-kernel, וזה לא מגן על קבצים שהמשתמש שלכם יכול לקרוא, לכן המשיכו ליישם את שאר אמצעי ההקשחה שהייתם מבצעים בכל שרת.

#podman#docker#rootless#containers#systemd