Docker
Container orchestration สำหรับ development, CI/CD และ production บน AWS EC2
What I Can Do
- Build และ run containerized applications
- เขียน multi-stage Dockerfile เพื่อลด image size
- จัดการ multi-container apps ด้วย Docker Compose
- Debug container issues บน production (AWS EC2)
- Setup volume, network, environment variables อย่างถูกต้อง
Commands I Use Daily
Container Management
# ดู running containers
docker ps
# ดู container ทั้งหมดรวม stopped
docker ps -a
# run container แบบ detach + ตั้งชื่อ + map port
docker run -d --name myapp -p 8080:3000 myapp:latest
# หยุด container
docker stop myapp
# ลบ container
docker rm myapp
# หยุดแล้วลบทีเดียว
docker rm -f myapp
# เข้าไปใน container (shell)
docker exec -it myapp /bin/sh
# run command ใน container โดยไม่เข้า shell
docker exec myapp ls /app
# ดู log แบบ follow + แสดงเวลา
docker logs -f --timestamps myapp
# ดู resource usage แบบ real-time (CPU, memory, network I/O)
docker stats
# ดู config detail ของ container — ใช้ debug network, volume, env
docker inspect myapp
# copy file จาก container ออกมา host
docker cp myapp:/app/config.json ./config.json
# restart container
docker restart myappImage Management
# build image จาก Dockerfile + tag
docker build -t myapp:1.0 .
# build ด้วย specific Dockerfile
docker build -f Dockerfile.prod -t myapp:prod .
# ดู images ทั้งหมด
docker image ls
# ดู image size + layers
docker history myapp:latest
# tag image สำหรับ push ไป registry
docker tag myapp:1.0 registry.example.com/myapp:1.0
# push image ไป registry
docker push registry.example.com/myapp:1.0
# pull image จาก registry
docker pull nginx:alpine
# ลบ image
docker rmi myapp:old
# ลบ dangling images (untagged)
docker image prune -fDocker Compose
# start ทุก services (detach mode)
docker compose up -d
# rebuild แล้ว start (ใช้ตอน code เปลี่ยน)
docker compose up -d --build
# หยุดทุก services
docker compose down
# หยุด + ลบ volumes ด้วย (ระวัง ข้อมูล DB หาย)
docker compose down -v
# ดู status ของ services
docker compose ps
# ดู logs ทุก services
docker compose logs -f
# ดู logs เฉพาะ service
docker compose logs -f api
# restart เฉพาะ service เดียว
docker compose restart api
# scale service (เช่น run 3 instances)
docker compose up -d --scale worker=3Network & Volume
# ดู network ทั้งหมด — ใช้ตรวจว่า container อยู่ network เดียวกัน
docker network ls
# สร้าง custom network
docker network create my-network
# ดู containers ใน network
docker network inspect my-network
# ดู volumes ทั้งหมด
docker volume ls
# ลบ unused volumes
docker volume prune -fCleanup & Disk
# ดู disk usage ของ Docker
docker system df
# ล้าง dangling images, stopped containers, unused networks
docker system prune -f
# ล้างทุกอย่างรวม unused volumes (ใช้ตอน disk เต็ม)
docker system prune -a --volumesContainer คืออะไร
Container เป็น lightweight isolated process ที่ run บน shared OS kernel — ต่างจาก VM ที่ต้อง run ทั้ง OS แยก Container ใช้ Linux namespaces + cgroups ในการแยก process, filesystem, network ทำให้ boot เร็วและใช้ resource น้อยกว่า VM มาก
Image vs Container
- Image = read-only template (เหมือน class) — สร้างจาก Dockerfile, ประกอบด้วยหลาย layers ซ้อนกัน
- Container = running instance ของ image (เหมือน object) — สร้างจาก
docker run, มี writable layer ด้านบน - Image เดียวสามารถสร้างหลาย containers ได้
Dockerfile Basics
Dockerfile คือ set of instructions สำหรับ build image — แต่ละ instruction สร้าง 1 layer
FROM— base image เช่นgolang:1.22-alpine,node:20-slimWORKDIR— set working directoryCOPY/ADD— copy files เข้า imageRUN— execute command ตอน build เช่น install dependenciesEXPOSE— declare port (documentation, ไม่ได้ publish จริง)CMD/ENTRYPOINT— command ที่ run ตอน start container
docker run / build / pull
docker build -t myapp .— build image จาก Dockerfiledocker pull nginx:alpine— download image จาก registrydocker run -d --name myapp myapp— run container แบบ detach
Port Mapping
-p host:container — map port จากเครื่อง host เข้า container เช่น -p 8080:3000 ทำให้เข้า localhost:8080 แล้วไปที่ container port 3000
Volume
- Named volume —
docker volume create pgdata+-v pgdata:/var/lib/postgresql/data— Docker manage ให้, persist ข้ามการ recreate container - Bind mount —
-v ./src:/app/src— mount โฟลเดอร์จาก host เข้า container โดยตรง, ใช้ตอน development
Multi-stage Build
แยก build stage ออกจาก runtime stage เพื่อให้ final image เล็กที่สุด — build tools ไม่ติดไปใน production image
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o main ./cmd/server
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/main .
CMD ["./main"]Docker Compose
จัดการ multi-container applications ด้วย docker-compose.yml — define services, networks, volumes ในไฟล์เดียว ใช้ docker compose up สั่ง run ทุก service พร้อมกัน
Networking (Bridge / Host)
- Bridge (default) — container อยู่ใน private network, ติดต่อกันผ่าน container name เป็น hostname
- Host — container ใช้ network ของ host โดยตรง, ไม่มี network isolation
- Custom bridge network ทำให้ container คุยกันได้ผ่าน DNS โดยไม่ต้อง link
.dockerignore
ระบุ files/folders ที่ไม่ต้อง copy เข้า build context — ลด build time และป้องกัน sensitive files หลุดเข้า image เช่น node_modules, .git, .env
Layer Caching
Docker cache แต่ละ layer — ถ้า instruction ไม่เปลี่ยน ใช้ cache จาก build ก่อน ดังนั้นควร COPY dependency files ก่อน source code เพื่อให้ go mod download หรือ npm install ถูก cache
Resource Limits
กำหนด memory และ CPU limits เพื่อป้องกัน container ใช้ resource เกิน
services:
api:
deploy:
resources:
limits:
memory: 512M
cpus: "1.0"Container Orchestration Concepts
เข้าใจหลักการของ orchestration (Kubernetes, Docker Swarm) — service discovery, load balancing, rolling updates, self-healing, desired state management
Security (Non-root User, Read-only FS)
- Run container ด้วย non-root user —
USER 1001ใน Dockerfile - ใช้ read-only filesystem —
--read-onlyflag + tmpfs สำหรับ writable paths - Scan image หา vulnerabilities ด้วย
docker scoutหรือ Trivy - ไม่ store secrets ใน image — ใช้ environment variables หรือ secret management
Image Optimization
- ใช้ Alpine หรือ distroless base image
- Minimize layers — รวม RUN commands ด้วย
&& - ใช้
.dockerignoreอย่างเคร่งครัด - Multi-stage build เพื่อ exclude build tools
Health Checks
กำหนด health check เพื่อให้ Docker รู้ว่า container พร้อม serve traffic จริง — ใช้คู่กับ depends_on: condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user"]
interval: 5s
timeout: 3s
retries: 5Logging Drivers
Docker รองรับหลาย logging drivers — json-file (default), syslog, fluentd, awslogs เลือกให้เหมาะกับ infrastructure เช่น ใช้ awslogs ส่ง log ตรงไป CloudWatch
Docker in CI/CD
- Build image ใน CI pipeline แล้ว push ไป container registry
- ใช้ build cache (BuildKit) เพื่อเร่ง CI build
- Tag image ด้วย git SHA สำหรับ traceability
- ใช้ multi-stage build เพื่อ run tests ใน build stage
ปัญหาที่เจอบ่อย & วิธีแก้
Port already in use
Bind for 0.0.0.0:8080 failed: port is already allocated — port ถูกใช้อยู่แล้ว
วิธีแก้: หา process ที่ใช้ port อยู่ด้วย lsof -i :8080 แล้ว kill หรือเปลี่ยน port mapping เป็น -p 8081:3000
Container exits immediately
docker ps -a เห็น status Exited (1) — container start แล้วตายทันที
วิธีแก้: ดู log ด้วย docker logs myapp เพื่อหาสาเหตุ สาเหตุบ่อย: CMD ผิด, binary ไม่มีใน image, config file หาย, permission denied
Cannot connect between containers
Service A เรียก localhost:5432 ไปหา database แต่ connect ไม่ได้
วิธีแก้: ใน Docker network ต้องใช้ container name เป็น hostname ไม่ใช่ localhost เช่น postgres:5432 (ตาม service name ใน compose)
Image build ช้ามาก
ทุกครั้งที่ build ต้อง install dependencies ใหม่หมดทั้งที่ code เปลี่ยนแค่นิดเดียว
วิธีแก้: เรียงลำดับ COPY ใน Dockerfile ให้ copy dependency files (เช่น go.mod, package.json) ก่อน source code เพื่อให้ layer caching ทำงาน
Disk full / No space left on device
Docker กิน disk เยอะจาก dangling images, stopped containers, unused volumes
วิธีแก้: docker system df ดูว่าอะไรกินที่ แล้ว docker system prune -a --volumes ล้าง (ระวัง volumes ที่ยังใช้อยู่)
Permission denied ใน container
File ที่ COPY เข้าไปอ่านไม่ได้ หรือ write ไม่ได้เพราะ run ด้วย non-root user
วิธีแก้: เพิ่ม RUN chown -R 1001:1001 /app ก่อน USER 1001 ใน Dockerfile หรือ set file permissions ให้ถูกต้อง
Environment variables ไม่เข้า container
ตั้ง env ใน .env แล้วแต่ app อ่านไม่ได้
วิธีแก้: ตรวจว่า compose file มี env_file: .env หรือ environment: section ถูกต้อง ใช้ docker exec myapp env ตรวจว่า env เข้าจริงไหม
Volume mount ไม่ sync กับ host
แก้ไฟล์บน host แล้วแต่ container ไม่เห็นการเปลี่ยนแปลง (macOS)
วิธีแก้: macOS มี file sync delay กับ Docker — ลอง restart container หรือใช้ docker compose watch (Compose v2.22+) สำหรับ auto-sync ที่เร็วขึ้น
Related Skills
- Go — service ที่ run ใน container
- PostgreSQL — database ที่ run ผ่าน Docker Compose
- Kafka — message broker ใน containerized environment