הסבר התקנה ותפעול של Docker
Docker הוא פלטפורמה של וירטואליזציה, אבל לא במובן שאתם מכירים, כאשר התקנתם לראשונה Hyper-V או vMware הבנתם שאתם יכולים ליצור בתוך במחשב הפיזי שלכם מכונה וירטואלית שתמנהגת בדיוק כמו "עוד" מחשב, כך למעשה לבצע מעבדות והתקנת פלטפורמות כמו לינוקס על מחשב פיזי שהוא ווינדוס.
בעולם הארגוני משתמשים בווירטואליזציה בשביל לחסוך במקום, גמישות מהירות, למשל: ארגון לוקח 10 שרתים ומגדיר 400 שרתים, על ידי כך הוא יכול להגדיל תמיד את הדיסקים באופן דינמיף את הזיכון והמעבד באופן דינאמי, יכולים להשתמש ב Live Migration ובשיטות נוספות שנותנות גמישות בסביבה וירטואלית.
כאשר מתכנת מבקש מאנשי השרתים להקים לו שרת, המתכנת מבקש תחילה הגדרות בסיסיות:
מעבד: 4 ליבות
זיכרון: 8GB
נפח דיסק: 1TB
מערכת הפעלה: Windows Server 2016 או נאמר Centos 7 \ Red Hat
כתובת IP: כתובת שאיתה יוכל לעבוד
ואז המתכנת מתקין את הכלים שלו, ויזואל סטודיו אולי Apache2, אולי TomCat, או .net Framework מתקין הכל ומתחיל לעבוד על התוכנה שהוא צריך לפתח.
אתם בטח שואלים את עצמכם, אז מה הבעיה בתצורה הזו? הכל נשמע מעולה, המכונות הוירטואליות מנצלות את המשאבים כמו שצריך, יש גמישות, המתכנת מקבל שרת באופן מהיר ועולם הוירטואליזציה הרגיל בו VM קיים עובד מעולה! אז נכון, Docker בא לתת הרבה פתרונות למפתחים ואנשי תשתיות ביכולת ההפצה והעבודה.
וירטואליזציה שאנו מכירים נראית לרוב כך:
בתצורה זו אנו מתקינים את ה Hypervisor שהוא Hyper-V או vMware ועליו מכונות, ועל כל מכונה את השירות שאנו רוצים, נאמר
App1 – LAMP (Apache,MySql,PHP)
App2 – Microsoft .Net Framework, IIS
App3 – Microsoft DNS
על כל שרת מותקן שירות אחד וכל אחד מהVM צורך משאבים.
Docker
אז מה הוא בדיוק עושה? Docker משתמש במה שנקרא Container (מכולה בעברית) כל Container מכיל בתוכו אפליקציה (Apache, IIS, DNS וכו') ואותה אפליקציה שנמצאת בתוך המכולה לא יודעת על מכולות אחרות שנמצאות איתה באותו השרת, כך למעשה האפליקציה מבודדת משאר האפליקציות, כל מה שהאפליקציה צריכה, כל התוכנות שהיא צריכה על מנת לעבוד (שירותים, התקנות נלוות וכו') נמצאות איתה בתוך המכולה.
זאת אומרת שאפשר תמיד להזיז את המכולה Container לשרת אחר ושם האפליקציה תעבוד חלק כיוון שברגע שהמכולה עברה , עברו כל התוכנות הנלוות לאפליקציה וכל ההגדרות.
המכולות האלו יושבות בתוך המכונה הפיזית, כך מכונה פיזית אחת יכולה להכיל כמה עשרות של מכולות וכל מכולה עם אפליקציה אחרת לחלוטין ומבודדת לחלוטין מהשאר מבלי להסתמך על השאר.
מייקרוסופט מתארת את זה כך: תארו לכם מכולה אמיתית ובה מטבח, הכנסתם הכל, בלון גז, כיריים,כיסאות שולחנות, מחבת וכו' והנחתם את המכונה הזו על ספינה בשם Ship1 (המכונה הפיזית) עכשיו אתם רוצים להזיז את המכולה לספינה אחרת ושהמטבח שלכם יתפקד בדיוק כמו שהוא היה ב Ship1, אין שום בעיה.
העבירו את המכולה עם המטבח מ Ship1 לספינה Ship2 והמכולה והתוכן שלה (האפליקציה) לא מודע בכלל שהזיזו אותה.
ה Docker מנהל את ה Container, את ה Container ניתן להוריד מהDocker Hub, נוכל להוריד Container שמכיל Apache ופועל איתו, רק נצטרך להגדיר כמה הגדרות בסיסיות כמו כתובת IP וכו' ואז ה Container רץ ומספק את השירות שהוא אמור לספק, כך למעשה הוא מבודד משאר ה Containers ששוכנים במכונה הפיזית.
מונחים ב Docker
Docker בנוי מ3 שכבות:
- Container – המכולה עצמה שמכילה את האפליקציה עצמה
יוצרים את קבצי הבסיס של ה Image, של האפליקציה שלכם ואז מכניסים אותה לתוך Image, את ה Image אפשר להריץ, אפשר לשנות, אפשר ל"דחוף" ל Docker Hub ולתת גם לצוות שלכם או לאנשים אחרים להוריד - Services – השירותים בתוך ה Container שהאפליקציה מסתמכת עליהם
נאמר שיש לכם Image, כעת אתם רוצים להריץ את ה Image בתצורת Cluster כך שיש Load Balance בין 10 "מכולות" אז ניתן לייצר שירות כזה או אפילו שירות נוסף לזה שמציג לי את כל המכולות והכתובות שלהם - Stack – מה שמאחד את האפליקציה והשירותים לכדי תצורה אחת ומפעילה את כל המכולה
ה Docker מכיל את הפקודה docker שאיתה נשתמש על מנת לתפעל את המערכת, למערכת יש 4 כלים:
- Image – סוג של VM מוכן שאותו ניתן להריץ בתוך Container ניתן לכבות אותו ולדחוף אותו ל Docker Hub שם מתכנתים אחרים יכולים להוריד אותו או להריץ את המכונה ישר משם
- Container – ברגע שמריצים את ה Image (מה שמכיל את האפליקציה) נוצר "מכולה" ובתוכה האפליקציה רצה
- Network – כלי הרשת, כך למעשה נגדיר ונחבר את המכונה לכתובת IP מסוימת שיהיה ניתן להגיע אל הContainer
- Data Volumes – איפה שה Container רץ, ככל שהוא גדול יותר כך יותר נפח של אחסון אנחנו נצטרך
Install Docker
אנחנו נתקין את Docker CE ל Centos 7 ולכן הדרישות:
- CentOS 7 מעודכן
- Windows 10 על מנת לבדוק את ה Apache ושאר ההגדרות
נפתח את הטרמינל
הגדירו Repository
[root@localhost ~]# sudo yum install -y yum-utils \
device-mapper-persistent-data \
lvm2
נגדיר Repo נוסף
[root@localhost ~]# sudo yum-config-manager \
–add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
כעת נתקין את Docker
[root@localhost ~]# sudo yum install docker-ce
כעת נפעיל אותו
[root@localhost ~]# sudo systemctl start docker
נאפשר אותו בעלייה הבאה
[root@localhost ~]# sudo systemctl enable docker
נשתמש בפקודה Hello לראות שהכל תקין ואנחנו מקבלים הודעת ברוך הבא:
[root@localhost ~]# docker run hello-world
3
על מנת לבדוק גירסה נריץ את הפקודה
[root@localhost ~]# docker –version
יצירת Image
בתיקייה הראשית של לינוקס ניצור תיקייה בשם docker
[root@localhost ~]# mkdir docker
נכנס אל התיקייה
[root@localhost ~]# cd docker
ניצור את הקובץ
[root@localhost ~]# vi Dockerfile
נכניס לקובץ
# Use an official Python runtime as a parent image
FROM python:2.7-slim
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
ADD . /app
# Install any needed packages specified in requirements.txt
RUN pip install –trusted-host pypi.python.org -r requirements.txt
# Make port 80 available to the world outside this container
EXPOSE 80
# Define environment variable
ENV NAME World
# Run app.py when the container launches
CMD ["python", "app.py"]
נשמור וצא
כעת ניצור קובץ נוסף
[root@localhost ~]# vi requirements.txt
נכניס
Flask
Redis
נשמור ונסגור
כעת ניצור קובץ נוסף
[root@localhost ~]# vi app.py
כעת נכניס
from flask import Flask
from redis import Redis, RedisError
import os
import socket
# Connect to Redis
redis = Redis(host="redis", db=0, socket_connect_timeout=2, socket_timeout=2)
app = Flask(__name__)
@app.route("/")
def hello():
try:
visits = redis.incr("counter")
except RedisError:
visits = "<i>cannot connect to Redis, counter disabled</i>"
html = "<h3>Hello {name}!</h3>" \
"<b>Hostname:</b> {hostname}<br/>" \
"<b>Visits:</b> {visits}"
return html.format(name=os.getenv("NAME", "world"), hostname=socket.gethostname(), visits=visits)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=80)
נבצע
[root@localhost ~]# ls
והקבצים
Dockerfile app.py requirements.txt
כעת ניצור את ה Image
[root@localhost ~]# docker build -t friendlyhello .
כעת הפקודה תציג לנו איזה images יש לנו
[root@localhost ~]# docker images
friendlyhello latest 49fec906253c 23 hours ago 148MB
נוכל להריץ את ה Container בSession הנוכחי
בתצורה של 4000:80 זה אומר שפורט 4000 יפנה לפורט 80 שהוא פורט http (אל תריצו עדיין בתצורה זו אלא בתצורה הבאה שהיא עם -d)
[root@localhost ~]# docker run -p 4000:80 friendlyhello
נריץ ברקע על ידי -d שהוא מצב detached mode
[root@localhost ~]# docker run -d -p 4000:80 friendlyhello
כעת נבדוק שהוא רץ ברקע על ידי הפקודה
[root@localhost ~]# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
2cde3fed512c friendlyhello "python app.py" 9 seconds ago Up 9 seconds 0.0.0.0:4000->80/tcp silly_roentgen
נפתח ב Firewall את הפורט 4000 ואת פורט 80 ואת 8080 להמשך המדריך
[root@localhost ~]# firewall-cmd –permanent –zone=public –add-port=80/tcp
[root@localhost ~]# firewall-cmd –permanent –zone=public –add-port=4000/tcp
[root@localhost ~]# firewall-cmd –permanent –zone=public –add-port=8080/tcp
כעת נרשום בדפדפן את הכתובת IP עם הפורט 4000
3
תוכלו לראות שהוא רושם את ה ID של ה Container
נוכל לעצור את ה Container
[root@localhost ~]# docker container stop 2cde3fed512c
ונוכל להריץ אותו חזרה
[root@localhost ~]# docker container start 2cde3fed512c
התחברות ל Docker HUB ושמירת ה Image אליו
תחילה נירשם ל Docker HUB בקישור הבא
https://hub.docker.com/
לאחר ההרשמה נלחץ על Create Repository וניתן שם ל Repo שלנו נאמר new
6
כעת נתחבר ל Repo שלנו
[root@localhost ~]# docker login
נזין את שם המשתמש והסיסמא שלנו
כעת ניתן TAG שזה השם שיעלה ל Repo שלנו
[root@localhost ~]# docker tag image username/repository:tag
זה יראה כך
[root@localhost ~]# docker tag image tal221/new:friendlyhello
כעת נבנה את ה Image שנוכל לעלות אותו
[root@localhost ~]# docker build –tag tal221/new:friendlyhello .
כעת נעלה אותו
[root@localhost ~]# docker push tal221/new:friendlyhello
נוכל אפילו להריץ אותו מתוך ה Repo
[root@localhost ~]# docker run -p 4000:80 tal221/new:friendlyhello
בניית Service והרצתו
כעת נבנה Service שירציץ את ה Image שלנו כפול 5 על מנת ליצור יתירות
ניצור קובץ בשם
[root@localhost ~]# vi docker-compose.yml
נכניס את
אחרי זה שנו את username/repo:tag למשתמש שלכם וה Image שלכם
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure
ports:
– "80:80"
networks:
– webnet
networks:
webnet:
על מנת להריץ את המנגנון של Load Balance נריץ
[root@localhost ~]# docker swarm init
כעת ניתן שם לאפליקצית השירות שלנו
[root@localhost ~]# docker stack deploy -c docker-compose.yml getstartedlab
כעת נבדוק שהוא רץ
[root@localhost ~]# docker service ls
נוכל לבדוק גם על ידי הפקודה
[root@localhost ~]# docker service ps getstartedlab_web
ועל ידי הפקודה נוכל לראות את ה Containerים שרצים
[root@localhost ~]# docker container ls -q
כעת שתיכנסו לאתר בפורט 80 תראו שה Hostname משתנה כל הזמן שכל פועלים 5 Container בו זמנית
נוכל לשנות את כמות ה Container בקובץ docker-compose.yml ואז שוב להריץ
[root@localhost ~]# docker stack deploy -c docker-compose.yml getstartedlab
נוכל לסגור את ה swarm שהגדרנו על ידי
[root@localhost ~]# docker stack rm getstartedlab
ולהגדיר יציאה של ה docker על ידי הפקודה
[root@localhost ~]# docker swarm leave –force
Stacks
נוכל להריץ שירות שגם יריץ לנו 5 שכפולים של ה Container וגם אתר שיציג לנו את השכפולים, נערוך שוב את הקובץ
[root@localhost ~]# vi docker-compose.yml
נמחק את מה שכתוב ונכניס
version: "3"
services:
web:
# replace username/repo:tag with your name and image details
image: username/repo:tag
deploy:
replicas: 5
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.1"
memory: 50M
ports:
– "80:80"
networks:
– webnet
visualizer:
image: dockersamples/visualizer:stable
ports:
– "8080:8080"
volumes:
– "/var/run/docker.sock:/var/run/docker.sock"
deploy:
placement:
constraints: [node.role == manager]
networks:
– webnet
networks:
webnet:
נשמור ונריץ את הפקודה
[root@localhost ~]# docker stack deploy -c docker-compose.yml getstartedlab
כעת ניכנס לאתר עם הפורט 8080
http://192.168.1.122:8080
נוכל לראות את ה Container שרץ
7
ואם נכנס לאתר הרגיל
[root@localhost ~]# http://192.168.1.122/
נראה שהאתר עלה ונוכל לבצע ריסטרט על מנת לראות שאנחנו מגיעים כל פעם ל Container אחר
במאמר הבא נגדיר שרת Apahce דרך Container