listBasic Programming
รู้จักกับ Docker compose
สารบัญ
รู้จักกับ docker-compose (ตัว management ของ Docker)
จริงๆ เราสามารถใช้ Docker รันทุกอย่างได้เลยนะ ตั้งแต่ Http server, database เช่น สมมุติเราจะสร้าง Container 3 ตัวคือ
- node - http server (แบบเมื่อกี้)
- mysql - database
- phpmyadmin - หน้าจัดการ database
เราก็สามารถไล่สร้าง Dockerfile ทีละอัน และ run ทั้ง 3 ตัวมาก็ได้ ปัญหามันจะเกิดขึ้นคือ
- ถ้า Container เยอะ เราจะเริ่มจัดการยากขึ้น
- ยิ่งถ้ามีการ update application จะต้องคอยมา update แต่ละ image จะยิ่งจัดการยาก
มันก็เลยมี tool ตัวหนึ่ง คือตัว Composer สำหรับการควบคุม Docker container แบบทีละหลายตัวได้ คือ docker-compose ขึ้นมา
docker-compose คือเครื่องมือสำหรับจัดการ docker แบบทีละหลาย container ได้ ข้อดีของ docker-compose คือ ถ้าเกิด application เรามีการใช้ image file ร่วมกันหลายตัว มันจะเป็นตัวควบคุมทำให้ image แต่ละตัวสื่อสารกันได้ง่ายขึ้น (รวมถึงสามารถจำลองการ communication ใน production จริงได้เช่นกัน)
ซึ่งข้อดีของปัจจุบันคือ docker-compose เป็นตัว default ที่ลงมาให้กับ Docker desktop แล้วเรียบร้อย ! (ใช่ครับ เมื่อก่อนมันต้องไปหาลงเอง) ดังนั้นจึงไม่ต้องลงอะไรเพิ่มแล้ว สามารถใช้งานได้เลย
รู้จักกับ docker-compose.yml ไฟล์
เราจะเริ่มต้นโดยการลองเปลี่ยน node เป็น docker-compose.yml กันก่อน โดย
- เราจะใช้ Dockerfile อันเดิมที่เราสร้าง
- เราจะเปลี่ยนจาก
docker runเปลี่ยนเป็นการ run จากdocker-compose.yml - เราจะ start service ด้วย
docker-compose up -d --build
ที่ docker-compose.yml เราจะมีหน้าตาแบบนี้
- pattern ของ yaml file คือ key: value โดย ถ้าอันไหนเป็นลูกของ key ไหนก็จะเลื่อน tab ไป
- ภายใต้ services = จำนวน container ที่จะ run ใน docker-compose
version: '3' # กำหนด docker version
services:
node-server: # ตั้งชื่อ container (เหมือน --name)
build: . # ตำแหน่ง dockerfile
ports:
- "8000:8000" # map port ออกมา เหมือน -p ใน docker run วางไว้ตำแหน่งเดียวกันกับ folder project แล้วลอง run ด้วยคำสั่ง
docker-compose up -d --buildจะได้ผลลัพธ์ออกมาเหมือนกันกับก่อนหน้านี้ (สามารถเช็คได้ด้วย docker ps เช่นกัน)
คำสั่ง
docker-compose upเป็นคำสั่งสำหรับการ bulid และ run docker image ไปพร้อมๆกัน (docker-compose อำนวยความสะดวกในการ bulid + run ไปพร้อมกัน)- สามารถทำการ down service ทั้งหมดได้โดยใช้คำสั่ง
docker-compose downได้เช่นกัน - และกรณีที่ แค่ build แต่ไม่ run สามารถใช้เพียงแค่
docker-compose build
Next step เราจะเพิ่ม mysql และ phpmyadmin เข้ามา
เพิ่ม services อีก 2 ตัวเข้ามาคือ
- mysql - ฐานข้อมูล
- phpmyadmin (ต่อเข้ากับ mysql เพื่อใช้สำหรับ management ข้อมูล)
เนื่องจากรอบนี้ เราไม่จำเป็นต้องใช้ Dockerfile เนื่องจาก เราจะไม่ปรับแต่งอะไรใน mysql และ phpmyadmin ใช้จาก docker hub ตรงๆเลย เราเลยจะเพียงระบุ image ที่จะใช้เท่านั้น โดย
- mysql เราจะตั้งชื่อ container ว่า db
- phpmyadmin เราจะตั้งชื่อ container ว่า phpmyadmin
services:
node-server:
build: .
ports:
- "8000:8000"
db:
image: mysql:latest
container_name: db
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: root # กำหนด user ของ root mysql
MYSQL_DATABASE: tutorial # กำหนด database เริ่มต้นของ mysql
ports:
- "3306:3306"
phpmyadmin:
image: phpmyadmin/phpmyadmin:latest
container_name: phpmyadmin
environment:
PMA_HOST: db # ระบุ host ที่จะให้ phpmyadmin ไปจัดการ ซึ่งสามารถใส่เป็นชื่อ container name (db) ได้เลย
PMA_PORT: 3306 # ระบุ port ของ Database
PMA_USER: root # ระบุ user ของ Database
PMA_PASSWORD: root # ระบุ password ของ Database
ports:
- "8080:80"
depends_on:
- dbอธิบาย config เพิ่มเติม
- db (mysql) จะมีการใส่สิ่งที่เรียกว่า
environment(เป็นเหมือน config ระบบ) โดย เราจะกำหนด MYSQL_ROOT_PASSWORD, MYSQL_DATABASE เอาไว้ เพื่อให้ตอน run container ขึ้นมา เราจะสามารถ access เข้า root ได้ (production จริงเราจะไม่ทำแบบนี้กันนะครับ) ซึ่งอันนี้สามารถรู้ได้จากเอกสาร docker ของ mysql https://hub.docker.com/_/mysql - phpmyadmin คือหน้าจัดการ SQL database มีการใส่
environmentเช่นกัน โดยจะทำการเลือกไปยัง host db (mysql) โดยการใส่เพียงชื่อ container name ได้เลย (อันนี้เป็นข้อดีของพวก docker เช่นกัน มันสามารถคุยกันผ่านชื่อ container ได้)
แล้วลอง run ดูด้วย docker-compose up -d --build
ลองเปิดผ่าน localhost:8080 ดู ถ้าเจอหน้าจอประมาณนี้ = docker-compose ออกมาถูกต้องเรียบร้อย
มาลองทดสอบให้ node คุยกับ mysql ดูกัน
เราทำการลง library mysql2 เพิ่มเพื่อมาลองทดสอบ query กัน
update index.js ให้
- เพิ่ม GET /users สำหรับดึงข้อมูล users ทั้งหมดออกมา
- host สามารถใส่เป็น localhost หรือ db ก็ได้
code index.js
const express = require('express')
const mysql = require('mysql2/promise')
const app = express()
const port = 8000
const initMySQL = async () => {
conn = await mysql.createConnection({
host: 'db', // หรือใส่เป็น localhost ก็ได้
user: 'root',
password: 'root',
database: 'tutorial'
})
}
app.get('/hello-world', (req, res) => {
res.send('hello world')
})
// path = GET /users สำหรับ get users ทั้งหมดที่บันทึกเข้าไปออกมา
app.get('/users', async (req, res) => {
const [results] = await conn.query('SELECT * FROM users')
res.json(results)
})
app.listen(port, async () => {
await initMySQL()
console.log(`Server running at http://localhost:${port}/`)
})เสร็จแล้วลอง docker-compose down และ docker-compose up -d --build ใหม่
แล้วลองยิงไปที่ GET /users ดูก็จะสามารถดึงข้อมูลออกมาได้
อันนี้เป็นข้อมูลที่อยู่ใน phpmyadmin
อย่างที่เห็น ข้อมูลทั้งหมดมันเชื่อมกันแล้ว = การ config docker-compose เรียบร้อย
ทีนี้มีข้อสังเหตุอย่างหนึ่งหลังจาก docker-compose down จะเจอว่า
- พอลองกลับมา
docker-compose up -d --buildอีกรอบ จะไม่เจอ database ที่สร้างเอาไว้ - สาเหตุเพราะ เรายังไม่ได้มีการผูก volume หรือ disk อะไรเอาไว้เลย เลยกลายเป็นว่าทั้งหมดเก็บอยู่เพียงระดับ ram ของเครื่องแค่นั้น
มาดูเรื่อง docker volume กันต่อ
