Skip to main content

รู้จักกับ Docker compose

รู้จักกับ docker-compose (ตัว management ของ Docker)

จริงๆ เราสามารถใช้ Docker รันทุกอย่างได้เลยนะ ตั้งแต่ Http server, database เช่น สมมุติเราจะสร้าง Container 3 ตัวคือ

  1. node - http server (แบบเมื่อกี้)
  2. mysql - database
  3. 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 กันก่อน โดย

  1. เราจะใช้ Dockerfile อันเดิมที่เราสร้าง
  2. เราจะเปลี่ยนจาก docker run เปลี่ยนเป็นการ run จาก docker-compose.yml
  3. เราจะ 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-1

คำสั่ง

  • 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 ออกมาถูกต้องเรียบร้อย

docker-compose-2

มาลองทดสอบให้ 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 ดูก็จะสามารถดึงข้อมูลออกมาได้

docker-compose-3

อันนี้เป็นข้อมูลที่อยู่ใน phpmyadmin docker-compose-4

อย่างที่เห็น ข้อมูลทั้งหมดมันเชื่อมกันแล้ว = การ config docker-compose เรียบร้อย

ทีนี้มีข้อสังเหตุอย่างหนึ่งหลังจาก docker-compose down จะเจอว่า

  • พอลองกลับมา docker-compose up -d --build อีกรอบ จะไม่เจอ database ที่สร้างเอาไว้
  • สาเหตุเพราะ เรายังไม่ได้มีการผูก volume หรือ disk อะไรเอาไว้เลย เลยกลายเป็นว่าทั้งหมดเก็บอยู่เพียงระดับ ram ของเครื่องแค่นั้น

มาดูเรื่อง docker volume กันต่อ