Dockerfile เขียนอย่างไร? อธิบายทีละบรรทัด

Dockerfile คือหัวใจของการสร้าง Docker Image เอง ทุกครั้งที่สั่ง docker build Docker จะอ่านไฟล์นี้และสร้าง Image ตามคำสั่งทีละบรรทัด

Structure ของ Dockerfile

Dockerfile คือไฟล์ Text ธรรมดา ไม่มีนามสกุล แต่ละบรรทัดคือคำสั่งหนึ่งที่ Docker จะรันเพื่อสร้าง Image

# ตัวอย่าง Dockerfile สำหรับ Node.js App
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD ["node", "server.js"]

อธิบายทุกคำสั่ง

FROM — เลือก Base Image

คำสั่งแรกที่ต้องมีในทุก Dockerfile กำหนดว่าจะสร้างบนกระดาน OS หรือ Runtime อะไร

FROM ubuntu:22.04
FROM python:3.12-slim
FROM node:20-alpine
FROM nginx:latest

แนะนำใช้ alpine หรือ slim เพื่อให้ Image มีขนาดเล็กลง

WORKDIR — กำหนด Working Directory

กำหนด Directory ที่จะใช้เป็นฟล์เดอร์ถ้านภายใน Container ถ้าไม่มีจะสร้างให้อัตโนมัติ

WORKDIR /app

COPY — คัดลอกไฟล์จาก Host เข้าไปใน Image

# คัดลอกไฟล์เดียว
COPY index.html /var/www/html/

# คัดลอกทั้ง Directory
COPY . .

# คัดลอกเฉพาะไฟล์ที่ต้องการ
COPY package*.json ./

RUN — รันคำสั่งระหว่าง Build

ใช้ติดตั้ง Package, สร้าง Directory หรือปรับแต่ง Config ตอนสร้าง Image แต่ละคำสั่ง RUN จะสร้าง Layer ใหม่ใน Image

RUN apt update && apt install -y curl
RUN npm install
RUN pip install -r requirements.txt

แนะนำรวมคำสั่ง RUN เป็นบรรทัดเดียวด้วย && เพื่อลดจำนวน Layer และทำให้ Image เล็กลง

ENV — ตั้งค่า Environment Variable

ENV NODE_ENV=production
ENV PORT=3000

EXPOSE — ประกาศ Port ที่ใช้งาน

บอกว่า Container ใช้ Port อะไร (เป็นแค่ Documentation ไม่ได้ Publish Port จริง)

EXPOSE 3000
EXPOSE 80 443

CMD — คำสั่งเริ่มต้นเมื่อ Container รัน

คำสั่งที่จะรันเมื่อ Container เริ่มต้น มีได้แค่หนึ่งใน Dockerfile

CMD ["node", "server.js"]
CMD ["python", "app.py"]
CMD ["nginx", "-g", "daemon off;"]

ENTRYPOINT — กำหนดคำสั่งหลักที่เปลี่ยนไม่ได้

คล้าย CMD แต่ไม่สามารถ Override ได้ง่ายๆ มักใช้สำหรับ Script ที่ต้องรันเสมอทุกครั้ง

ENTRYPOINT ["docker-entrypoint.sh"]

ตัวอย่างครบ: Dockerfile สำหรับ PHP App

FROM php:8.2-apache

WORKDIR /var/www/html

COPY . .

RUN docker-php-ext-install pdo pdo_mysql

EXPOSE 80

CMD ["apache2-foreground"]

บุ๊ฟมือ: .dockerignore

สร้างไฟล์ .dockerignore คู่กับ Dockerfile เพื่อสั่งไฟล์ที่ไม่ต้องการเข้าไปใน Image

node_modules
.git
.env
*.log
__pycache__

Build Image จาก Dockerfile

# Build โดยใช้ชื่อ my-app
docker build -t my-app .

# Build พร้อม Version Tag
docker build -t my-app:1.0 .

# รัน Container จาก Image ที่สร้าง
docker run -d -p 3000:3000 my-app

สรุปคำสั่งใน Dockerfile

คำสั่ง หน้าที่
FROM เลือก Base Image
WORKDIR กำหนด Directory ทำงาน
COPY คัดลอกไฟล์เข้า Image
RUN รันคำสั่งตอน Build
ENV ตั้ง Environment Variable
EXPOSE ประกาศ Port
CMD คำสั่งเริ่ม Container
ENTRYPOINT คำสั่งหลักที่เปลี่ยนไม่ได้

เมื่อเขียน Dockerfile เป็นแล้ว ขั้นตอนถัดไปคือเรียนรู้ Docker Hub เพื่อแชร์ Image ไปใช้งานบนเครื่องอื่นได้ครับ