שילוב מספר מיכלים
פוסט זה כולל טיפ קצר על Docker. אם אתם רוצים ללמוד יותר לעומק על פיתוח עם Docker, Docker Compose או Kubernetes תשמחו לשמוע שבניתי קורס וידאו מקיף בנושא זה.
למידע נוסף והצטרפות לקורס בקרו בדף קורס Docker כאן באתר.
למרות שאנחנו יכולים להרכיב את כל המערכת שלנו לתוך מיכל אחד, בדרך כלל זה לא יהיה הרעיון הכי טוב. כשהמערכת כולה במיכל אחד קשה יותר להעביר סרביס מסוים למכונה אחרת - זה הכל או כלום. בעיה נוספת היא שדרוגים: כשכל הרכיבים של המערכת שמורים באותו מיכל ואתם צריכים לשדרג רק רכיב אחד, תהיו חייבים להוציא גירסא חדשה של המיכל כולו.
ההמלצה בקהילת הדוקריסטים היא לכן להפריד את המערכת שלכם למספר מיכלים, כאשר כל מיכל אחראי על חלק אחר במערכת ויכול תיאורטית לרוץ על מכונה נפרדת. כך בסיס הנתונים ישב במיכל משלו, כל Micro Service יקבל מיכל, רדיס במיכל משלו וגם Memcached במיכל נפרד.
אבל כשאנחנו מפרידים את המערכת שלנו למיכלים אנחנו מייצרים סיבוך אחר: הצורך לארגן את המיכלים יחד לריצה בצורה מתואמת, ולהתמודד עם אילוצים של חלקים שונים במערכת.
ב Docker מיכל שאמור לרוץ בסביבת ייצור כחלק ממערכת גדולה יותר נקרא Service. כמו שהקובץ Dockerfile הגדיר מה יש לנו בתוך מיכל, כך יש קובץ מקביל בשם docker-compose.yml
שאחראי על הגדרת הסרביסים במערכת. לכל סרביס נרצה להגדיר על איזה מכונות מותר לו לרוץ, מהם מיפויי הפורטים שלו ואילוצים שונים של הסרביס (למשל שסרביס מסוים חייב לרוץ על מכונה מסוימת, או לא יכול לתפוס יותר מכמות מסוימת של זיכרון).
1. בואו נבנה קובץ docker-compose לדוגמא
הקלידו את התוכן הבא לקובץ docker-compose.yml
. זה לא משנה באיזה תיקיה תשמרו אותו:
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: ynonp/get-started:part2
deploy:
replicas: 3
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
- "4000:80"
networks:
- webnet
redis:
image: redis
ports:
- "6379:6379"
volumes:
- "/Users/ynonperek/tmp/data:/data"
command: redis-server --appendonly yes
deploy:
replicas: 1
networks:
- webnet
networks:
webnet:
שימו לב לשנות את התיקיה /Users/ynonperek/tmp/data
לאיזושהי תיקיה ריקה על המחשב שלכם.
נראה מה כתבנו כאן:
הקובץ מתחיל בציון מספר גירסא - לתחביר הקובץ docker-compose היו מספר גלגולים והגירסא העדכנית היא מספר 3.
אחרי זה אנחנו ממשיכים להגדיר את הסרביסים שיקחו חלק במערכת שלנו. נתחיל עם הסרביס הראשון והיחיד שנקרא web.
אנחנו מגדירים image שהסרביס יריץ במפתח image.
אנחנו מגדירים מדיניות התקנה לסרביס - במקרה שלנו אני מצפה ליצור 5 מיכלים מאותו אימג', ושכל אחד מהם יקבל עשירית מה CPU וחמישים מגה זיכרון. כל פעם שמיכל מתרסק אני מצפה שהוא יופעל מחדש.
אני מגדיר מיפוי פורטים לאותו סרביס כך שפורט 80 של כל אחד מהמיכלים יופיע ברשת החיצונית בפורט 4000.
אני מגדיר שהמיכלים ישתמשו בהגדרות רשת שנקראת webnet. הגדרה זאת שמופיעה ללא פרטים אומרת שכל המיכלים ישבו מאחורי Load Balancer.
עכשיו ממשיכים להגדרת הסרביס השני, redis. אני מגדיר מיפוי לתיקיה ואת מספר הרפליקות, וגם את רדיס שם על אותה הרשת הפנימית.
אחרי סיום הגדרת הסרביסים אני יכול לבנות הגדרות ספציפיות ל Load Balancer. בינתיים אני משאיר את זה ריק.
2. הפעלת שני הסרביסים שבנינו
אנחנו כמעט מוכנים להפעיל את הסרביסים שלנו. בשביל להפעיל מיכלים מתואמים אנחנו צריכים להשתמש במנגנון נוסף של דוקר שנקרא Docker Swarm. אפשר לחשוב על מנגנון זה כמו מערכת לניהול Service-ים. ה Swarm לוקח את הקובץ docker-compose.yml, מייצר ממנו את כל הסרביסים המתאימים ומחלק את הסרביסים למכונות השונות ברשת.
אני עובד כרגע רק עם מכונת הפיתוח שלי, כלומר מכונה יחידה ברשת, ולכן אסתפק בפקודה הבאה כדי לאתחל את ה swarm עם מכונה בודדת (ובפוסטים הבאים בסידרה נוכל לדבר על הרחבה של המנגנון ושילוב מכונות נוספות):
$ docker swarm init
Swarm initialized: current node (mllwpdgsr5fk7ah037z7hstk4) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-0a7rsj9ryuj40n7csof11097lzdz8okj0m724bdisqvdo52aje-9iypcjhadd3d2ifsglu6oxle7 192.168.65.3:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
עכשיו שיש לנו מכונה נוכל להריץ את docker-compose על המכונה עם:
$ docker stack deploy -c docker-compose.yml helloworld
Creating network helloworld_webnet
Creating service helloworld_redis
Creating service helloworld_web
השם helloworld הוא בחירה שלי. עכשיו בואו נראה את הסרביסים שלנו בפעולה:
$ docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
gjzmfimb4srr helloworld_redis replicated 1/1 redis:latest *:6379->6379/tcp
o8vqg6pejono helloworld_web replicated 3/3 ynonp/get-started:part2 *:4000->80/tcp
ובשביל לראות את פרטי המיכלים עצמם נוכל להפעיל:
$ docker container ls
ID NAME MODE REPLICAS IMAGE PORTS
gjzmfimb4srr helloworld_redis replicated 1/1 redis:latest *:6379->6379/tcp
o8vqg6pejono helloworld_web replicated 3/3 ynonp/get-started:part2 *:4000->80/tcp
localhost:docker ynonperek$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3b1de797b0dd ynonp/get-started:part2 "python app.py" 25 seconds ago Up 22 seconds 80/tcp helloworld_web.1.n5bnb9apc4bq7nco7hmk8me1d
8871f5dbd186 ynonp/get-started:part2 "python app.py" 25 seconds ago Up 22 seconds 80/tcp helloworld_web.2.6xglx5gixsthryfz72bon70iq
59012179c4fa ynonp/get-started:part2 "python app.py" 25 seconds ago Up 22 seconds 80/tcp helloworld_web.3.fzjrphh7fdwx15pl8vzqmpzng
ec546297bbf5 redis:latest "docker-entrypoint.s…" 28 seconds ago Up 27 seconds 6379/tcp helloworld_redis.1.7kqywtqr5jyrydbvjfo3c5sny
ואנחנו רואים את שני האימג'ים רצים, אחד ב-3 מיכלים והשני במיכל יחיד. אפשר גם לנסות לגלוש למחשב המקומי לפורט 4000 ותוכלו לראות את דף האינטרנט מסקריפט הפייתון שלנו.
3. הוספת משאבים
ומה אם רוצים להוסיף עוד שני קונטיינרים שיריצו את הפייתון שלנו? אין בעיה. פשוט מעדכנים את הקובץ docker-compose.yml ומפעילים שוב:
docker stack deploy -c docker-compose.yml helloworld
אם הוספתם מכונות דוקר מספיק חכם בשביל לא לגעת במכונות הקיימות שלכם ורק להוסיף את מה שביקשתם. אם הורדתם מכונות כמובן שהוא יסגור את המכונות שלא צריך.
בשביל למחוק את האפליקציה שיצרתם תוכלו להשתמש בפקודה:
$ docker stack rm helloworld
ובשביל לבטל את כל ה Swarm תוכלו להפעיל:
$ docker swarm leave --force
הדוגמא כאן בפוסט מבוססת על המדריך של דוקר בקישור הזה: