שלום אורח התחבר

הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

מעדיפים לקרוא מהטלגרם? בקרו אותנו ב:@tocodeil

או הזינו את כתובת המייל וקבלו את הפוסט היומי בכל בוקר אליכם לתיבה:

שנים חשבתי ששתי הפקודות זה פשוט שתי דרכים לכתוב את אותה פקודה. לקח לי זמן לשים לב להתנהגויות מוזרות של הכלי ולקשר אותן לפקודה הספציפית אבל כמו הרבה דברים בחיים ברגע שרואים את זה כבר אי אפשר להחזיר את הגלגל לאחור.

הסיפור הרשמי של שתי הפקודות הוא פשוט - הכלי docker-compose הוא סקריפט פייתון, הוא היה שם קודם וקוד המקור שלו (אם מצאתי נכון) הוא כאן: https://github.com/docker/compose.

לעומתו docker compose מסומן בתור compose גירסה 2, כתוב ב go וקוד המקור שלו (בהנחה שמצאתי נכון) הוא כאן: https://github.com/docker/compose-cli.

למרות שהיינו מצפים שאחת הגירסאות תהיה עדיפה על השניה בכל המצבים (כנראה גירסה 2), ולמרות שלפי התיעוד גירסה 2 אמורה לעשות את כל מה שגירסה 1 יודעת לעשות, בפועל ההבדלים בין הגירסאות קיימים ואני עדיין לא מרגיש מוכן לוותר על קומפוז גירסה 1. אלה הדברים המרכזיים שאני שמתי לב אליהם:

  1. גירסה 2, כלומר docker compose תומכת ביצירת קונטיינרים בעננים של מייקרוסופט ואמזון באמצעות אינטגרציה מובנית. מספיק ליצור context, לכתוב docker compose up ויש לכם קונטיינרים באוויר ב ECS או ACI.

  2. על הלינוקס שלי, בגירסה 2 כשאני מעלה מכונות עם docker compose up ואז לוחץ Ctrl+C אני נשאר תקוע על איזה הודעת "המכונות עצרו". בגירסת docker-compose up לחיצה על Ctrl+C עוצרת את המכונות אבל גם מחזירה אותי למסוף.

  3. גירסה 1 כלומר docker-compose תומכת בכתיבת הלוג ל syslog ונראה שגירסה 2 לא. במילים אחרות קובץ קומפוז כזה:

version: '3'
services:
  worker:
    image: // image
    logging:
      driver: syslog
      options:
        syslog-address: "udp://XXX.papertrailapp.com:XXXX"
        tag: "{{.Name}}/{{.ID}}"

שמצאתי כאן בסטאק אוברפלו ובמקומות נוספים יעבוד עם docker-compose up אבל לא יעבוד עם docker compose up.

  1. קומפוז גירסה 2 (הגירסה בלי המקף) תומך ב Apple Silicon.

אם אתם מכירים או מצאתם הבדלים נוספים בין הכלים ורוצים לשתף אני אשמח לשמוע בתגובות.

אתמול פירסמתי מדריך על העלאת קונטיינר דוקר לענן של Microsoft, וכבר כמה אנשים שאלו איך אפשר לפרסם את אותו קונטיינר בענן הגדול יותר של AWS. אז פתחתי את ה AWS CLI וציפיתי להתפנק עם כל הכלים המושקעים של אמזון. לצערי זאת לא היתה החוויה שקיבלתי אבל בכל זאת הצלחתי להגיע לענן וגם לשרוד כדי לספר.

גירסאות עדכניות של docker כוללות מנגנון שנקרא Context. הקונטקסט מספר לדוקר איפה המכונות שצריכות להפעיל את הקונטיינרים יושבות ובאיזה מנגנון אנחנו מדברים עם מכונות אלה (מי ה Orchestrator). לדוקר יש אינטגרציה מובנית עם AWS ועם Azure Devops כך שכל מה שצריך בשביל להעלות קונטיינרים לענן הוא:

  1. ליצור Context ולחבר אותו ל Azure Devops או ל AWS.

  2. להשתמש בפקודות Docker רגילות כדי להפעיל קונטיינרים.

  3. באופן אוטומטי הקונטיינרים ישתמשו בקונטקסט שהגדרנו ויעלו בענן במקום אצלי על המכונה.

ניסוי? בשמחה. אבל קודם נצטרך לעבור את מדיניות האבטחה הדרקונית של אמזון. בתוך קונסולת הניהול יש להיכנס לשירות שנקרא IAM וליצור משתמש חדש. יש במדריך כאן רשימה של כל ההרשאות שאותו משתמש צריך. אני לא מצאתי איך לעשות copy/paste בקלות להרשאות אז בחרתי מרשימת ה Policies מה שנראה לי קשור. סך הכל בשביל משתמש שמצליח להעלות קונטיינרים לענן שלהם הוספתי את ה Policies הבאים:

AmazonEC2FullAccess
IAMFullAccess
AWSAgentlessDiscoveryService
ElasticLoadBalancingFullAccess
AmazonEC2ContainerRegistryFullAccess
AWSCloudMapFullAccess
CloudWatchLogsFullAccess
AmazonECS_FullAccess
AmazonRoute53FullAccess
AWSCloudFormationFullAccess

השיטה של להוסיף הרשאות עד שזה עובד מתאימה לפוסט, אבל לאפליקציה אמיתית כן שווה להתאמץ ולמצוא את ההרשאות המינימליות שאתם צריכים.

אחרי יצירת המשתמש וההרשאות אתם צריכים לחבר אותו לדוקר קומפוז שלכם ובשביל זה נכנסים (עדיין ב IAM) לטאב Security Credentials, בוחרים Create Access Key ומשאירים את החלון עם ה Access Key ID וה Secret פתוח.

משם פותחים בחלון חדש מסוף שורת פקודה ומפעילים משם:

docker context create ecs myawscontext

המילה האחרונה בשורה היא שם ה Context ואפשר לשנות אותה לכל שם שאתם רוצים. בתגובה דוקר ישאל אתכם איך להתחבר ל AWS ואתם תוכלו להגיד לו שיש לכם אסימון גישה ותדביקו את המזהה והסוד במסוף.

בסיום התהליך יהיה לכם Context חדש עבור AWS ואפשר לוודא שזה עבד עם:

$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
myawscontext *      ecs                 (eu-north-1)

שימו לב לשורה השניה מסוג ecs ועם האזור שבחרתם ליצור בו את המכונות.

ההבדל השני בין AWS ל Azure הוא שבעבודה עם AWS חייבים להשתמש ב Docker Compose ולא ניתן להעלות קונטיינר בודד. זה לא סוף העולם כי תמיד אפשר ליצור קובץ docker-compose.yml שמתאים לקונטיינר בודד. הנה הדמו שאני העליתי:

version: "3.9"
services:
  web:
    image: "nginxdemos/hello"
    ports:
      - "80:80"

את התוכן שמרתי בקובץ בשם docker-compose.yml בתיקיה חדשה (זה הקובץ היחיד בתיקיה) והמשכתי להעלות אותו לאמזון עם הפקודה:

$ docker compose up

הפקודה נכשלה באקראי מדי פעם על Timeout-ים, אבל גם לפעמים הצליחה, אז אם אתם מפעילים ומקבלים שגיאה שווה להפעיל פעם שניה בשביל לוודא שזו שגיאה אמיתית. כשהכל עובד תוכלו לראות את התוצאה עם:

$ docker compose ps
NAME                                                 SERVICE             STATUS              PORTS
task/mydockerdemo/cdf554598aab4f1fb3f1685bc074de98   web                 Running             mydoc-LoadB-13SBJMOZQ5M30-224910942.us-east-1.elb.amazonaws.com:80->80/http

שכבר נותן לנו את כתובת המכונה שמריצה את הדמו. גלישה לנתיב שמופיע שם תציג דף פתיחה משרת nginx.

אחרי שהכל עבד אפשר להשתמש ב:

$ docker compose down

כדי להוריד את הסרביסים שיצרתם, או להפעיל מחדש docker compose up כדי להעלות גירסה חדשה.

ממש שמחתי לראות את העבודה הטובה שעשו ב Docker כדי לייצר ממשק זהה להעלאת קונטיינרים למספר ספקי ענן. למרות זאת קשה להתעלם מהעובדה שהגישה לשרתים של Azure היתה קלה ומהירה יותר. גם אם נתעלם מנושא בחירת ההרשאות - ב Azure היה לי הרבה יותר קל למצוא את ה Instances שנוצרו בממשק הבקרה שלהם ולראות סטטוס של המכונות דרך ממשק ה Web. זמני המתנה לפקודות docker היו קצרים יותר ולא נתקלתי בכישלונות אקראיים שהסתדרו מעצמם. אם היתה תחרות בין עננים אז לפחות בצד של ממשק עם דוקר הענן של מייקרוסופט מנצח בגדול.

לפני כמה ימים כתבתי כאן על החשבון החינמי לשנה שפתחתי על Azure Devops, והיום היתה לי הזדמנות לשחק עם עוד מנגנון נחמד של המערכת והוא התקנת קונטיינרים בענן וגיליתי שדוקר כבר עשו בשבילנו את כל העבודה הקשה.

גירסאות עדכניות של docker כוללות מנגנון שנקרא Context. הקונטקסט מספר לדוקר איפה המכונות שצריכות להפעיל את הקונטיינרים יושבות ובאיזה מנגנון אנחנו מדברים עם מכונות אלה (מי ה Orchestrator). לדוקר יש אינטגרציה מובנית עם AWS ועם Azure Devops כך שכל מה שצריך בשביל להעלות קונטיינרים לענן הוא:

  1. ליצור Context ולחבר אותו ל Azure Devops או ל AWS.

  2. להשתמש בפקודות Docker רגילות כדי להפעיל קונטיינרים.

  3. באופן אוטומטי הקונטיינרים ישתמשו בקונטקסט שהגדרנו ויעלו בענן במקום אצלי על המכונה.

ניסוי? בשמחה. בהנחה שיש גם לכם חשבון ב Azure Devops תוכלו להפעיל:

docker login azure

ואז דוקר יפתח דפדפן ויבקש מכם להתחבר לחשבון ה Azure Devops שלכם.

אחרי הכניסה מפעילים את הפקודה:

docker context create aci mycontext

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

$ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT               KUBERNETES ENDPOINT   ORCHESTRATOR
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                         swarm
mycontext *         aci                 yo@centralus

אפשר לראות שיש לי שני קונטקסטים על המכונה: הראשון נקרא default והשני נקרא mycontext.

הפקודה הבאה אומרת לדוקר להתחיל להשתמש בקונטקסט השני:

$ docker context use mycontext

ועכשיו אנחנו מוכנים להרים קונטיינר לענן. הפקודה הבאה יצרה קונטיינר דמו של שרת node.js:

$ docker run -d -p 80:80 nginxdemos/hello

לפי האימג' nginxdemos/hello. כמובן שאתם יכולים לבחור כל Docker Image שתרצו ויש גם תמיכה מלאה ב docker-compose (עליה עוד נדבר בפוסט המשך בעתיד). לפקודת ה run יכול לקחת קצת זמן לסיים לרוץ אבל בסוף זה נגמר ואפשר לראות עם docker ps מה קיבלנו:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             STATUS              PORTS
boring-aryabhata    nginxdemos/hello                        Running             52.182.228.142:80->80/tcp

כניסה לכתובת ה IP של המכונה תציג את דף הכניסה מהאימג', שהוא דף Hello World של שרת nginx.

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

המשך קריאה...

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

בואו נראה כמה דוגמאות בהן אנחנו בונים יישומים מסוגים שונים בתור אימג'ים כדי שלאחרים יהיה קל להתקין ולהפעיל את היישומים שלנו.

המשך קריאה...

אנחנו ממשיכים ברצף של דוקר והפעם נרצה להכיר את הפקודה volume ואיך היא עוזרת לנו בבניית אימג'ים גנריים.

הרבה פעמים אנחנו רוצים להשתמש באותו אימג' למספר מטרות, לדוגמא נרצה לבנות אימג' גנרי של שרת Nginx, ולהשתמש באותו אימג' בכמה מערכות או לכמה אתרים.

באמצעות שמירת הקונפיגורציה וקבצים חשובים מחוץ לאימג' נוכל לבנות אימגים גנריים ולהשתמש בהם בהקשרים שונים. זה הרבה יותר נוח מאשר להכין אימג' שונה לכל סביבה.

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

המשך קריאה...

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

המשך קריאה...

כל מערכת שאתם מפעילים עלולה להגיע למצבים מביכים כשהיא פוגשת את העולם האמיתי. לפעמים עומסים, לפעמים באגים ולרוב שילוב של שניהם יגרמו למערכת שלכם להיתקע או להתרסק. לדוקר יש מנגנון אוטומטי שמזהה נפילות מסוג זה וגם יפעיל מחדש את האפליקציה כשזה קורה כדי שאף אחד לא ישים לב לפאדיחה. זה נקרא Health Check ובוא נראה איך זה עובד.

המשך קריאה...

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

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

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

ב Docker מיכל שאמור לרוץ בסביבת ייצור כחלק ממערכת גדולה יותר נקרא Service. כמו שהקובץ Dockerfile הגדיר מה יש לנו בתוך מיכל, כך יש קובץ מקביל בשם docker-compose.yml שאחראי על הגדרת הסרביסים במערכת. לכל סרביס נרצה להגדיר על איזה מכונות מותר לו לרוץ, מהם מיפויי הפורטים שלו ואילוצים שונים של הסרביס (למשל שסרביס מסוים חייב לרוץ על מכונה מסוימת, או לא יכול לתפוס יותר מכמות מסוימת של זיכרון).

המשך קריאה...

סיבה טובה להתרגש מדוקר היא שעכשיו הרבה יותר קל להתקין תוכנות ועזרי פיתוח אצלכם על המחשב בלי שתצטרכו לחשוש מהתנגשויות בין התוכנות החדשות לבין דברים שכבר מותקנים לכם על המחשב. נראה מספר דוגמאות למכונות שאתם כבר יכולים לקחת ולעבוד איתן.

המשך קריאה...