איך לארח את Planka עצמאית עם Docker Compose
פרסו את Planka 2 על VPS עם Docker Compose, Postgres ו-Traefik. כך תגדירו את משתני האתחול למנהל ותמנעו משגיאת BASE_URL ששוברת התחברויות.
מה מקבלים מאירוח עצמי של Planka
אירוח עצמי של Planka מספק לצוות לוח Kanban עם מודל של כרטיסים, רשימות ותוויות, כפי שמשתמשים כבר מכירים מ־Trello, והוא פועל על VPS שבשליטתכם. אין מגבלה על מספר המשתמשים ואין חיוב לפי משתמש, משום שהעלות היחידה היא עלות השרת. במדריך הזה נפרוס את Planka באמצעות Docker Compose מאחורי Traefik, עם Postgres עבור הנתונים ועם volume בעל שם עבור כל קובץ שהמשתמשים מעלים.
Planka 2 מופץ תחת Fair Use License של הפרויקט. הפרויקט מתאר רישיון זה כזמינות קוד ולא כקוד פתוח. מותר להפעיל את Planka עבור פרויקטים פנימיים של הארגון שלכם. הפעלתו כשירות אירוח מסחרי עבור צדדים שלישיים מחייבת רישיון Pro או Enterprise.
קהל היעד של המדריך הוא צוות של שניים עד חמישה אנשים שעוזב את השכבה החינמית של Trello. אם אתם עדיין מחליטים באיזה לוח להשתמש, קראו תחילה את ההשוואה בין חלופות Trello באירוח עצמי. המדריך מניח שהבחירה כבר התקבלה, ועוסק רק בפריסה.
נדרש VPS שמריץ Docker Engine עם תוסף Compose, וכן רשומת DNS מסוג A שמפנה אליו. בנוסף, נדרש במחשב זה מופע Traefik שכבר מבצע סיום TLS (אבטחת שכבת התעבורה). אם Traefik עדיין אינו מותקן, הגדירו תחילה reverse proxy של Traefik לפני כמה יישומי Compose, ואם הקובץ שלהלן אינו מוכר לכם, קראו את היסודות של Docker Compose עבור VPS.
כמה VPS נדרש עבור Planka?
הפרויקט אינו מפרסם דרישת חומרה מינימלית, לכן יש להתייחס לכל מספר שקוראים כנקודת התחלה ולא כמדידה. הנתון של 2 vCPU ו־4 GB שחוזר באתרי אירוח הוא ברירת מחדל נוחה של ספק, ולא דרישה שהפרויקט מדד. עבור לוח עבודה שחמישה אנשים משתמשים בו, זו הקצאה נדיבה.
מה שפועל בפועל קטן בהיקפו: תהליך אחד של Node.js שמספק את ה־API ואת ה־frontend שנבנה, ושרת Postgres שמאחסן את הנתונים. שרת זה מפעיל תהליך פיקוח וכן תהליך backend אחד לכל חיבור פתוח. בתוך המכולה של Planka פועל גם תהליך proxy קטן שמסנן את הבקשות היוצאות שלה. תוכנית עם 1 vCPU ו־2 GB מספיקה ללוח עבודה של שניים עד חמישה אנשים, ורוב הזיכרון הפנוי ישמש את Postgres כמטמון. לוח עבודה הוא שכן קל, לכן אם אותו VPS מיועד גם לאחסון מסמכי הצוות, יש להתאים את המשאבים ליישום הזה תחילה: הפעלת AFFiNE כמרחב עבודה בסגנון Notion דורשת בעצמה כמה ג׳יגה־בייטים, עוד לפני ש־Planka זקוקה למשאבים כלשהם.
יש להתאים את נפח הדיסק לפני התאמת הזיכרון, משום שקבצים מצורפים הם הרכיב שגדל. מדדו את המופע שלכם במקום להסתמך על הפסקה הזו:
docker stats --no-stream
docker system df -vהפקודה הראשונה מציגה את הזיכרון ואת ה־CPU בזמן אמת עבור כל מכולה. השנייה מציגה כמה מקום תופס כל volume. בצעו את שתי המדידות לאחר שבוע עבודה רגיל, ולא ביום ההתקנה, משום שלוח עבודה לא פעיל אינו מספק מידע על הצוות שלכם.
כתיבת קובץ Compose
צרו את התיקייה והעבירו את הבעלות עליה, כדי שלא תצטרכו לערוך את הקבצים האלה דרך sudo.
sudo mkdir -p /opt/planka
sudo chown "$USER":"$USER" /opt/planka
cd /opt/plankaצרו את הסודות בקובץ .env לצד קובץ Compose. Compose קורא את הקובץ הזה באופן אוטומטי ומחליף את המשתנים בערכים.
umask 077
{
printf 'SECRET_KEY=%s\n' "$(openssl rand -hex 64)"
printf 'POSTGRES_PASSWORD=%s\n' "$(openssl rand -hex 24)"
printf 'ADMIN_PASSWORD=%s\n' "$(openssl rand -hex 12)"
} > .env
chmod 600 .envopenssl rand -hex מכוון. מחרוזת הקסדצימלית מכילה רק ספרות ואת האותיות a עד f, ולכן היא אינה יכולה לשבש את מחרוזת החיבור של DATABASE_URL שאליה היא מודבקת. סיסמת base64 עם לוכסן או סימן at בתוכה גורמת לשגיאת חיבור שנראית כמו שם מארח שגוי, ועלולה לעלות לכם בשעת עבודה. התבנית הרחבה יותר מוסברת ב־שמירת סודות מחוץ לקובץ Compose.
כעת docker-compose.yml. החליפו את kanban.example.com בשם המארח שלכם בשני המקומות שבהם הוא מופיע.
services:
planka:
image: ghcr.io/plankanban/planka:2.2.1
restart: unless-stopped
volumes:
- planka-data:/app/data
environment:
- BASE_URL=https://kanban.example.com
- DATABASE_URL=postgresql://planka:${POSTGRES_PASSWORD}@postgres/planka
- SECRET_KEY=${SECRET_KEY}
- TRUST_PROXY=true
- DEFAULT_ADMIN_EMAIL=you@example.com
- DEFAULT_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- DEFAULT_ADMIN_NAME=Your Name
- DEFAULT_ADMIN_USERNAME=admin
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.planka.rule=Host(`kanban.example.com`)"
- "traefik.http.routers.planka.entrypoints=websecure"
- "traefik.http.routers.planka.tls.certresolver=default"
- "traefik.http.services.planka.loadbalancer.server.port=1337"
depends_on:
postgres:
condition: service_healthy
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- db-data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=planka
- POSTGRES_USER=planka
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
networks:
- internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U planka -d planka"]
interval: 10s
timeout: 5s
retries: 5
volumes:
planka-data:
db-data:
networks:
proxy:
external: true
internal:כדאי להסביר ארבע החלטות בקובץ הזה, משום שאלו ההחלטות שמשנים לאחר מכן ומתחרטים עליהן.
- בשירות Planka אין בלוק
ports:. Traefik ניגש למכולה דרך רשתproxy, ולכן פורט 1337 לעולם אינו מפורסם על השרת המארח. פרסום הפורט יאפשר לכל אחד לעקוף את ה־proxy ואת התעודה שלכם. loadbalancer.server.port=1337מציין את הפורט בתוך המכולה. Planka מאזין ב־1337, והדוגמה במקור ניגשת אליו דרך 3000 רק משום שהיא ממפה את הפורט לשרת המארח. כאן אין מיפוי לשרת המארח, ולכן יש להודיע ל־Traefik מהו פורט המכולה.condition: service_healthyפועל יחד עם בדיקת התקינות של Postgres. בלעדיו Planka מופעל לפני שמסד הנתונים מקבל חיבורים, נכשל בשאילתה הראשונה ויוצא, כך שהמצב נראה כמו לולאת קריסות. המנגנון מוסבר ב־בדיקות תקינות וסדר הפעלה ב־Compose.- שירות מסד הנתונים נקרא
postgresבכוונה. Planka 2 מנתב את הבקשות היוצאות שלו דרך מסנן פנימי, שרשימת החסימה כברירת מחדל שלו היאlocalhost,postgres. אם תשנו את שם השירות, תסירו את מסד הנתונים שלכם מהרשימה בלי לקבל על כך חיווי ברור.
בדקו ש־Compose יכול לראות את הסודות לפני שתפעילו דבר:
docker compose config | grep -E 'image:|BASE_URL|POSTGRES_USER'הפקודה מדפיסה את הקובץ לאחר שהערכים של .env הוחלפו. ערך ריק פירושו ש־Compose אינו קורא את קובץ .env, בדרך כלל משום שהפקודה מופעלת מתיקייה אחרת.
מה משתני אתחול חשבון המנהל עושים בפועל
מאז Planka 1.13 לא נוצר עבורכם מנהל, ולכן במסד נתונים חדש אין משתמש שיכול להתחבר. הקבוצה DEFAULT_ADMIN_* היא אחת משתי הדרכים לפתור זאת.
בעת האתחול Planka מחפש משתמש שתואם ל־DEFAULT_ADMIN_EMAIL. אם משתמש כזה אינו קיים, הוא יוצר אותו באמצעות הסיסמה, שם התצוגה ושם המשתמש שהוגדרו לצדו. הדבר מתרחש באתחול הראשון מול מסד נתונים ריק, ולכן משתנים אלה מאתחלים חשבון ואינם מנהלים אותו.
ל־DEFAULT_ADMIN_EMAIL יש תפקיד נוסף שלעתים מבלבל משתמשים. כל עוד המשתנה מוגדר, איש אינו יכול לערוך או למחוק מהממשק את החשבון שהוא מציין. זהו מנגנון הגנה מפני נעילה מחוץ לחשבון, וזו גם הסיבה שאי אפשר לשנות בממשק את שם החשבון או את כתובת הדוא"ל שלו. הסירו את המשתנה והפעילו מחדש, והחשבון יהפוך לחשבון מנהל רגיל שאפשר לערוך כמו כל חשבון אחר.
יש להיזהר במיוחד משורת הסיסמה. כל דבר שנמצא תחת environment: ניתן לקריאה לכל מי שיכול להריץ docker inspect במכולה, ולכן DEFAULT_ADMIN_PASSWORD לא צריך להישאר שם לצמיתות. התחברו, שנו את הסיסמה בממשק, מחקו את השורה, ולאחר מכן הריצו שוב את docker compose up -d.
הדרך הנקייה יותר אינה משתמשת במשתנים כלל. השביתו בהערה את כל הקבוצה DEFAULT_ADMIN_*, ולאחר מכן צרו את החשבון באופן אינטראקטיבי:
docker compose run --rm planka npm run db:create-admin-userהפקודה מבקשת כתובת דוא"ל, סיסמה, שם תצוגה ושם משתמש אופציונלי, וכותבת את המשתמש ישירות למסד הנתונים. הסיסמה אינה נכתבת לקובץ Compose או לסביבת המכולה. השתמשו בדרך זו אם ליותר מאדם אחד יש גישה למעטפת אל ה־VPS. הפקודה מפעילה תחילה את Postgres בגלל depends_on, ולכן היא פועלת גם ב־stack שטרם הופעל.
בשתי הדרכים תמשיכו לנהל את הסיסמאות של Planka באופן ידני. עד גרסה 2.1.1, מהדורת Community יכלה להעביר התחברויות לספק OIDC כגון Authentik שפועל אצלכם כשרת כניסה יחידה, אך גרסה 2.2.0, שפורסמה באוגוסט 2026, העבירה את OIDC ואת SSO אל PLANKA Pro. באותה גרסה קיבלה מהדורת Community אימות דו־שלבי (TOTP) לחשבונות מקומיים, ולכן הפעילו אותו לפחות עבור חשבון המנהל.
מדוע BASE_URL גורם לכשל בהתחברות כאשר הוא אינו תואם לשם המארח
BASE_URL הוא הכתובת המדויקת שאנשים מקלידים בדפדפן, כולל הסכמה וללא לוכסן בסוף. עבור המחסנית הזו, הכתובת היא https://kanban.example.com. Planka בונה מהערך הזה את הקישורים שלו ואת חיבור ה־WebSocket, ולכן BASE_URL שגוי אינו מציג שגיאה ברורה. במקום זאת מתקבל דף שנטען, אך הטעינה שלו אינה מסתיימת לעולם.
התרחיש הנפוץ הוא להעתיק את הדוגמה של ספק התוכנה, להשאיר את BASE_URL=http://localhost:3000 במקומו, ולגשת לאתר באמצעות HTTPS בשם המתחם האמיתי. טופס ההתחברות נשלח ופרטי ההתחברות מתקבלים. הלוח אינו מופיע. פתחו את מסוף המפתחים בדפדפן ותראו בקשות אל /socket.io/ שנכשלות, משום שהלקוח קיבל הוראה לפתוח את חיבור ה־live שלו אל localhost:3000, ובמחשב שלכם הכתובת הזו אינה מובילה לשום דבר.
TRUST_PROXY=true הוא החצי השני של אותה בעיה. Planka פועל מאחורי Traefik, ולכן כל בקשה מגיעה אליו מכתובת ה־proxy באמצעות HTTP לא מוצפן בתוך רשת Docker. ללא TRUST_PROXY, היישום מתעלם מהכותרות X-Forwarded-Proto ו־X-Forwarded-For ש־Traefik מגדיר, ולכן הוא סבור שהחיבור אינו מאובטח ומתייחס לכל הלקוחות כאילו הגיעו מאותה כתובת IP. כאשר מגדירים אותו, היישום קורא את הכותרות האלה ומתאם את הסכמה עם הדפדפן.
Traefik מעביר WebSockets ללא תצורה נוספת, וזו אחת הסיבות להעדיף אותו במקרה הזה. ב־nginx, ה־proxy חייב להעביר את כותרות השדרוג, proxy_set_header Upgrade $http_upgrade ו־proxy_set_header Connection "upgrade", אחרת מתקבל אותו מחוון טעינה תקוע, אך מסיבה אחרת. אפשר להגדיר אותן בבלוק הכללי location /; גם בלוק נפרד עבור /socket.io יעבוד, אך אינו נדרש.
העברת הלוח לשם מארח חדש בהמשך מחייבת לשנות שני דברים יחד: את הערך של BASE_URL ואת כלל Host() של Traefik. אם משנים אחד מהם ושוכחים את האחר, חוזרים לאותו מחוון טעינה תקוע. הצגת Planka מתת־נתיב כגון https://example.com/planka נתמכת החל מגרסה 2.1.0, שפורסמה במרץ 2026. בגרסאות ישנות יותר, הקצו לו תת־דומיין משלו.
היכן Planka שומרת קבצים מצורפים ותמונות פרופיל
Planka 2 שומרת את כל הקבצים שמשתמשים מעלים תחת נתיב יחיד בתוך המכולה: /app/data. קבצים מצורפים, תמונות פרופיל של משתמשים ותמונות רקע של לוחות, כולם נמצאים תחת נתיב זה. גרסה 1 השתמשה בשלוש ספריות נפרדות, לכן קובץ Compose שהועתק ממדריך ישן ממפה נתיבים שכבר אינם קיימים, וספריית הנתונים האמיתית נותרת ללא מיפוי (unmounted).
מיפוי יחיד זה הוא ההבדל בין לוח ששורד שדרוג לבין אובדן נתונים. אם /app/data אינו נמצא על volume, העלאות נשמרות בשכבת הכתיבה של המכולה. שכבה זו נמחקת בכל פעם שהמכולה נוצרת מחדש, והמכולה נוצרת מחדש בכל פעם שמשנים את תגית ה-image. הלוח יחזור להיראות תקין, הכרטיסים יהיו שם, אך כל קישור לקובץ מצורף יהיה שבור, כיוון ששורות מסד הנתונים עדיין מצביעות על קבצים שכבר אינם קיימים.
ה-named volume בקובץ ה-Compose לעיל מונע זאת. גם bind mount יעבוד ויקל על גיבוי הקבצים באמצעות כלים סטנדרטיים, אך הוא דורש צעד נוסף. תהליך ה-Node בתוך המכולה רץ תחת UID 1000, לכן ספרייה מארחת (host) בבעלות root תגרום לשגיאת הרשאות בהעלאה הראשונה:
sudo chown -R 1000:1000 /opt/planka/dataהשיקולים בבחירה בין השניים מפורטים ב-bind mounts לעומת named volumes.
אם הקבצים המצורפים חורגים מנפח הדיסק בתוכנית שלכם, Planka יכולה לכתוב אותם לאחסון תואם S3 במקום זאת, באמצעות S3_ENDPOINT, S3_BUCKET ומשתני המפתח התואמים. אלו יכולים להצביע על bucket מאוחסן או על אחסון אובייקטים MinIO בניהול עצמי בשרת אחר. החליטו על כך לפני שהצוות ממלא את הלוח, כיוון שההגדרה חלה על העלאות חדשות בלבד.
הפעלת ה־stack ובדיקת תקינותו
docker compose pull
docker compose up -d
docker compose psdocker compose ps אמור להציג את postgres בתור healthy ואת planka בתור running. אם Planka מופעל מחדש בלולאה, בדקו תחילה את החיבור למסד הנתונים ולא את היישום.
docker compose logs -f plankaבהפעלה ראשונה תקינה מתבצעות מיגרציות של מסד הנתונים, ולאחר מכן השרת מדווח שהוא מאזין בפורט 1337. אשרו שהסכמה אכן נוצרה באמצעות שאילתה ישירה אל Postgres, במקום להסתמך על הלוג:
docker compose exec postgres psql -U planka -d planka -c '\dt'רשימת טבלאות הכוללת את board ואת card פירושה שהמיגרציות התבצעו. ההודעה "Did not find any relations" פירושה ש־Planka לא התחבר מעולם, ולכן השוו את DATABASE_URL לערכים POSTGRES_USER ו־POSTGRES_PASSWORD בקובץ .env שלכם.
לאחר מכן בדקו את הניתוב מהמחשב שלכם, ולא מה־VPS:
curl -I https://kanban.example.comHTTP/2 200 פירושו ש־Traefik מחזיק תעודה ומגיע אל המכולה. תגובת 404 שמוחזרת על ידי Traefik פירושה שאף נתב לא התאים לבקשה: כלל Host() אינו תואם לשם המתחם שביקשתם, או ש־Traefik לא זיהה את התוויות. תגובת 502 פירושה שהנתב התאים, אך Traefik לא הצליח להגיע אל המכולה, למשל משום שהיא אינה מחוברת לרשת proxy. כעת פתחו את האתר והתחברו באמצעות חשבון המנהל.
בצעו pg_dump לפני כל שדרוג גרסה
הלוח שלכם מאוחסן בשני מקורות נפרדים, לכן הגיבוי חייב לכלול את שניהם: מסד הנתונים Postgres ואת ה-volume של planka-data. בצעו dump למסד הנתונים בזמן שה-stack פעיל.
docker compose exec -T postgres pg_dump -U planka -d planka > "planka-db-$(date +%F).sql"השימוש ב--T אינו נתון לבחירה. בלעדיו, Compose מקצה pseudo-terminal, ושכבת הטרמינל משכתבת את תווי סוף השורה בזרם הנתונים. התוצאה היא קובץ dump שייכשל באמצע תהליך השחזור. הכשל יתגלה רק שבועות לאחר מכן, ברגע הגרוע ביותר האפשרי.
לאחר מכן, טפלו בקבצים שהועלו. תחילה, מצאו את השם האמיתי של ה-volume, כיוון ש-Compose מוסיף לו קידומת של שם תיקיית הפרויקט.
docker volume ls | grep planka
docker run --rm -v planka_planka-data:/data -v "$PWD":/backup alpine \
tar czf /backup/planka-files-$(date +%F).tgz -C /data .הפרויקט כולל גם את docker-backup.sh ו-docker-restore.sh במאגר שלו, והתיעוד הרשמי ממליץ להריץ אותם כ-cron job לילי. שתי הגישות תקינות. מה שאינו תקין הוא גיבוי שמעולם לא שוחזר; לכן, שחזרו גיבוי פעם אחת לשרת VPS זמני, וודאו שניתן להתחבר ולפתוח קובץ מצורף. אותם שני מקורות אחסון מופיעים בכל יישום Compose המקבל קבצים להעלאה, כך שאם בהמשך תתקינו Chatwoot על אותו שרת של מערכת התמיכה שלכם, השגרה שתבנו כאן תהיה רלוונטית גם שם, עם שינויים קלים בלבד בשמות ה-volumes.
הריצו את ה-dump מיד לפני כל שינוי גרסה. גיבוי מאתמול בלילה אינו זהה לגיבוי שבוצע לפני המיגרציה שאתם עומדים להריץ.
קיבוע התגיות וקריאת הערות הגרסה
שתי תגיות התמונה בקובץ זה מקובעות בכוונה.
ghcr.io/plankanban/planka:2.2.1 היא גרסה מסוימת, הנוכחית נכון לאוקטובר 2026. latest משתנה בכל פעם שהפרויקט upstream מפרסם גרסה, ולכן docker compose pull שגרתי עלול להכניס migration של schema במועד שלא בחרתם. קראו את הערות הגרסה לפני שאתם משנים את המספר, משום ששם מתועדים שינויים שאינם תואמים לאחור ותיקוני אבטחה. גרסה 2.0.3 פורסמה כגרסת אבטחה, וזה בדיוק סוג המידע שכדאי לקרוא ולא לקבל בטעות. כך גם גרסה 2.2.1, שפורסמה באוגוסט 2026: היא מתקנת פגיעות path traversal שאפשרה למשתמש מחובר לקרוא קבצים שרירותיים במופעים המשתמשים באחסון קבצים מקומי, כפי שמוגדר במדריך זה; ה־advisory מציין שגרסה 2.1.1 ומוקדמות יותר מושפעות. אם אתם מגיעים מ־2.1.x, קראו תחילה את הערות גרסה 2.2.0, משום שגרסה זו משביתה משתמשים שהתחברו אי פעם רק באמצעות SSO, עד שמנהל מערכת מגדיר להם סיסמה. כאן קל לקבע את הגרסה, משום שהפרויקט upstream מפרסם images. כאשר פרויקט אינו מפרסם images, נדרשת אותה משמעת בתוספת שלב, כפי שקורה ב־openGym שנבנה במחשב מהתגית שנשלפה באמצעות git.
postgres:16-alpine מקובעת לגרסה ראשית מסיבה מהותית יותר. Postgres כותב את ספריית הנתונים שלו בתבנית הקשורה לגרסה הראשית, והשרת מסרב לפתוח ספרייה שנכתבה בגרסה ראשית אחרת. אם תכתבו postgres:latest ותאפשרו לתגית לעבור את 16, המכולה לא תופעל. לדוגמה, התמונה של גרסה 17 נעצרת עם:
FATAL: database files are incompatible with server
DETAIL: The data directory was initialized by PostgreSQL version 16, which is not compatible with this version 17.שום דבר אינו אובד, והפעלה מחדש אינה מתקנת דבר. מעבר לגרסה ראשית חדשה של Postgres מחייב dump מהגרסה הישנה ו־restore לספריית נתונים חדשה בגרסה החדשה, או הרצת pg_upgrade, שממירה את הנתונים ללא dump אך דורשת שהבינאריים של השרת הישן והחדש יהיו זמינים יחד. בכל מקרה מדובר במשימה מתוכננת, כשה־stack מושבת, ולא בתופעת לוואי של משיכת image.
אם אתם מעבירים התקנת Planka 1.x קיימת במקום להתחיל מאפס, לשדרוג זה יש נוהל מתועד משלו ב־תיעוד הפרויקט, ואין דרך לחזור לגרסה 1 ללא גיבוי שנוצר מראש.
מצבי כשל והטקסטים שיופיעו
Planka מופעל מחדש בלולאה, והלוג מציין את מסד הנתונים. פרטי הכניסה ב־DATABASE_URL אינם תואמים לסביבת Postgres. שימו לב ש־POSTGRES_PASSWORD מוחל רק כאשר ספריית הנתונים מאותחלת בפעם הראשונה, ולכן תיקון המשתנה לאחר אתחול ראשון שגוי לא ישנה דבר. יש להסיר את אמצעי האחסון db-data ולהתחיל מחדש.
ההתחברות מצליחה, אך הלוח אינו נטען. BASE_URL אינו תואם לכתובת שבשורת הכתובת של הדפדפן, או ש־TRUST_PROXY חסר. קונסולת הדפדפן מציגה בקשות שנכשלו אל /socket.io/.
העלאות נכשלות, אף שכל השאר פועל. נקודת עגינה (bind mount) נמצאת בבעלות root. הריצו sudo chown -R 1000:1000 על הספרייה במארח והפעילו מחדש את המכולה.
קבצים מצורפים נעלמו לאחר שדרוג. /app/data לא היה באמצעי אחסון, ולכן הקבצים נשמרו בשכבת המכולה שהשדרוג החליף. שחזרו את הקבצים מגיבוי, ולאחר מכן הוסיפו את אמצעי האחסון לפני שתשנו שוב את תגית התמונה.
Traefik מחזיר 404. אף נתב לא התאים לבקשה: כלל Host() אינו תואם לרשומת ה־DNS שלכם, או שהתוויות לא הגיעו מעולם אל Traefik. docker compose config מציג את התוויות לאחר החלפה, ושם ניתן לזהות שגיאות הקלדה. 502 מציין במקום זאת שהנתיב התאים, אך לא ניתן היה להגיע אל המכולה, ולכן בדקו שהיא מחוברת לרשת proxy.
התראות או webhooks אינם מגיעים לעולם. Planka 2 שולח את בקשות ה־HTTP היוצאות שלו דרך מסנן פנימי, ורשימת החסימה המוגדרת כברירת מחדל כוללת את localhost ואת postgres. webhook שמופנה אל localhost נחסם בכוונה, ולאחר שתגדירו את OUTGOING_ALLOWED_HOSTS, כל מארח שאינו ברשימה הזו ייחסם גם הוא. הפנו את ה־webhook אל שם השירות של המכולה האחרת, והוסיפו את השם הזה אל OUTGOING_ALLOWED_HOSTS אם אתם משתמשים ברשימת היתרים, במקום להסיר את המסנן.
לאחר שהמערכת פועלת, העומס התפעולי קטן. עקבו אחר הערות הגרסה, וצרו dump של מסד הנתונים לפני כל שדרוג. אתחול מחדש מעלה את ה־stack באופן עצמאי בזכות restart: unless-stopped, כל עוד שירות Docker עצמו מופעל בעת האתחול, והמאמר Stacks של Compose שחוזרים לפעול לאחר אתחול מחדש עוסק במקרים שבהם הוא אינו מופעל.
FAQ
מדוע Planka נטען ללא סוף לאחר ההתחברות?
פרטי ההתחברות התקבלו, אך החיבור החי לא נוצר. Planka בונה את כתובת ה־WebSocket שלו מתוך BASE_URL. לכן, אם המשתנה עדיין מוגדר ל־http://localhost:3000, בעוד שאתם ניגשים לאתר בכתובת https://kanban.example.com, הדפדפן מנסה לפתוח socket לכתובת שאינה קיימת במחשב שלכם. מסוף המפתחים מציג בקשות שנכשלו אל /socket.io/. הגדירו את BASE_URL לכתובת הציבורית המדויקת, ללא לוכסן בסוף, הוסיפו את TRUST_PROXY=true כדי שהיישום יכבד את הכותרת X-Forwarded-Proto מ־reverse proxy, ולאחר מכן הריצו docker compose up -d.
כיצד יוצרים את משתמש הניהול הראשון של Planka?
מאז גרסה 1.13 לא נוצר משתמש מנהל באופן אוטומטי. הגדירו את DEFAULT_ADMIN_EMAIL עם משתני הסיסמה, השם ושם המשתמש התואמים, והפעילו את ה־stack; לחלופין, הריצו docker compose run --rm planka npm run db:create-admin-user וענו על ההנחיות. הפקודה האינטראקטיבית בטוחה יותר בשרת משותף, משום שהסיסמה אינה נכנסת לסביבת המכולה, שבה docker inspect יכול לקרוא אותה. השארת DEFAULT_ADMIN_EMAIL מוגדר לאחר מכן מונעת עריכה ומחיקה של החשבון מהממשק.
היכן Planka מאחסן קבצים מצורפים ותמונות משתמש?
כל הקבצים שהועלו נשמרים תחת /app/data בתוך המכולה ב־Planka 2, כולל קבצים מצורפים, תמונות משתמש ורקעים של לוחות. מפו את הנתיב הזה ל־named volume. אם הוא אינו ממופה, הקבצים נשמרים בשכבת הכתיבה של המכולה ונמחקים בפעם הבאה שהמכולה נוצרת מחדש, דבר שקורה בכל שדרוג של image. גם bind mount מתאים, אך תהליך Node פועל עם UID 1000. לכן הריצו sudo chown -R 1000:1000 על התיקייה במארח, אחרת העלאות ייכשלו בגלל שגיאת הרשאות.
כמה RAM נדרש ל־Planka באירוח עצמי?
הפרויקט אינו מפרסם דרישת חומרה מינימלית. הנתון של 2 vCPU ו־4 GB, שחוזר באתרי אחסון, הוא ברירת מחדל של ספק ולא תוצאה של מדידה, והוא נדיב עבור לוח קטן. עומס העבודה כולל תהליך Node אחד ושרת Postgres, שמפעיל תהליך backend קטן עבור כל חיבור פתוח. לכן חבילה עם 1 vCPU ו־2 GB מספיקה לצוות של שניים עד חמישה משתמשים. הריצו docker stats --no-stream לאחר שבוע עבודה רגיל וקבעו את הגודל לפי הנתונים שלכם. עקבו אחר הדיסק בקפידה רבה יותר מאשר אחר הזיכרון, משום שהקבצים המצורפים הם שגדלים.
כיצד משדרגים את Planka בלי לאבד נתונים?
גבו את מסד הנתונים וצרו ארכיון של אמצעי האחסון של ההעלאות מיד לפני השדרוג, ולא לפי לוח הזמנים של הלילה הקודם. השתמשו ב־docker compose exec -T postgres pg_dump -U planka -d planka > planka-db.sql, והשאירו את -T כדי שה־pseudo-terminal לא ישחית את הפלט המנותב. קראו את הערות השחרור של כל גרסה שעליה אתם מדלגים, שנו את תגית ה־image לגרסה ספציפית במקום latest, ולאחר מכן הריצו docker compose pull ו־docker compose up -d ועקבו אחר הלוג כדי לוודא שההגירה מתבצעת. השאירו את תגית Postgres מקובעת לגרסה הראשית שלה, משום שהשרת מסרב לפתוח ספריית נתונים שנכתבה על ידי גרסה ראשית אחרת.