spinny:~/writing $ less docker-containers-complete-guide.md
12Docker เปลี่ยนวิธีที่เราสร้าง ส่งมอบ และรันซอฟต์แวร์ แทนที่จะ "ทำงานได้บนเครื่องของฉัน" Docker รับประกันว่าแอปพลิเคชันของคุณจะทำงานเหมือนกันทุกที่ - บนแล็ปท็อปของคุณ, บนเครื่องของเพื่อนร่วมงาน, ใน CI/CD และใน production ในคู่มือนี้ เราจะเริ่มจากศูนย์ไปจนถึงการ deploy แอปพลิเคชันจริง34## Docker คืออะไร?56Docker เป็นแพลตฟอร์มที่แพ็กเกจแอปพลิเคชันของคุณและ dependency ทั้งหมดลงในหน่วยมาตรฐานที่เรียกว่า **คอนเทนเนอร์** คอนเทนเนอร์เป็นกระบวนการที่แยกตัวและเบา ซึ่งใช้เคอร์เนลของ OS โฮสต์ร่วมกัน แต่มีระบบไฟล์ เครือข่าย และพื้นที่กระบวนการของตัวเอง78```mermaid9graph TD10 subgraph "Traditional Deployment"11 A1[App 1] --> OS1[Guest OS]12 A2[App 2] --> OS2[Guest OS]13 OS1 --> HV[Hypervisor]14 OS2 --> HV15 HV --> HW1[Hardware]16 end1718 subgraph "Docker Deployment"19 B1[App 1] --> D1[Container]20 B2[App 2] --> D2[Container]21 D1 --> DE[Docker Engine]22 D2 --> DE23 DE --> HW2[Hardware]24 end25```2627### คอนเทนเนอร์ vs เครื่องเสมือน2829| ด้าน | คอนเทนเนอร์ | เครื่องเสมือน |30|------|-------------|-------------|31| **การเริ่มต้น** | วินาที | นาที |32| **ขนาด** | MB | GB |33| **OS** | ใช้เคอร์เนลโฮสต์ร่วมกัน | OS แขกเต็มรูปแบบ |34| **การแยกตัว** | ระดับกระบวนการ | ระดับฮาร์ดแวร์ |35| **ประสิทธิภาพ** | เกือบเท่า native | มี overhead จาก hypervisor |36| **ความหนาแน่น** | หลายร้อยต่อโฮสต์ | หลายสิบต่อโฮสต์ |3738## ติดตั้ง Docker3940```bash41# macOS42brew install --cask docker4344# Ubuntu/Debian45curl -fsSL https://get.docker.com | sh46sudo usermod -aG docker $USER4748# Verify installation49docker --version50docker run hello-world51```5253## แนวคิดหลัก5455### อิมเมจ5657อิมเมจเป็นเทมเพลตแบบอ่านอย่างเดียวที่มีคำสั่งสำหรับสร้างคอนเทนเนอร์ คิดว่ามันเป็นสแน็ปช็อตของแอปพลิเคชันและสภาพแวดล้อมของมัน5859```bash60# Pull an image from Docker Hub61docker pull node:20-alpine6263# List local images64docker images6566# Remove an image67docker rmi node:20-alpine68```6970### คอนเทนเนอร์7172คอนเทนเนอร์เป็นอินสแตนซ์ที่กำลังทำงานของอิมเมจ คุณสามารถสร้าง เริ่ม หยุด และลบคอนเทนเนอร์ได้7374```bash75# Run a container76docker run -d --name my-app -p 3000:3000 node:20-alpine7778# List running containers79docker ps8081# List all containers (including stopped)82docker ps -a8384# Stop a container85docker stop my-app8687# Remove a container88docker rm my-app8990# View logs91docker logs my-app9293# Execute a command inside a running container94docker exec -it my-app sh95```9697## การเขียน Dockerfile9899Dockerfile เป็นไฟล์ข้อความที่มีคำสั่งสำหรับสร้างอิมเมจ แต่ละคำสั่งจะสร้างเลเยอร์หนึ่ง100101### Dockerfile พื้นฐานสำหรับแอป Node.js102103```dockerfile104# Use an official Node.js runtime as base image105FROM node:20-alpine106107# Set working directory108WORKDIR /app109110# Copy package files first (better caching)111COPY package.json package-lock.json ./112113# Install dependencies114RUN npm ci --only=production115116# Copy application code117COPY . .118119# Expose the port the app runs on120EXPOSE 3000121122# Command to run the application123CMD ["node", "server.js"]124```125126### สร้างและรัน127128```bash129# Build the image130docker build -t my-node-app .131132# Run the container133docker run -d -p 3000:3000 my-node-app134135# Visit http://localhost:3000136```137138## Multi-Stage Build139140Multi-stage build รักษาอิมเมจ production ให้เล็กโดยแยกสภาพแวดล้อมการ build ออกจาก runtime141142```dockerfile143# Stage 1: Build144FROM node:20-alpine AS builder145WORKDIR /app146COPY package.json package-lock.json ./147RUN npm ci148COPY . .149RUN npm run build150151# Stage 2: Production152FROM node:20-alpine AS runner153WORKDIR /app154COPY --from=builder /app/dist ./dist155COPY --from=builder /app/node_modules ./node_modules156COPY --from=builder /app/package.json ./157EXPOSE 3000158CMD ["node", "dist/server.js"]159```160161สิ่งนี้สร้างอิมเมจที่มีเฉพาะผลลัพธ์ที่คอมไพล์แล้วและ dependency ของ production - ไม่มีซอร์สโค้ด, ไม่มี dependency ของการพัฒนา, ไม่มีเครื่องมือ build162163### ตัวอย่าง Multi-Stage สำหรับ Next.js164165```dockerfile166FROM node:20-alpine AS deps167WORKDIR /app168COPY package.json package-lock.json ./169RUN npm ci170171FROM node:20-alpine AS builder172WORKDIR /app173COPY --from=deps /app/node_modules ./node_modules174COPY . .175RUN npm run build176177FROM node:20-alpine AS runner178WORKDIR /app179ENV NODE_ENV=production180COPY --from=builder /app/public ./public181COPY --from=builder /app/.next/standalone ./182COPY --from=builder /app/.next/static ./.next/static183EXPOSE 3000184CMD ["node", "server.js"]185```186187## วอลุ่ม: ข้อมูลถาวร188189ตามค่าเริ่มต้น ข้อมูลภายในคอนเทนเนอร์จะหายไปเมื่อคอนเทนเนอร์ถูกลบ วอลุ่มแก้ปัญหานี้190191```bash192# Create a named volume193docker volume create my-data194195# Run with a volume196docker run -d -v my-data:/app/data my-app197198# Bind mount (map host directory to container)199docker run -d -v $(pwd)/data:/app/data my-app200201# List volumes202docker volume ls203```204205## เครือข่าย206207Docker สร้างเครือข่ายแบบแยกตัวเพื่อให้คอนเทนเนอร์สื่อสารกัน208209```bash210# Create a custom network211docker network create my-network212213# Run containers on the same network214docker run -d --name api --network my-network my-api215docker run -d --name db --network my-network postgres:16216217# Containers can reach each other by name218# From "api" container: postgres://db:5432219```220221```mermaid222graph LR223 subgraph "my-network"224 API[api container\nport 3000] -- "db:5432" --> DB[db container\nport 5432]225 end226 User -- "localhost:3000" --> API227```228229## Docker Compose230231Docker Compose ให้คุณกำหนดและรันแอปพลิเคชันหลายคอนเทนเนอร์ด้วยไฟล์ YAML เดียว232233### docker-compose.yml234235```yaml236services:237 api:238 build: ./api239 ports:240 - "3000:3000"241 environment:242 - DATABASE_URL=postgres://user:pass@db:5432/mydb243 depends_on:244 - db245246 db:247 image: postgres:16-alpine248 environment:249 - POSTGRES_USER=user250 - POSTGRES_PASSWORD=pass251 - POSTGRES_DB=mydb252 volumes:253 - pgdata:/var/lib/postgresql/data254 ports:255 - "5432:5432"256257 redis:258 image: redis:7-alpine259 ports:260 - "6379:6379"261262volumes:263 pgdata:264```265266### คำสั่ง267268```bash269# Start all services270docker compose up -d271272# View logs273docker compose logs -f274275# Stop all services276docker compose down277278# Rebuild and restart279docker compose up -d --build280281# Scale a service282docker compose up -d --scale api=3283```284285## .dockerignore286287เหมือนกับ `.gitignore` ไฟล์นี้ป้องกันไฟล์ที่ไม่จำเป็นไม่ให้ถูกคัดลอกเข้าไปในอิมเมจ288289```plaintext290node_modules291.git292.env293*.md294.next295dist296coverage297```298299## แนวปฏิบัติที่ดีที่สุดสำหรับ Production300301### 1. ใช้อิมเมจฐานที่เล็ก302303```dockerfile304# Bad: 1GB+305FROM node:20306307# Good: ~180MB308FROM node:20-alpine309```310311### 2. อย่ารันเป็น Root312313```dockerfile314FROM node:20-alpine315RUN addgroup -S app && adduser -S app -G app316USER app317WORKDIR /home/app318COPY --chown=app:app . .319```320321### 3. ใช้แท็กอิมเมจที่เฉพาะเจาะจง322323```dockerfile324# Bad: can change unexpectedly325FROM node:latest326327# Good: pinned version328FROM node:20.11-alpine3.19329```330331### 4. ใช้ประโยชน์จาก Build Cache332333จัดลำดับคำสั่ง Dockerfile จากที่เปลี่ยนน้อยที่สุดไปมากที่สุด:334335```dockerfile336FROM node:20-alpine337WORKDIR /app338339# These change rarely - cached340COPY package.json package-lock.json ./341RUN npm ci --only=production342343# This changes often - not cached344COPY . .345```346347### 5. Health Check348349```dockerfile350HEALTHCHECK --interval=30s --timeout=3s --retries=3 \351 CMD wget -qO- http://localhost:3000/health || exit 1352```353354### 6. ใช้ตัวแปรสภาพแวดล้อม355356```dockerfile357ENV NODE_ENV=production358ENV PORT=3000359```360361## สรุปคำสั่ง Docker ที่ใช้บ่อย362363```bash364# Images365docker build -t name:tag . # Build image366docker images # List images367docker rmi image_name # Remove image368docker image prune # Remove unused images369370# Containers371docker run -d -p 3000:3000 image # Run detached372docker ps # List running373docker stop container_name # Stop374docker rm container_name # Remove375docker logs -f container_name # Follow logs376docker exec -it container sh # Shell into container377378# Compose379docker compose up -d # Start services380docker compose down # Stop services381docker compose logs -f # Follow all logs382docker compose ps # List services383384# Cleanup385docker system prune -a # Remove everything unused386```387388## จาก Docker สู่ Kubernetes389390Docker จัดการคอนเทนเนอร์แต่ละตัว เมื่อคุณต้อง orchestrate คอนเทนเนอร์หลายร้อยตัวข้ามหลายเซิร์ฟเวอร์ คุณต้องการ Kubernetes Docker และ Kubernetes เป็นส่วนเสริมของกัน:3913921. **Docker**: สร้างและรันคอนเทนเนอร์3932. **Kubernetes**: orchestrate คอนเทนเนอร์ในระดับใหญ่ (การจัดตาราง, การปรับขนาด, การซ่อมแซมอัตโนมัติ)394395หากคุณสนใจขั้นตอนถัดไป ลองอ่านบทความของผมเกี่ยวกับ Introduction to Kubernetes396397## สรุป398399Docker เป็นทักษะพื้นฐานสำหรับนักพัฒนาสมัยใหม่ มันขจัดความไม่สอดคล้องกันของสภาพแวดล้อม ทำให้การ deploy ง่ายขึ้น และเป็นรากฐานสำหรับการ orchestrate คอนเทนเนอร์ด้วย Kubernetes เริ่มต้นด้วย Dockerfile อย่างง่าย ย้ายไปยัง Docker Compose สำหรับแอปหลายบริการ และนำ multi-stage build และแนวปฏิบัติด้านความปลอดภัยที่ดีที่สุดมาใช้เมื่อคุณเติบโต400401วิธีที่ดีที่สุดในการเรียนรู้ Docker คือการทำ containerize โปรเจกต์ที่คุณกำลังทำอยู่ เริ่มวันนี้402
:Docker สำหรับผู้เริ่มต้น: จาก Image แรกสู่การ Deploy ใน Productionlines 1-402 (END) — press q to close