Docker Machine คือ tool ที่ใช้สำหรับจัดเตรียม (Provision) docker เป็น virtual hosts บน Mac หรือ Windows รวมถึง ติดตั้งเพิ่ม docker บน Native Linux Host ที่มีอยู่แล้วในเครือข่ายของคุณ ยิ่งไปกว่านั้นยังสามารถจัดเตรียม docker ไปบน cloud providers เช่น Azure, AWS, or Digital Ocean เป็นต้น
Docker Machine จัดการ remote docker host เหล่านี้ด้วยการใช้คำสั่ง docker-machine
การติดตั้ง Docker Machine ขึ้นอยู่กับว่าจะใช้บนระบบปฏิบัติการอะไร ถ้าเป็น Windows ก็ให้ติดตั้ง Docker for Windows ซึ่งจะได้ Docker Engine และ Docker Machine มาด้วยเลย แต่ถ้าระบบปฏิบัติการ Windows นั้นไม่ผ่าน requirements ที่จะรัน Docker for Windows ได้ คุณก็เปลี่ยนไปติดตั้ง Docker Toolbox แทนได้ ซึ่งต้องใช้ร่วมกับ Oracle VM VirtualBox แทน Hyper-V
การใช้งาน Docker Machine จาก Windows ที่ติดตั้ง Docker Toolbox
Docker Machine จะสร้าง VM พร้อมติดตั้ง Docker Engine ให้ด้วย
ตัวอย่างการใช้งาน ทำนองนี้
docker-machine create --driver virtualbox vm1
เมื่อจะเข้าไปใช้เครื่อง vm1 ทำดังนี้
eval "$(docker-machine env vm1)"
และทำคำสั่งอีก 1 คำสั่งตามที่มีข้อความแสดงขึ้นมา
ตอนนี้เราก็สามารถใช้งาน docker ที่เครื่อง vm1 ได้แล้ว เช่น ทดสอบว่า docker ทำงานได้แล้ว
docker run hello-world
ออกโดยใช้คำสั่ง
exit
หรือหากต้องการรันคำสั่งครั้งเดียวที่เครื่อง vm1 โดยไม่ต้องเข้าไป ก็ใช้คำสั่งทำนองนี้
docker-machine ssh vm1 "docker ps"
การติดตั้ง Docker Machine บนระบบปฏิบัติการ Linux
สำหรับการติดตั้ง Docker Machine บนระบบปฏิบัติการ Linux (ทดสอบกับ Ubuntu 16.04 server) จะต้องใช้คำสั่งดังนี้
curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && \ chmod +x /tmp/docker-machine && \ sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
การใช้งาน Docker Machine จาก Linux เพื่อติดตั้ง docker engine ไปบน ubuntu ที่ยังไม่ได้ติดตั้ง docker ไว้ (To provision Docker hosts on remote systems)
จะมีขั้นตอนหลายขั้นดังนี้
1. ที่เครื่องใช้งานที่เราติดตั้ง docker-machine ไว้ ให้เราสร้าง public, private key pair ด้วยคำสั่ง “ssh-keygen -t rsa” และไม่ต้อง protect private key ด้วย password ด้วยนะ เพราะว่า docker-machine ทำงานไม่ได้
2. ส่ง public key ด้วยคำสั่ง “ssh-copy-id” ไปยัง Linux host ที่เราจะจัดการ
3. ที่ Linux host ที่เราจะจัดการ ต้องอนุญาตให้ใช้คำสั่ง sudo แบบ passwordless เพื่อให้ docker-machine สามารถ access เข้าไปได้ ทำด้วยคำสั่ง “sudo visudo” และเพิ่มบรรทัดนี้ต่อท้ายไฟล์
%sudo ALL=(ALL) NOPASSWD:ALL
เพิ่มเติม
หากต้องการใช้ docker-machine จาก Windows ไป provision linux host ก็ให้ก็อปปี้ private key ไปใส่ใน Windows host ก่อนที่จะรัน docker-machine โดยตรวจสอบให้แน่ใจว่า ssh ใช้ key นี้ได้ด้วยคำสั่ง “ssh -i <private key> <userid>@<host>” ซึ่งเป็นการทดสอบว่าเรา ssh เข้าไปยัง Linux host นั้นได้โดยไม่ต้องใส่ password
สำหรับการใช้ Docker Machine เพื่อติดตั้ง docker engine ไปบน cloud providers นั้นก็สามารถใช้ได้ แต่ในเอกสารของ docker แนะนำให้ใช้ Docker Cloud จะดีกว่า เนื้อหาส่วนนี้ผมจะไม่ลงรายละเอียด ให้อ่านเพิ่มเติมจากอ้างอิงด้านล่าง
การใช้งานคำสั่ง docker-machine เพื่อสั่งทำงาน Swarm Cluster
ต่อไปเป็นตัวอย่างที่ประกอบด้วยเครื่องจำนวน 2 เครื่อง เครื่องแรกเป็น swarm manager และเครื่องที่สองเป็น swarm worker ซึ่งเรื่องนี้ เราได้ทดสอบการทำงานแบบ manual ไปแล้วใน “เตาะแตะไปกับ Docker ตอนที่ 3 Swarm” ซึ่งผู้อ่านจะพบว่าในบทความตอนที่ 3 นั้น เราจะต้องแก้ไขชื่อ hostname ให้กับ ubuntu server ที่จะเป็น swarm manager และ ที่จะเป็น swarm worker แต่ตอนนี้ docker-machine จะช่วยเราตั้งชื่อ hostname ในไฟล์ /etc/hosts และ /etc/hostname ให้อัตโนมัติ และติดตั้ง Docker Engine ให้ด้วย
ตัวอย่าง ผมทดสอบด้วย VM จำนวน 3 เครื่อง ใช้ username ชื่อ mama ดังนี้
เครื่อง A
– Ubuntu server
– IP 10.0.2.9
เครื่อง B
– Ubuntu server
– IP 10.0.2.10
เครื่อง C
– Ubuntu server ที่ได้ติดตั้ง docker-machine เพิ่มแล้ว
– IP 10.0.2.11
คำสั่งที่ทำที่เครื่อง A และ B
sudo visudo
เพิ่มบรรทัดนี้ต่อท้าย (ผมใช้ username ชื่อ mama ที่อยู่ใน group sudo ในการรัน docker)
%sudo ALL=(ALL) NOPASSWD:ALL
คำสั่งที่ทำที่เครื่อง C
ssh-keygen -t rsa ssh-copy-id -i ~/.ssh/id_rsa.pub mama@10.0.2.9 ssh-copy-id -i ~/.ssh/id_rsa.pub mama@10.0.2.10 docker-machine create -d generic --generic-ip-address 10.0.2.9 --generic-ssh-user mama --generic-ssh-key ~/.ssh/id_rsa docker-vm1 docker-machine create -d generic --generic-ip-address 10.0.2.10 --generic-ssh-user mama --generic-ssh-key ~/.ssh/id_rsa docker-vm2
ตรวจสอบว่า เรามี machine อะไรบ้าง ด้วยคำสั่ง
docker-machine ls
ผลลัพธ์
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS docker-vm1 - generic Running tcp://10.0.2.9:2376 v17.06.0-ce docker-vm2 - generic Running tcp://10.0.2.10:2376 v17.06.0-ce
เรามาดูกันว่ามันง่ายมาก ๆ เลยครับในการใช้คำสั่ง docker-machine จากเครื่อง C ไปสั่งให้เครื่อง A และ เครื่อง B ทำการรัน application ชื่อ testlab
ที่เครื่อง C เราสั่งคำสั่งนี้ เพื่อให้เครื่อง A เป็น swarm manager
docker-machine ssh docker-vm1 "docker swarm init --advertise-addr 10.0.2.9"
ที่เครื่อง C เราสั่งคำสั่งนี้ เพื่อให้เครื่อง B เป็น swarm worker
docker-machine ssh docker-vm2 "docker swarm join --token SWMTKN-1-61mjquxxkwwkc0tphusc3j98bmhnw5yeh1ykhkp6lp8l8z9em4-46ngusa5zoanprd7042avulpz 10.0.2.9:2377"
ที่เครื่อง C เราสั่งคำสั่งนี้ เพื่อรัน application ชื่อ testlab
docker-machine ssh docker-vm1 "cd ~/myservice ; docker stack deploy -c docker-compose.yml testlab"
ตอนนี้เราก็ได้เปิดบริการ testlab เรียบร้อย
เราจะตรวจสอบดูว่ามี container ถูกรันไว้ในเครื่อง A และ เครื่อง B ดังนี้
docker-machine ssh docker-vm1 "docker ps" docker-machine ssh docker-vm2 "docker ps"
และเมื่อเราต้องการจะ stop application เราก็สั่งดังนี้
docker-machine ssh docker-vm1 "docker stack rm testlab" docker-machine ssh docker-vm1 "docker swarm leave --force" docker-machine ssh docker-vm2 "docker swarm leave --force"
สะดวกมากจริง ๆ ครับ ลองทดสอบใช้งานดูนะครับ
Output ของคำสั่งที่ใช้
mama@ubuntu:~$ curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && chmod +x /tmp/docker-machine && sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 617 0 617 0 0 354 0 --:--:-- 0:00:01 --:--:-- 354
100 25.3M 100 25.3M 0 0 99879 0 0:04:26 0:04:26 --:--:-- 221k
[sudo] password for mama:
mama@ubuntu:~$ docker-machine create -d generic --generic-ip-address 10.0.2.9 --generic-ssh-user mama --generic-ssh-key ~/.ssh/id_rsa docker-vm1
Creating CA: /home/mama/.docker/machine/certs/ca.pem
Creating client certificate: /home/mama/.docker/machine/certs/cert.pem
Running pre-create checks...
Creating machine...
(docker-vm1) Importing SSH key...
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with ubuntu(systemd)...
Installing Docker...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env docker-vm1
mama@ubuntu:~$
mama@ubuntu:~$ docker-machine ls
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
docker-vm1 - generic Running tcp://10.0.2.9:2376 v17.06.0-ce
docker-vm2 - generic Running tcp://10.0.2.10:2376 v17.06.0-ce
mama@ubuntu:~$ docker-machine ssh docker-vm1 "docker swarm init --advertise-addr 10.0.2.9"
Swarm initialized: current node (k8x7e19z0iedo3yfcokeu2jpt) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-61mjquxxkwwkc0tphusc3j98bmhnw5yeh1ykhkp6lp8l8z9em4-46ngusa5zoanprd7042avulpz 10.0.2.9:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
This node joined a swarm as a worker.
mama@ubuntu:~$ docker-machine env docker-vm1
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://10.0.2.9:2376"
export DOCKER_CERT_PATH="/home/mama/.docker/machine/machines/docker-vm1"
export DOCKER_MACHINE_NAME="docker-vm1"
# Run this command to configure your shell:
# eval $(docker-machine env docker-vm1)
mama@ubuntu:~$ docker-machine ssh docker-vm2 "docker swarm join --token SWMTKN-1-61mjquxxkwwkc0tphusc3j98bmhnw5yeh1ykhkp6lp8l8z9em4-46ngusa5zoanprd7042avulpz 10.0.2.9:2377"
This node joined a swarm as a worker.
mama@ubuntu:~$ docker-machine ssh docker-vm1 "cd ~/myservice ; docker stack deploy -c docker-compose.yml testlab"
Creating network testlab_webnet
Creating service testlab_redis
Creating service testlab_web
Creating service testlab_visualizer
mama@ubuntu:~$ docker-machine ssh docker-vm1 "docker ps"
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e50ac8163d9a redis:latest "docker-entrypoint..." About a minute ago Up About a minute 6379/tcp testlab_redis.1.iu0rtua66lrfrzgsdn6vu2kf9
368530178c51 woonpsu/docsdocker:part1 "python app.py" 2 minutes ago Up 2 minutes 80/tcp testlab_web.4.njqokwoqie76knjurptkm35qu
63c811bc1772 woonpsu/docsdocker:part1 "python app.py" 2 minutes ago Up 2 minutes 80/tcp testlab_web.6.urlvghe3yx6p6ljsg5l4x9ix8
130e4967165a woonpsu/docsdocker:part1 "python app.py" 2 minutes ago Up 2 minutes 80/tcp testlab_web.2.020dbtitrcx0b876ryz5xf83r
mama@ubuntu:~$ docker-machine ssh docker-vm1 "docker stack rm testlab"
Removing service testlab_web
Removing service testlab_redis
Removing service testlab_visualizer
Removing network testlab_webnet
mama@ubuntu:~$ docker-machine ssh docker-vm1 "docker swarm leave --force"
Node left the swarm.
mama@ubuntu:~$ docker-machine ssh docker-vm2 "docker swarm leave --force"
Node left the swarm.
References: