DevOps
น้องๆ หลายคนคงเคยได้ยินคำว่า Docker กันมาบ้างใช่มั้ย? สมัยผมทำร้านเน็ตฯ (SiamCafe.net) เมื่อ 20 กว่าปีก่อนเนี่ย การ deploy application แต่ละทีนี่ปวดหัวสุดๆ ต้องมานั่ง setup environment ให้มันเป๊ะๆ บน server แต่ละเครื่อง ซึ่งมันเสียเวลา แถมยังผิดพลาดง่ายอีกต่างหาก
Docker เนี่ย มันเข้ามาแก้ปัญหานี้แหละครับ มันคืออะไร? ทำไมมันถึงสำคัญ? เดี๋ยวพี่จะเล่าให้ฟังแบบง่ายๆ เลย
Docker มันคือ platform ที่ช่วยให้เรา package application ของเรา พร้อมกับ dependencies ทั้งหมด (เช่น libraries, runtime environment) ลงไปในสิ่งที่เรียกว่า "Container" ครับ คิดง่ายๆ ว่ามันคือกล่องๆ นึง ที่ข้างในมีทุกอย่างที่ application ของเราต้องการ เพื่อให้มันทำงานได้ ไม่ว่าเราจะเอา container นี้ไปรันที่ไหน มันก็จะทำงานได้เหมือนกันหมด
สมัยก่อนตอนทำ SiamCafe Blog นี่ ถ้าจะย้ายเว็บทีนึง ต้องมานั่งลง PHP, MySQL, Apache ใหม่หมด แถมบางที version ไม่ตรงกันอีก กว่าจะรันได้เหมือนเดิมนี่แทบแย่ แต่ถ้าเราใช้ Docker เราแค่ copy container ไปวาง แล้วสั่งรัน จบเลย ง่ายกว่าเยอะ
Docker มันสำคัญมากๆ เพราะมันช่วยแก้ปัญหาหลายอย่างที่คนทำ development และ operations เจอกันบ่อยๆ ครับ:
ลองนึกภาพสมัยก่อนที่ต้องลง OS ใหม่ทุกครั้งที่จะ deploy application แต่ละตัว เทียบกับตอนนี้ที่แค่สั่ง docker run ชีวิตมันง่ายขึ้นเยอะ!
Docker ทำงานโดยใช้สิ่งที่เรียกว่า "Containerization" ซึ่งเป็นรูปแบบหนึ่งของการ virtualization ที่ lightweight กว่า VM ครับ Docker engine จะใช้ kernel ของ host OS ร่วมกัน ทำให้ container มีขนาดเล็กกว่า VM มาก
Container จะสร้างจากสิ่งที่เรียกว่า "Docker Image" ซึ่งเป็น template ที่มีทุกอย่างที่ container ต้องการ Image จะถูก build จากสิ่งที่เรียกว่า "Dockerfile" ซึ่งเป็นไฟล์ text ที่บอก Docker ว่าจะต้องทำอะไรบ้าง เพื่อสร้าง image นี้
ลองดูตัวอย่าง Dockerfile ง่ายๆ:
# Use an official Python runtime as a parent image
FROM python:3.9-slim-buster
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
# Make port 8000 available to the world outside this container
EXPOSE 8000
# Define environment variable
ENV NAME SiamCafe
# Run app.py when the container launches
CMD ["python", "app.py"]
Dockerfile นี้จะบอก Docker ว่า:
/app/apprequirements.txtapp.py เมื่อ container เริ่มทำงานเอาล่ะ ทีนี้มาดูขั้นตอนการใช้งาน Docker แบบง่ายๆ กันบ้าง
docker build -t my-app . (my-app คือชื่อ image ที่เราตั้ง)docker run -p 8000:8000 my-app (-p 8000:8000 คือการ map port 8000 บน host ไปยัง port 8000 ใน container)localhost:8000 เพื่อเข้าใช้งาน application ของเราแค่นี้เอง! ง่ายใช่มั้ยล่ะ? ลองทำตามดูนะครับ
หลายคนอาจจะสงสัยว่า Docker ต่างจาก VM ยังไง? ลองดูตารางเปรียบเทียบนี้ครับ:
| Feature | Docker | Virtual Machine (VM) |
|---|---|---|
| Operating System | Shares host OS kernel | Runs its own full OS |
| Size | Small (MBs) | Large (GBs) |
| Startup Time | Fast (seconds) | Slow (minutes) |
| Resource Usage | Low | High |
| Isolation | Process isolation | Full OS isolation |
จากตารางจะเห็นได้ว่า Docker มีข้อดีหลายอย่างเหนือ VM โดยเฉพาะเรื่องขนาด, startup time, และ resource usage แต่ VM ก็ยังมีข้อดีในเรื่องของ isolation ที่ดีกว่า
สมัยผมทำร้านเน็ตฯ ถ้าใช้ VM นี่คงเปลือง resources มหาศาล Docker นี่แหละตอบโจทย์กว่าเยอะ
นอกจากคำสั่ง build และ run แล้ว ยังมีคำสั่ง Docker อีกหลายคำสั่งที่เราควรรู้:
docker ps: แสดง container ที่กำลัง run อยู่docker images: แสดง image ที่มีอยู่ในเครื่องdocker stop <container_id>: หยุด containerdocker rm <container_id>: ลบ containerdocker rmi <image_id>: ลบ imagedocker pull <image_name>: ดาวน์โหลด image จาก Docker Hubdocker push <image_name>: อัพโหลด image ขึ้น Docker Hubลองเอาคำสั่งเหล่านี้ไปใช้ดูนะครับ จะช่วยให้เราจัดการ Docker ได้ง่ายขึ้นเยอะ
หวังว่าบทความนี้จะช่วยให้น้องๆ เข้าใจ Docker มากขึ้นนะครับ ถ้ามีคำถามอะไรเพิ่มเติม ถามมาได้เลย SiamCafe Blog ยินดีช่วยเหลือเสมอ
หลังจากที่น้องๆ ได้ลองเล่น Docker เบื้องต้นกันแล้ว ทีนี้เรามาดูกันว่าเราจะสามารถเอา Docker ไปใช้ทำอะไรได้อีกบ้าง
ใน application จริงๆ ส่วนใหญ่มักจะประกอบไปด้วยหลาย components เช่น web server, database, cache server ซึ่งแต่ละ component ก็อาจจะ run อยู่ใน container แยกกัน Docker Compose จะช่วยให้เราจัดการ container เหล่านี้ได้ง่ายขึ้น
Docker Compose จะใช้ไฟล์ docker-compose.yml ในการ define services ต่างๆ ที่อยู่ใน application ของเรา ลองดูตัวอย่าง:
version: "3.9"
services:
web:
image: nginx:latest
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html
db:
image: postgres:14
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: mypassword
POSTGRES_DB: mydb
ไฟล์นี้จะ define 2 services คือ web และ db:
web จะใช้ image nginx:latest และ map port 80 บน host ไปยัง port 80 ใน container นอกจากนี้ยัง mount directory ./html บน host ไปยัง /usr/share/nginx/html ใน containerdb จะใช้ image postgres:14 และตั้ง environment variables สำหรับ username, password, และ database nameเราสามารถสั่ง start application ได้ด้วยคำสั่ง docker-compose up Docker Compose จะจัดการสร้างและ run container ทั้งหมดให้เรา
Docker Hub คือ registry ที่เก็บ Docker images จำนวนมาก เราสามารถดาวน์โหลด images เหล่านี้มาใช้ได้ฟรีๆ หรือจะสร้าง account แล้วอัพโหลด images ของเราขึ้นไปก็ได้
การใช้ Docker Hub จะช่วยให้เราไม่ต้อง build images เองตั้งแต่ต้น เราสามารถใช้ images ที่มีอยู่แล้ว แล้วปรับแต่งเพิ่มเติมได้ตามต้องการ
สมัยผมทำ SiamCafe Blog ก็ใช้ images จาก Docker Hub เยอะมาก ทั้ง nginx, mysql, redis สะดวกสุดๆ
โดยปกติแล้ว data ที่อยู่ใน container จะหายไปเมื่อ container ถูกลบ Docker Volumes จะช่วยให้เราจัดการ data persistence ได้ โดยการ mount directory บน host ไปยัง directory ใน container
Docker Volumes มี 2 แบบ:
docker volume create my-volume แล้ว mount volume นี้ไปยัง containerdocker run หรือใน docker-compose.ymlการใช้ Docker Volumes จะช่วยให้เราเก็บ data ของ application ไว้ได้ แม้ว่า container จะถูกลบไปแล้ว
Docker เป็นเครื่องมือที่ทรงพลังมากๆ ที่ช่วยให้เราจัดการ application ได้ง่ายขึ้น ไม่ว่าจะเป็นเรื่องของ consistency, isolation, portability, หรือ efficiency
ถ้าใครยังไม่เคยลองใช้ Docker พี่แนะนำให้ลองเล่นดูนะครับ แล้วจะรู้ว่าชีวิตมันง่ายขึ้นเยอะจริงๆ SiamCafe Blog มีบทความเกี่ยวกับ Docker อีกเยอะ ลองเข้าไปอ่านดูได้
ขอให้สนุกกับการใช้ Docker นะน้องๆ!
ดูวิดีโอเพิ่มเติมเกี่ยวกับDocker สำหรับมือใหม่ เริ่มต้นย:
สมัยผมทำร้านเน็ตฯ Dockerfile รกๆ นี่ปวดหัวเลยครับพี่น้อง! พยายามทำให้มันอ่านง่าย เป็นสัดส่วน ใช้ comment อธิบายขั้นตอนต่างๆ จะช่วยชีวิตตอน debug ได้เยอะเลยครับ
# Use an official Python runtime as a parent image
FROM python:3.9-slim-buster
# Set the working directory to /app
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . /app
# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -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"]
เห็นไหมครับ? บอกเลยว่าแต่ละ step ทำอะไร จะกลับมาแก้ทีหลังก็ง่ายกว่าเยอะ
.dockerignore นี่เหมือน firewall ให้ Docker เลยครับพี่น้อง! ไฟล์ไหนไม่จำเป็นต้อง copy เข้า container ก็ใส่ไว้ในนี้ซะ จะช่วยลดขนาด image และ build time ได้เยอะมาก
node_modules
.git
*.log
พวก node_modules หรือ log file นี่ตัวดีเลย ใส่ไว้ใน .dockerignore ด่วนๆ
เคยไหม build image ใหญ่บะเริ่มเทิ่ม? Multi-Stage Builds ช่วยได้! แบ่งการ build เป็นหลาย stage stage แรกใช้ build tool หนักๆ พอ build เสร็จก็ copy เฉพาะสิ่งที่จำเป็นไป stage สุดท้าย
FROM maven:3.8.1-openjdk-17 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
FROM openjdk:17-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
แบบนี้ image เล็กลงเยอะ แถม security ดีขึ้นด้วย
สมัยก่อนร้านเน็ตฯ ผมต้องคอยดู CPU, RAM ตลอด Docker ก็เหมือนกัน ต้อง monitor resource usage ของ container อย่างสม่ำเสมอ จะได้รู้ว่า container ไหนกิน resource เยอะผิดปกติ จะได้แก้ไขทัน
Docker มันเบากว่า Virtual Machine เยอะครับ! Virtual Machine ต้องจำลอง OS ทั้งหมด แต่ Docker แชร์ kernel กับ host OS ทำให้ resource usage น้อยกว่า เริ่มต้นเร็วกว่า
Docker Image เหมือน template ครับ ส่วน Container คือ instance ที่ run จาก image นั้น คิดง่ายๆ Image คือ class ส่วน Container คือ object
Push image ขึ้น Docker Hub เลยครับ! Docker Hub เหมือน GitHub สำหรับ Docker Image คนอื่นจะได้ pull ไปใช้ได้ง่ายๆ หรือจะสร้าง private registry เองก็ได้ ถ้าต้องการความปลอดภัย
Docker Compose เอาไว้จัดการหลาย container ที่ทำงานร่วมกันครับ สมมติว่า application ของเรามี web server, database, redis ก็ใช้ Docker Compose define dependencies ระหว่าง container พวกนี้ได้
พยายามใช้ base image ที่ official และได้รับการ update อย่างสม่ำเสมอ หลีกเลี่ยงการ run process ด้วย user root และ scan image หา vulnerability เป็นประจำ
Docker นี่เป็นเครื่องมือที่ powerful มากครับพี่น้อง! ช่วยให้เรา deploy application ได้ง่าย สะดวก รวดเร็ว แต่ก็ต้องศึกษาและทำความเข้าใจ concepts ต่างๆ ให้ดี จะได้ใช้งานได้อย่างมีประสิทธิภาพ และอย่าลืม iCafeForex ด้วยนะครับ เป็นกำลังใจให้ทุกคนที่กำลังเรียนรู้ Docker ครับ!
สุดท้ายนี้ อย่าลืมแวะไปอ่านบทความอื่นๆ ที่ SiamCafe Blog นะครับ มีอะไรดีๆ อีกเยอะเลย!