สวัสดีครับ บทความนี้ผมจะพูดถึงเรื่อง Docker compose ซึ่งผมมองว่ามันเป็นหัวใจหลักของ Docker เลยก็ว่าได้เพราะมันจะช่วยให้การจัดการ Docker ทั้ง project ของเราเป็นเรื่องง่าย ก่อนที่จะอ่านบทความนี้จะต้องรู้ใน
เรื่องของ docker image, docker container และมีความเข้าใจเรื่อง Docker มาบ้างแล้ว ไม่งั้นเดี๋ยวจะงง
Docker Compose คืออะไร
จากก่อนหน้านี้เวลาเราจัดการ Docker Container ไม่ว่าจะเป็นการ Start, Stop, volume ฯลฯ เราจะใช้คําสั่ง docker … ซึ่งจะเป็นการจัดการ Docker Container เพียงตัวเดียวเท่านั้น ถ้ามีหลาย Container ก็ต้องจัดการทีละ Container ถ้าใช้งานโดยทั่วไป Container ไม่เยอะก็ไม่มีปัญหาอะไร แต่ถ้า Project ไหนที่มี Container เยอะๆ จะเป็นเรื่องยากที่เราจะจัการ Container ได้ทั้งหมด Docker Compose จะมาช่วยให้เราสามารถจัดการ Container ทั้งหมดให้เป็นเรื่องง่าย โดยการควบคุม Container ทั้งหมดจะอยู่ใน file docker-compose.yml ส่วนรายละเอียดของ file docker-compose.yml ผมจะพูดในหัวข้อท้ายๆครับ หลังจากที่ทําความเข้าใจเกี่ยวกับ Docker Compose แล้ว เพื่อให้เข้าใจมากขึ้นเรามาทํา Workshop กันครับ
ภาพรวมของ Workshop
ใน Workshop นี้เราจะสร้างเว็บขึ้นมา 3 หน้า(ใช้ nginx+nodejs) ดังนี้
- หน้า hello world (กําหนดให้เรียกเว็บโดยใช้ url นี้ http://ip_server)
- หน้า hello nodejs 1 (กําหนดให้เรียกเว็บโดยใช้ url นี้ http://ip_server/node1)
- หน้า hello nodejs 2 (กําหนดให้เรียกเว็บโดยใช้ url นี้ http://ip_server/node2)
ซึ่งเราจะออกแบบโดยมี Container ดังนี้
- **lb **ทําหน้าที่เป็น load balance และหน้า hello world โดยจะสร้าง Image จาก Docker Image ของ nginx
- nodejs1 เป็น Container ของหน้า hello nodejs 1 โดยจะสร้าง Image จาก Docker Image ของ nodejs
- nodejs2 เป็น Container ของหน้า hello nodejs 2 โดยจะสร้าง Image จาก Docker Image ของ nodejs
โครงสร้างความสัมพันธ์ของแต่ละ Container มีดังนี้
ในการใช้งาน Docker Compose สามารถทําได้หลายรูปแบบ ในบทความนี้ผมจะออกแบบโครงสร้างของ ไฟล์ต่างๆดังนี้
-[workshop-docker-compose]
+-[build]
| +-[lb]
| | |-dockerfile
| | └ default.conf
| |
| +-[nodejs1]
| | |-dockerfile
| | └ hello.js
| |
| +-[nodejs2]
| |-dockerfile
| └ hello.js
|
+-[src]
| +-[lb]
| └ index.html
|
└ docker-compost.yml
จากโครงสร้างของไฟล์ด้านบน ผมจะแยกเก็บข้อมูลเป็นส่วนๆดังนี้
- build ใน folder นี้ ผมจะเก็บ dockerfile สําหรับสร้าง Docker Image ที่ผมต้องการ ในบทความนี้ผมจะสร้าง Dcoker image ของ lb (nginx), nodejs1 (nodejs), nodejs2 (nodejs) ขึ้นมา
- src ใน folder นี้ ผมจะเก็บพวก Source code หรือ resource ต่างๆ ที่เราจะ map volume มาจาก container ตัวอย่างในบทความนี้ผมจะ map volume จาก หน้า index ของ nginx (lb container) มาที่ “src/lb/”
จะเห็นว่าผมสร้าง dockerfile ขึ้นมา 3 file แยกไว้ตาม folder ต่างๆ ทั้งสามไฟล์นี้จะทําหน้าที่สร้าง Docker Image ของแต่ละ Container และไฟล์อื่นๆที่ผมสร้างขึ้นมีหน้าที่ดังนี้
- hello.js จะเป็น Source code ของ nodejs ที่ทําหน้าที่แสดงหน้าเว็บของ nodejs1 และ nodejs2
- default.conf เป็นไฟล์ config ของ nginx
- index.html เป็นหน้า index ของ lb (nginx)
- docker-compose.yml เป็น file Docker Compose ที่เราจะเขียน script ลงไปเพื่อบอกคุณสมบัติ และความสัมพันธ์ของแต่ละ Container
หัวใจหลักของ Docker Compose จะอยู่ที่ไฟล์ docker-compose.yml ซึ่งภายในจะเป็น script ที่ระบุคุณสมบัติต่างๆ และความสัมพันธ์ของ Container ทั้งหมดของระบบ
Install Docker Compose
มา Install Dcoker Compose กันก่อนครับ ทําตามวิธีนี้ได้เลยครับ คําสั่งในการ Install คือ
curl -L https://github.com/docker/compose/releases/download/1.8.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
ต่อไป กําหนดสิทธิให้สามารถ Execute ได้ ใช้คําสั่งนี้
chmod +x /usr/local/bin/docker-compose
เมื่อทุกอย่างเรียบร้อย ก็ทดสอบการ install โดยการ check version
docker-compose --version
จะได้ประมาณนี้
docker-compose version: 1.8.0
เริ่มทํา Workshop
ในหัวข้อนี้เราจะมาลองเล่นกันก่อนว่า Docker Compose มันดีอย่างไง มันช่วยให้ชีวิตดีขึ้นหรือไม่ โดยผมสร้าง Workshop ไว้แล้วอยู่บน github ซึ่ง Workshop นี้จะมีการทํางานและโครงสร้างตามที่ผมบอกไปในหัวข้อ ภาพรวมของ Workshop เริ่มแรกเข้าไปโหลด workshop มาก่อนครับ ที่นี่ครับ github.com/mrthiti/workshop-docker-compose.git หรือจะ clone โดยใช้คําสั่งนี้
git clone https://github.com/mrthiti/workshop-docker-compose.git
เราจะได้โฟลเดอร์ workshop-docker-compose มา ให้เราเข้าไปในโฟลเดอร์ workshop-docker-compose แล้วใช้คําสั่ง
docker-compose up -d --build
เมื่อเราใช้คําสั่งนี้แล้ว ระบบจะทําการสร้าง Image ต่างๆ ตามที่เราเขียน script ไว้ในไฟล์ docker-compose.yml แล้วก็ทําการ run container ให้เราด้วย ซึ่งใน Workshop นี้หลังจากที่เรียกคําสั่งนี้ไป เราจะได้เว็บตามที่เราออกแบบไว้ทุกประการ ทดลองผลการรันคําสั่งโดยทําตามนี้ ลองเข้าไปที่ http://your_pi_server:3000/ เราจะได้
ลองเข้าไปที่ http://your_pi_server:3000/node1 เราจะได้
ลองเข้าไปที่ http://your_pi_server:3000/node2 เราจะได้
เห็นมั้ยครับเราใช้คําสั่งเพียงคําสั่งเดียว (docker-compose up -d —build) สามารถที่จะรันเว็บของเราได้ทั้งเว็บ และอีกอย่างคือ ผมสามารจะนําไปรันบนเครื่องใดก็ได้ ถ้าต้องการ stop container ทั้งหมดก็สามารถใช้คําสั่งนี้ได้เลยครับ
docker-compose down
ในหัวข้อถัดไปเราจะมาดูวิธีการเขียน Script ของ docker compose กันครับ
วิธีการเขียน script ของ Docker Compose
การเขียน script ของ Docker Compose นั้นคือ การเขียนบอก Docekr Compose ว่า เราจะสร้าง image อะไรบ้าง และ image ต่างๆมันมีความสัมพันธ์กันอย่างไร โดยเราจะเขียนไว้ในไฟล์ docker-compose.yml เรามาดูตัวอย่างพื้นฐานการเขียนกันครับ (จากไฟล์ docker-compose.yml ของ workshop)
version: "2"
services:
lb:
build: ./build/lb
container_name: lb
volumes:
- ./src/lb:/usr/share/nginx/html
links:
- nodejs1
- nodejs2
ports:
- 3000:80
nodejs1:
build: ./build/nodejs1
container_name: nodejs1
nodejs2:
build: ./build/nodejs2
container_name: nodejs2
ผมจะอธิบายคําสั่งต่างๆดังนี้ครับ
- version: คือ ส่วนหัวที่จะไว้บอกว่าเป็น script version ไหน โดยปกติจะใช้ version 2
- service: คือ ส่วนของการประกาศ service ต่างๆ โดยในตัวอย่าง จะมี service ดังนี้
- lb
- nodejs1
- nodejs2
- build: คือ ให้ทําการสร้าง Docker Image โดยจะระบุ path ที่อยู่ของ dockerfile
- image: คือ ระบุว่า service นี้จะใช้ image อะไร
- container_name: คือ ระบุชื่ของ container
- links: คือ การระบุว่า service นี้เชื่อมต่อกับ service ไหนบ้าง หรืออีกในนึงก็คือ การเชื่อมต่อ Container เข้าด้วยกันนั่นเอง
- ports: คือ การบอกว่า service หรือ Container นี้ map port อะไรบ้าง (เหมือน option -p ในคําสั่ง docker run -p)
คําสั่งต่างๆใน Workshop นี้เป็นส่วนหนึ่งครับ ยังมีคําสั่งอื่นๆอีก โดยเราสามารถจะศึกษาเพิ่มเติมได้ที่ docs.docker.com/compose/
เราอาจจะมองว่า 1 Service ก็คือ 1 Containerก็ได้ครับ
docker compose มันเป็นเรื่องที่ค่อนข้างเข้าใจยากหน่อย คุณสามารถศึกษาได้จาก Workshop ของผมเพิ่มเติม ลองเล่นลองแก้ไขคําสั่งต่างๆดูครับ จะทําให้เข้าใจมากยิ่งขึ้น