Docker: จากการพัฒนาสู่การใช้งานจริง
คู่มือ Docker ฉบับสมบูรณ์สำหรับการ containerize แอปพลิเคชัน Dockerfile, Docker Compose, multi-stage build และการ deploy สู่ production พร้อมตัวอย่างจริง

Docker ปฏิวัติวิธีการพัฒนา ทดสอบ และ deploy แอปพลิเคชัน ด้วยการห่อหุ้มแอปพลิเคชันและ dependency ทั้งหมดไว้ใน container แบบพกพา Docker ขจัดปัญหาที่รู้จักกันดีว่า "ทำงานได้บนเครื่องของฉัน" และรับประกันความสอดคล้องในทุกสภาพแวดล้อม คู่มือนี้ครอบคลุมเส้นทางทั้งหมดตั้งแต่ Dockerfile แรกจนถึงการ deploy สู่ production
Docker Desktop 5.x นำเสนอการปรับปรุงประสิทธิภาพอย่างมาก รวมถึงการรองรับ containerd แบบ native การจัดการทรัพยากรที่ได้รับการปรับแต่ง และการผสานรวมกับ Kubernetes อย่างไร้รอยต่อ Image แบบ multi-architecture (ARM/x86) กลายเป็นมาตรฐานในปัจจุบัน
พื้นฐานของ Containerization
Container คือหน่วยซอฟต์แวร์น้ำหนักเบาที่รวม code, runtime, system library และการตั้งค่าต่างๆ ไว้ด้วยกัน ต่างจาก virtual machine ที่ virtualize hardware ตรงที่ container ใช้ kernel ของระบบ host ร่วมกัน ทำให้เริ่มต้นได้เร็วกว่าและใช้ทรัพยากรน้อยกว่า
# terminal
# Docker installation on Ubuntu
sudo apt update
sudo apt install -y docker.io
# Add user to docker group (avoids sudo)
sudo usermod -aG docker $USER
# Verify installation
docker --version
# Docker version 26.1.0, build 1234567
# First container: downloads image and runs
docker run hello-worldคำสั่งนี้ดาวน์โหลด image hello-world จาก Docker Hub และเริ่มต้น container ที่แสดงข้อความยืนยัน
# terminal
# List running containers
docker ps
# List all containers (including stopped)
docker ps -a
# List downloaded images
docker images
# Remove a container
docker rm <container_id>
# Remove an image
docker rmi <image_name>คำสั่งพื้นฐานเหล่านี้จัดการวงจรชีวิตของ container และ image
การสร้าง Dockerfile แรก
Dockerfile ประกอบด้วยคำสั่งสำหรับสร้าง Docker image แต่ละคำสั่งสร้าง layer ใน image สุดท้าย ทำให้สามารถ cache และนำกลับมาใช้ใหม่ได้
# Dockerfile
# Base image: Node.js 22 on Alpine Linux (lightweight)
FROM node:22-alpine
# Set working directory in the container
WORKDIR /app
# Copy dependency files first (cache optimization)
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy source code
COPY . .
# Expose port (documentation)
EXPOSE 3000
# Startup command
CMD ["node", "server.js"]ลำดับของคำสั่งมีความสำคัญอย่างยิ่งต่อการ optimize cache ไฟล์ที่เปลี่ยนแปลงไม่บ่อย (package.json) ควรถูก copy ก่อน source code
# terminal
# Build image with a tag
docker build -t my-app:1.0 .
# Run the container
docker run -d -p 3000:3000 --name my-app-container my-app:1.0
# Check logs
docker logs my-app-container
# Access container shell
docker exec -it my-app-container shflag -d รัน container ในโหมด background, -p map port 3000 ของ container ไปยัง port 3000 ของ host
Image Alpine มีขนาดเล็กกว่ามาก (ประมาณ 5 MB เทียบกับ 120 MB ของ Debian) อย่างไรก็ตาม Alpine ใช้ musl libc แทน glibc ซึ่งอาจทำให้เกิดความไม่เข้ากันกับ native dependency บางตัว เมื่อเกิดปัญหา แนะนำให้ใช้ image ที่ใช้ Debian (node:22-slim)
Multi-stage Build สำหรับ Production
Multi-stage build สร้าง production image ที่ได้รับการ optimize โดยแยกสภาพแวดล้อม build ออกจากสภาพแวดล้อม runtime เฉพาะ artifact ที่จำเป็นเท่านั้นที่จะถูกรวมใน image สุดท้าย
# Dockerfile.production
# ============================================
# Stage 1: Build
# ============================================
FROM node:22-alpine AS builder
WORKDIR /app
# Copy and install dependencies (including devDependencies)
COPY package*.json ./
RUN npm ci
# Copy source code
COPY . .
# Build the application (TypeScript, bundling, etc.)
RUN npm run build
# ============================================
# Stage 2: Production
# ============================================
FROM node:22-alpine AS production
# Non-root user for security
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
# Copy only necessary files from builder stage
COPY /app/dist ./dist
COPY /app/node_modules ./node_modules
COPY /app/package.json ./
# Switch to non-root user
USER nodejs
# Environment variables
ENV NODE_ENV=production
ENV PORT=3000
EXPOSE 3000
# Startup command
CMD ["node", "dist/server.js"]วิธีนี้ลดขนาด image สุดท้ายได้อย่างมาก โดยไม่รวม build tool, devDependencies และไฟล์ source
# terminal
# Build with specific file
docker build -f Dockerfile.production -t my-app:production .
# Compare image sizes
docker images | grep my-app
# my-app production abc123 150MB
# my-app 1.0 def456 450MBการลดขนาดสามารถถึง 60-70% ขึ้นอยู่กับโปรเจกต์ ช่วยปรับปรุงเวลา deploy และลด attack surface
Docker Compose สำหรับ Orchestration ในเครื่อง
Docker Compose ทำให้การจัดการแอปพลิเคชันหลาย container ง่ายขึ้น ไฟล์ YAML ประกาศ service ทั้งหมด การตั้งค่า และ dependency ของมัน
# docker-compose.yml
version: "3.9"
services:
# Main application
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://postgres:secret@db:5432/myapp
- REDIS_URL=redis://cache:6379
volumes:
# Mount source code for hot-reload
- ./src:/app/src
- ./package.json:/app/package.json
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
networks:
- app-network
# PostgreSQL database
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
POSTGRES_DB: myapp
volumes:
# Data persistence
- postgres_data:/var/lib/postgresql/data
# Initialization script
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
networks:
- app-network
# Redis cache
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
command: redis-server --appendonly yes
networks:
- app-network
# Named volumes for persistence
volumes:
postgres_data:
redis_data:
# Dedicated network for isolation
networks:
app-network:
driver: bridgeService สื่อสารกันโดยใช้ชื่อ (db, cache) ผ่านเครือข่ายภายในของ Docker Healthcheck รับประกันว่า dependency พร้อมใช้งานก่อนที่แอปพลิเคชันจะเริ่มต้น
# terminal
# Start all services
docker compose up -d
# View logs from all services
docker compose logs -f
# Logs from a specific service
docker compose logs -f app
# Stop and remove containers
docker compose down
# Removal including volumes (caution: data loss)
docker compose down -v
# Rebuild after Dockerfile changes
docker compose up -d --buildพร้อมที่จะพิชิตการสัมภาษณ์ DevOps แล้วหรือยังครับ?
ฝึกฝนด้วยตัวจำลองแบบโต้ตอบ, flashcards และแบบทดสอบเทคนิคครับ
การจัดการ Secret และตัวแปรสภาพแวดล้อม
การจัดการ secret อย่างปลอดภัยเป็นสิ่งสำคัญยิ่งใน production Docker มีหลายวิธีการขึ้นอยู่กับบริบท
# docker-compose.override.yml (development only)
version: "3.9"
services:
app:
env_file:
- .env.development
environment:
- DEBUG=trueสำหรับ production Docker secrets ให้ความปลอดภัยที่สูงขึ้น
# docker-compose.production.yml
version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile.production
secrets:
- db_password
- api_key
environment:
- NODE_ENV=production
- DATABASE_PASSWORD_FILE=/run/secrets/db_password
- API_KEY_FILE=/run/secrets/api_key
secrets:
db_password:
file: ./secrets/db_password.txt
api_key:
file: ./secrets/api_key.txtโค้ดแอปพลิเคชันอ่าน secret จากไฟล์ที่ mount ไว้
const fs = require('fs');
const path = require('path');
// Utility function to read Docker secrets
function readSecret(secretName) {
const secretPath = `/run/secrets/${secretName}`;
// Check if secret file exists
if (fs.existsSync(secretPath)) {
return fs.readFileSync(secretPath, 'utf8').trim();
}
// Fallback to classic environment variables
const envVar = secretName.toUpperCase();
return process.env[envVar];
}
module.exports = {
databasePassword: readSecret('db_password'),
apiKey: readSecret('api_key'),
};วิธีนี้ป้องกันไม่ให้ secret ถูกเปิดเผยในตัวแปรสภาพแวดล้อมหรือ Docker image
การ Optimize Docker Image
หลายเทคนิคช่วยลดขนาด image และปรับปรุงประสิทธิภาพ
# Dockerfile.optimized
FROM node:22-alpine AS base
# Install necessary tools in a single layer
RUN apk add --no-cache \
dumb-init \
&& rm -rf /var/cache/apk/*
# ============================================
# Stage: Dependencies
# ============================================
FROM base AS deps
WORKDIR /app
# Copy only lock files for caching
COPY package.json package-lock.json ./
# Install with mounted npm cache (BuildKit)
RUN \
npm ci --only=production
# ============================================
# Stage: Builder
# ============================================
FROM base AS builder
WORKDIR /app
COPY package.json package-lock.json ./
RUN \
npm ci
COPY . .
RUN npm run build
# ============================================
# Stage: Production
# ============================================
FROM base AS production
# Image metadata
LABEL maintainer="team@example.com"
LABEL version="1.0"
LABEL description="Production-ready Node.js application"
# Non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nodejs -u 1001
WORKDIR /app
# Copy production dependencies
COPY /app/node_modules ./node_modules
# Copy build output
COPY /app/dist ./dist
COPY /app/package.json ./
USER nodejs
ENV NODE_ENV=production
# dumb-init as PID 1 for signal handling
ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/server.js"]การใช้ dumb-init รับประกันการจัดการสัญญาณ Unix อย่างถูกต้อง ทำให้ container สามารถ shutdown ได้อย่างสมบูรณ์
# terminal
# Enable BuildKit for advanced features
export DOCKER_BUILDKIT=1
# Build with cache and detailed output
docker build --progress=plain -t my-app:optimized .
# Analyze image layers
docker history my-app:optimized
# Detailed image inspection
docker inspect my-app:optimizedImage ควรถูกสแกนหาช่องโหว่เป็นประจำโดยใช้เครื่องมืออย่าง Trivy หรือ Snyk Base image ต้องได้รับการอัปเดตเป็นประจำเพื่อรวม security patch
เครือข่าย Docker ขั้นสูง
Docker มี network driver หลายประเภทสำหรับกรณีการใช้งานที่แตกต่างกัน
# docker-compose.networking.yml
version: "3.9"
services:
# Publicly accessible frontend
frontend:
build: ./frontend
ports:
- "80:80"
networks:
- frontend-network
- backend-network
# API accessible only from frontend
api:
build: ./api
networks:
- backend-network
- database-network
# No external ports exposed
# Isolated database
database:
image: postgres:16-alpine
networks:
- database-network
# Accessible only by API
networks:
frontend-network:
driver: bridge
backend-network:
driver: bridge
internal: true # No internet access
database-network:
driver: bridge
internal: trueการตั้งค่านี้แยก service ตามหลักการ least privilege ฐานข้อมูลเข้าถึงได้เฉพาะจาก API เท่านั้น
# terminal
# Inspect Docker networks
docker network ls
# Details of a specific network
docker network inspect app-network
# Create a custom network
docker network create --driver bridge --subnet 172.28.0.0/16 custom-network
# Connect a container to an existing network
docker network connect custom-network my-containerVolume และการเก็บรักษาข้อมูล
Docker volume รักษาข้อมูลเกินกว่าวงจรชีวิตของ container
# docker-compose.volumes.yml
version: "3.9"
services:
app:
image: my-app:latest
volumes:
# Named volume for persistent data
- app_data:/app/data
# Bind mount for development
- ./uploads:/app/uploads:rw
# Read-only mount for configuration
- ./config:/app/config:ro
backup:
image: alpine
volumes:
# Access same volume for backups
- app_data:/data:ro
- ./backups:/backups
command: |
sh -c "tar czf /backups/backup-$$(date +%Y%m%d).tar.gz /data"
volumes:
app_data:
driver: local
driver_opts:
type: none
device: /path/to/host/data
o: bindความแตกต่างระหว่าง named volume และ bind mount เป็นสิ่งสำคัญ: volume ถูกจัดการโดย Docker ในขณะที่ bind mount ใช้ filesystem ของ host โดยตรง
# terminal
# List volumes
docker volume ls
# Inspect a volume
docker volume inspect app_data
# Remove orphaned volumes
docker volume prune
# Backup a volume
docker run --rm -v app_data:/data -v $(pwd):/backup alpine \
tar czf /backup/volume-backup.tar.gz /dataการ Deploy สู่ Production
กระบวนการ deploy ที่แข็งแกร่งประกอบด้วย build, test และ push ไปยัง registry
# deploy.sh
#!/bin/bash
set -e
# Variables
REGISTRY="registry.example.com"
IMAGE_NAME="my-app"
VERSION=$(git describe --tags --always)
echo "Building version: $VERSION"
# Build production image
docker build \
-f Dockerfile.production \
-t $REGISTRY/$IMAGE_NAME:$VERSION \
-t $REGISTRY/$IMAGE_NAME:latest \
--build-arg BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--build-arg VERSION=$VERSION \
.
# Security scan
echo "Running security scan..."
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
aquasec/trivy image $REGISTRY/$IMAGE_NAME:$VERSION
# Push to registry
echo "Pushing to registry..."
docker push $REGISTRY/$IMAGE_NAME:$VERSION
docker push $REGISTRY/$IMAGE_NAME:latest
echo "Deployment complete: $REGISTRY/$IMAGE_NAME:$VERSION"สำหรับ server deployment ไฟล์ compose สำหรับ production แยกต่างหากจะปรับแต่งการตั้งค่า
# docker-compose.prod.yml
version: "3.9"
services:
app:
image: registry.example.com/my-app:latest
restart: always
deploy:
replicas: 3
resources:
limits:
cpus: "0.5"
memory: 512M
reservations:
cpus: "0.25"
memory: 256M
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"การตั้งค่านี้กำหนดการจัดสรรทรัพยากร กลยุทธ์การอัปเดต และ healthcheck สำหรับการ deploy ที่เชื่อถือได้
# terminal
# Production deployment with Docker Compose
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
# Zero-downtime update (rolling update)
docker compose -f docker-compose.yml -f docker-compose.prod.yml pull
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps app
# Rollback if issues occur
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps \
--scale app=0 && \
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d --no-deps appการ Monitor และ Debug Container
การ monitor container เป็นสิ่งจำเป็นใน production
# terminal
# Real-time statistics for all containers
docker stats
# Statistics for a specific container with custom format
docker stats my-app --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
# Inspect processes in a container
docker top my-app
# Real-time Docker events
docker events --filter container=my-app
# Copy files from/to a container
docker cp my-app:/app/logs/error.log ./error.logสำหรับการ debug เชิงลึก มีเทคนิคหลายอย่างให้ใช้
# terminal
# Interactive shell in a running container
docker exec -it my-app sh
# Execute a single command
docker exec my-app cat /app/config/settings.json
# Start a container in debug mode
docker run -it --rm --entrypoint sh my-app:latest
# Inspect environment variables
docker exec my-app printenv
# Analyze logs with filters
docker logs my-app --since 1h --tail 100 | grep ERROR# docker-compose.monitoring.yml
version: "3.9"
services:
app:
# ... existing configuration
labels:
- "prometheus.scrape=true"
- "prometheus.port=3000"
- "prometheus.path=/metrics"
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=15d'
grafana:
image: grafana/grafana:latest
ports:
- "3001:3000"
volumes:
- grafana_data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=secret
volumes:
prometheus_data:
grafana_data:stack monitoring นี้ช่วยให้สามารถเก็บรวบรวมและแสดงผล metric ของ container ได้
สรุป
Docker เปลี่ยนแปลงวงจรการพัฒนาโดยรับประกันความสอดคล้องในทุกสภาพแวดล้อม Containerization นำมาซึ่งความพกพา การแยกส่วน และความสามารถในการทำซ้ำ คุณสมบัติที่จำเป็นสำหรับแอปพลิเคชันสมัยใหม่
Docker Checklist สำหรับ Production
- ✅ Multi-stage build สำหรับ image ที่ได้รับการ optimize
- ✅ ใช้ user ที่ไม่ใช่ root ใน container
- ✅ Healthcheck ถูกตั้งค่าสำหรับทุก service
- ✅ Secret ถูกจัดการผ่าน Docker secrets หรือตัวแปรสภาพแวดล้อมที่ปลอดภัย
- ✅ จำกัดทรัพยากร (CPU, หน่วยความจำ) ที่กำหนดไว้
- ✅ Volume สำหรับการเก็บรักษาข้อมูลที่สำคัญ
- ✅ Logging แบบรวมศูนย์พร้อม file rotation
- ✅ สแกนความปลอดภัยของ image ก่อน deploy
- ✅ กลยุทธ์การอัปเดตแบบ zero-downtime
- ✅ เครือข่ายแยกระหว่าง service
เริ่มฝึกซ้อมเลย!
ทดสอบความรู้ของคุณด้วยตัวจำลองสัมภาษณ์และแบบทดสอบเทคนิคครับ
การเชี่ยวชาญ Docker เป็นทักษะพื้นฐานของนักพัฒนาสมัยใหม่ทุกคน ตั้งแต่สภาพแวดล้อมในเครื่องจนถึงการ deploy สู่ production Docker กำหนดมาตรฐาน workflow และทำให้การดำเนินงานง่ายขึ้น แนวคิดที่นำเสนอที่นี่เป็นรากฐานที่แข็งแกร่งสำหรับการสำรวจ Kubernetes และการ orchestrate container ในระดับใหญ่
แท็ก
แชร์
บทความที่เกี่ยวข้อง

คำถามสัมภาษณ์ DevOps ที่จำเป็น: คู่มือฉบับสมบูรณ์ 2026
เตรียมตัวสัมภาษณ์ DevOps ด้วยคำถามที่ต้องรู้เกี่ยวกับ CI/CD, Kubernetes, Docker, Terraform และแนวปฏิบัติ SRE พร้อมคำตอบละเอียด

สัมภาษณ์ Kubernetes: อธิบาย Pods, Services และ Deployments อย่างละเอียด
คำถามสัมภาษณ์ Kubernetes เกี่ยวกับ Pods, Services และ Deployments พร้อมตัวอย่าง YAML กลไก networking ภายใน และกลยุทธ์ scaling สำหรับปี 2026