Docker เบื้องต้น: คู่มือฉบับสมบูรณ์

Introduction

ในยุคที่เทคโนโลยีพัฒนาอย่างรวดเร็ว การพัฒนาและ deploy แอปพลิเคชันต้องการความยืดหยุ่นและประสิทธิภาพสูง Docker เป็นเทคโนโลยีที่ปฏิวัติวงการ DevOps และ Software Development ด้วยการนำเสนอแนวคิดของ Containerization ที่ทำให้การพัฒนา testing และ deployment แอปพลิเคชันง่ายและรวดเร็วขึ้นอย่างมาก

ปัญหาที่ Docker ช่วยแก้ไข

ก่อนที่จะมี Docker นักพัฒนาต้องเจอปัญหาเหล่านี้บ่อยครั้ง:


Docker คืออะไร

Docker เป็น open-source platform ที่ใช้สำหรับพัฒนา shipping และรันแอปพลิเคชันภายใน containers ซึ่ง containers เป็นหน่วยมาตรฐานของซอฟต์แวร์ที่รวม code และ dependencies ทั้งหมดไว้ด้วยกัน ทำให้แอปพลิเคชันสามารถทำงานได้อย่างรวดเร็วและเชื่อถือได้ในสภาพแวดล้อมที่แตกต่างกัน

คุณสมบัติหลักของ Docker


Container vs Virtualization

เพื่อเข้าใจ Docker ให้ดีขึ้น เราต้องเข้าใจความแตกต่างระหว่าง Containerization กับ Virtualization

Traditional Virtualization (Virtual Machines)

graph TB
    subgraph "Physical Server"
        Hardware[Hardware/Infrastructure]
        HostOS[Host Operating System]
        Hypervisor[Hypervisor]
        
        subgraph VM1["Virtual Machine 1"]
            GuestOS1[Guest OS]
            Bins1[Binaries/Libraries]
            App1[Application 1]
        end
        
        subgraph VM2["Virtual Machine 2"]
            GuestOS2[Guest OS]
            Bins2[Binaries/Libraries]
            App2[Application 2]
        end
        
        subgraph VM3["Virtual Machine 3"]
            GuestOS3[Guest OS]
            Bins3[Binaries/Libraries]
            App3[Application 3]
        end
    end
    
    Hardware --> HostOS
    HostOS --> Hypervisor
    Hypervisor --> VM1
    Hypervisor --> VM2
    Hypervisor --> VM3

Virtual Machines ทำงานโดย:

Containerization (Docker)

graph TB
    subgraph "Physical Server"
        Hardware2[Hardware/Infrastructure]
        HostOS2[Host Operating System]
        DockerEngine[Docker Engine]
        
        subgraph Container1["Container 1"]
            Bins4[Binaries/Libraries]
            App4[Application 1]
        end
        
        subgraph Container2["Container 2"]
            Bins5[Binaries/Libraries]
            App5[Application 2]
        end
        
        subgraph Container3["Container 3"]
            Bins6[Binaries/Libraries]
            App6[Application 3]
        end
    end
    
    Hardware2 --> HostOS2
    HostOS2 --> DockerEngine
    DockerEngine --> Container1
    DockerEngine --> Container2
    DockerEngine --> Container3

Containers ทำงานโดย:

ตารางเปรียบเทียบ

คุณสมบัติ Virtual Machines Containers
ขนาด GBs (รวม OS เต็มระบบ) MBs (เฉพาะ app และ dependencies)
Startup Time นาที วินาที
ประสิทธิภาพ น้อยกว่า (overhead จาก virtualization) ใกล้เคียง native
Isolation สมบูรณ์แบบ (Hardware-level) Process-level
Resource Usage สูง ต่ำ
Portability ต่ำ (ขึ้นกับ hypervisor) สูง (รันได้ทุกที่ที่มี Docker)

สถาปัตยกรรมของ Docker

Docker ใช้สถาปัตยกรรมแบบ client-server มาทำงาน

graph LR
    Client[Docker Client
docker CLI] Daemon[Docker Daemon
dockerd] Registry[Docker Registry
Docker Hub] Client -->|REST API| Daemon Daemon -->|Pull/Push| Registry subgraph "Docker Host" Daemon Images[(Images)] Containers[Containers] Volumes[(Volumes)] Networks[Networks] end Daemon --> Images Daemon --> Containers Daemon --> Volumes Daemon --> Networks

ส่วนประกอบหลักของ Docker

1. Docker Client

2. Docker Daemon (dockerd)

3. Docker Images

4. Docker Containers

5. Docker Registry


การติดตั้ง Docker

ตรวจสอบการติดตั้ง

หลังจากติดตั้งแล้ว ให้ตรวจสอบว่า Docker ทำงานได้:

# ตรวจสอบ version
docker --version

# ตรวจสอบข้อมูลระบบ
docker info

# ทดสอบรัน container แรก
docker run hello-world

ผลลัพธ์ที่ควรได้:

Hello from Docker!
This message shows that your installation appears to be working correctly.

Docker Images

Image คือ template สำหรับสร้าง containers ประกอบด้วย layers ของ filesystem และ metadata

graph TD
    A[Base Image
Ubuntu 20.04] --> B[Layer 2
Install Python] B --> C[Layer 3
Copy App Code] C --> D[Layer 4
Install Dependencies] D --> E[Final Image
My App:v1.0] style A fill:#e1f5ff style B fill:#b3e5fc style C fill:#81d4fa style D fill:#4fc3f7 style E fill:#29b6f6

คำสั่งจัดการ Images

1. ค้นหา Images บน Docker Hub

# ค้นหา image ของ nginx
docker search nginx

# ค้นหาแบบจำกัดผลลัพธ์
docker search --limit 5 nginx

2. ดาวน์โหลด (Pull) Images

# Pull image เวอร์ชันล่าสุด
docker pull nginx

# Pull image เวอร์ชันเฉพาะ (แนะนำ)
docker pull nginx:1.25.3

# Pull image จาก official repository
docker pull ubuntu:22.04

# Pull image จาก user/organization
docker pull mysql:8.0

3. แสดงรายการ Images

# แสดง images ทั้งหมด
docker images

# แสดงแบบละเอียด
docker images --all

# แสดงเฉพาะ Image IDs
docker images -q

# กรองตาม repository name
docker images nginx

ตัวอย่างผลลัพธ์:

REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nginx        latest    605c77e624dd   2 weeks ago    141MB
nginx        1.25.3    605c77e624dd   2 weeks ago    141MB
ubuntu       22.04     174c8c134b2a   3 weeks ago    77.8MB
mysql        8.0       3218b38490ce   4 weeks ago    517MB

4. ดูข้อมูลละเอียดของ Image

# ดูข้อมูลเต็มของ image
docker inspect nginx:latest

# ดูประวัติการสร้าง layers
docker history nginx:latest

# ดู metadata เฉพาะส่วน
docker inspect --format='{{.Architecture}}' nginx:latest

5. ลบ Images

# ลบ image ตาม name:tag
docker rmi nginx:1.25.3

# ลบ image ตาม Image ID
docker rmi 605c77e624dd

# บังคับลบ (ถึงแม้มี container ใช้งานอยู่)
docker rmi -f nginx:latest

# ลบ images ที่ไม่มี tag (dangling images)
docker image prune

# ลบ images ทั้งหมดที่ไม่ได้ใช้งาน
docker image prune -a

สร้าง Image จาก Dockerfile

Dockerfile เป็นไฟล์ text ที่มีคำสั่งสำหรับสร้าง image

ตัวอย่างที่ 1: Simple Python Application

สร้างไฟล์โครงสร้างดังนี้:

my-python-app/
├── Dockerfile
├── app.py
└── requirements.txt

app.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    return 'Hello from Docker Container!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

requirements.txt:

flask==3.0.0

Dockerfile:

# เริ่มจาก base image
FROM python:3.11-slim

# ตั้ง working directory
WORKDIR /app

# Copy requirements file
COPY requirements.txt .

# ติดตั้ง dependencies
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY app.py .

# เปิด port
EXPOSE 5000

# คำสั่งรัน application
CMD ["python", "app.py"]

สร้าง Image:

# Build image พร้อมตั้งชื่อและ tag
docker build -t my-python-app:1.0 .

# Build แบบไม่ใช้ cache
docker build --no-cache -t my-python-app:1.0 .

# ดู build process แบบละเอียด
docker build -t my-python-app:1.0 . --progress=plain

ตัวอย่างที่ 2: Node.js Application

Dockerfile:

FROM node:18-alpine

WORKDIR /usr/src/app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm install

# Copy app source
COPY . .

EXPOSE 3000

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

Build Command:

docker build -t my-node-app:latest .

6. Tag Images

# สร้าง tag ใหม่สำหรับ image ที่มีอยู่
docker tag my-python-app:1.0 my-python-app:latest

# สร้าง tag สำหรับ push ไปยัง registry
docker tag my-python-app:1.0 username/my-python-app:1.0

# Tag พร้อมชื่อ registry
docker tag my-python-app:1.0 myregistry.com:5000/my-python-app:1.0

7. Push Images ไปยัง Registry

# Login เข้า Docker Hub
docker login

# Push image
docker push username/my-python-app:1.0

# Push ทุก tags
docker push --all-tags username/my-python-app

8. Save และ Load Images

# Save image เป็นไฟล์ tar
docker save -o my-python-app.tar my-python-app:1.0

# Save หลาย images
docker save -o my-images.tar nginx:latest ubuntu:22.04

# Load image จากไฟล์
docker load -i my-python-app.tar

# Load และแสดง output
docker load < my-python-app.tar

Docker Containers

Container คือ runnable instance ของ image ที่สามารถ start, stop, move และ delete ได้

Lifecycle ของ Container

stateDiagram-v2
    [*] --> Created: docker create
    Created --> Running: docker start
    Running --> Paused: docker pause
    Paused --> Running: docker unpause
    Running --> Stopped: docker stop
    Stopped --> Running: docker start
    Running --> Killed: docker kill
    Killed --> [*]
    Stopped --> [*]: docker rm
    Created --> [*]: docker rm

คำสั่ง docker run

docker run เป็นคำสั่งที่รวม create และ start เข้าด้วยกัน

รูปแบบพื้นฐาน

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

ตัวอย่างที่ 1: รัน Container แบบง่าย

# รัน nginx container
docker run nginx

# รัน container แบบ detached (background)
docker run -d nginx

# รัน container พร้อมตั้งชื่อ
docker run -d --name my-nginx nginx

# รัน container พร้อม publish port
docker run -d -p 8080:80 --name web-server nginx

อธิบาย options:

ตัวอย่างที่ 2: รัน Container แบบ Interactive

# รัน Ubuntu container แบบ interactive
docker run -it ubuntu bash

# รันคำสั่งใน container แล้วออก
docker run ubuntu echo "Hello Docker"

# รัน container พร้อม environment variables
docker run -it -e "MY_VAR=Hello" ubuntu bash
# ใน container: echo $MY_VAR

# รัน Alpine Linux (lightweight)
docker run -it alpine sh

อธิบาย options:

ตัวอย่างที่ 3: Port Mapping

# Map single port
docker run -d -p 8080:80 nginx

# Map multiple ports
docker run -d -p 8080:80 -p 8443:443 nginx

# Map ทุก ports ที่ expose (แบบสุ่ม)
docker run -d -P nginx

# Map specific IP address
docker run -d -p 127.0.0.1:8080:80 nginx

# ตรวจสอบ port mapping
docker port my-nginx

ตัวอย่างที่ 4: จำกัดทรัพยากร

# จำกัด memory
docker run -d --memory="512m" nginx

# จำกัด CPU
docker run -d --cpus="1.5" nginx

# จำกัดทั้ง memory และ CPU
docker run -d \
  --memory="1g" \
  --memory-swap="2g" \
  --cpus="2" \
  --name limited-nginx \
  nginx

# ดูการใช้ทรัพยากร real-time
docker stats limited-nginx

ตัวอย่างที่ 5: Environment Variables

# ตั้งค่า environment variable เดียว
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql:8.0

# ตั้งค่าหลาย environment variables
docker run -d \
  -e MYSQL_ROOT_PASSWORD=secret \
  -e MYSQL_DATABASE=myapp \
  -e MYSQL_USER=appuser \
  -e MYSQL_PASSWORD=apppass \
  --name mysql-server \
  mysql:8.0

# ใช้ env file
# สร้างไฟล์ db.env
# MYSQL_ROOT_PASSWORD=secret
# MYSQL_DATABASE=myapp
docker run -d --env-file db.env mysql:8.0

ตัวอย่างที่ 6: Auto-restart Container

# ไม่ restart อัตโนมัติ (default)
docker run -d --restart=no nginx

# Restart เสมอ
docker run -d --restart=always --name always-nginx nginx

# Restart เมื่อ fail เท่านั้น
docker run -d --restart=on-failure --name onfail-nginx nginx

# Restart เมื่อ fail พร้อมจำกัดจำนวนครั้ง
docker run -d --restart=on-failure:5 nginx

# Restart เว้นแต่จะ stop ด้วยตัวเอง
docker run -d --restart=unless-stopped nginx

จัดการ Containers

1. แสดงรายการ Containers

# แสดง containers ที่กำลังรันอยู่
docker ps

# แสดง containers ทั้งหมด (รวมที่หยุดแล้ว)
docker ps -a

# แสดงเฉพาะ Container IDs
docker ps -q

# แสดงแบบ custom format
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.Status}}"

# แสดง containers ล่าสุด (5 ตัว)
docker ps -n 5

2. ดูรายละเอียด Container

# ดูข้อมูลทั้งหมดของ container
docker inspect my-nginx

# ดูข้อมูลเฉพาะส่วน
docker inspect --format='{{.NetworkSettings.IPAddress}}' my-nginx

# ดู logs
docker logs my-nginx

# ดู logs แบบ follow (real-time)
docker logs -f my-nginx

# ดู logs พร้อม timestamp
docker logs -t my-nginx

# ดู logs จำนวนจำกัด
docker logs --tail 50 my-nginx

3. จัดการ Container Lifecycle

# Start container ที่หยุดอยู่
docker start my-nginx

# Stop container (graceful shutdown)
docker stop my-nginx

# Stop พร้อมกำหนด timeout
docker stop -t 30 my-nginx

# Restart container
docker restart my-nginx

# Pause container (หยุดชั่วคราว)
docker pause my-nginx

# Unpause container
docker unpause my-nginx

# Kill container (force stop)
docker kill my-nginx

# Kill ด้วย specific signal
docker kill -s SIGTERM my-nginx

4. รันคำสั่งใน Container ที่กำลังทำงาน

# รันคำสั่งใน container
docker exec my-nginx ls -la

# เข้าไปใช้ bash ใน container
docker exec -it my-nginx bash

# รันคำสั่งในฐานะ specific user
docker exec -u root -it my-nginx bash

# รันคำสั่งใน working directory เฉพาะ
docker exec -w /var/log -it my-nginx bash

# รันคำสั่งพร้อม environment variable
docker exec -e MY_VAR=test my-nginx env

5. Copy Files ระหว่าง Host และ Container

# Copy จาก host ไป container
docker cp myfile.txt my-nginx:/usr/share/nginx/html/

# Copy จาก container มา host
docker cp my-nginx:/var/log/nginx/access.log ./

# Copy ทั้ง directory
docker cp ./my-website/. my-nginx:/usr/share/nginx/html/

# Copy พร้อม preserve ownership
docker cp --archive my-nginx:/app/data ./backup

6. ลบ Containers

# ลบ container ที่หยุดแล้ว
docker rm my-nginx

# บังคับลบ container ที่กำลังรัน
docker rm -f my-nginx

# ลบหลาย containers
docker rm container1 container2 container3

# ลบ containers ทั้งหมดที่หยุดแล้ว
docker container prune

# ลบ containers ทั้งหมด (รวมที่กำลังรัน)
docker rm -f $(docker ps -aq)

ตัวอย่างการใช้งานจริง

ตัวอย่างที่ 1: รัน Web Server

# รัน Nginx web server
docker run -d \
  --name my-website \
  -p 8080:80 \
  -v $(pwd)/html:/usr/share/nginx/html:ro \
  --restart=unless-stopped \
  nginx:latest

# ทดสอบ
curl http://localhost:8080

ตัวอย่างที่ 2: รัน MySQL Database

# รัน MySQL container
docker run -d \
  --name mysql-db \
  -e MYSQL_ROOT_PASSWORD=rootpass123 \
  -e MYSQL_DATABASE=myapp \
  -e MYSQL_USER=appuser \
  -e MYSQL_PASSWORD=apppass123 \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  --restart=always \
  mysql:8.0

# เชื่อมต่อเข้า MySQL
docker exec -it mysql-db mysql -u root -p

# Backup database
docker exec mysql-db mysqldump -u root -prootpass123 myapp > backup.sql

# Restore database
docker exec -i mysql-db mysql -u root -prootpass123 myapp < backup.sql

ตัวอย่างที่ 3: รัน Redis Cache

# รัน Redis
docker run -d \
  --name redis-cache \
  -p 6379:6379 \
  -v redis-data:/data \
  --restart=always \
  redis:alpine redis-server --appendonly yes

# ทดสอบ Redis
docker exec -it redis-cache redis-cli
# ใน redis-cli: SET mykey "Hello Docker"
# ใน redis-cli: GET mykey

ตัวอย่างที่ 4: รัน MongoDB

# รัน MongoDB
docker run -d \
  --name mongodb \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=adminpass \
  -p 27017:27017 \
  -v mongo-data:/data/db \
  --restart=always \
  mongo:7.0

# เชื่อมต่อเข้า MongoDB
docker exec -it mongodb mongosh -u admin -p adminpass

Docker Networks

Docker Networks ช่วยให้ containers สามารถสื่อสารกันได้ และควบคุมการเข้าถึงจากภายนอก

graph TB
    subgraph "Docker Host"
        subgraph "Bridge Network (default)"
            C1[Container 1
172.17.0.2] C2[Container 2
172.17.0.3] end subgraph "Custom Bridge Network" C3[Container 3
my-app] C4[Container 4
my-db] end subgraph "Host Network" C5[Container 5
uses host network] end C1 <--> C2 C3 <--> C4 end Host[Host Machine] <--> C1 Host <--> C2 Host <--> C3 Host <--> C4 Host <--> C5 Internet[Internet] <--> Host

ประเภทของ Docker Networks

1. Bridge Network (default)

2. Host Network

3. None Network

4. Custom Bridge Network

คำสั่งจัดการ Networks

1. แสดงรายการ Networks

# แสดง networks ทั้งหมด
docker network ls

# แสดงแบบ custom format
docker network ls --format "table {{.Name}}\t{{.Driver}}\t{{.Scope}}"

# กรองตาม driver
docker network ls --filter driver=bridge

2. ดูรายละเอียด Network

# ดูข้อมูล network
docker network inspect bridge

# ดูเฉพาะ containers ใน network
docker network inspect --format='{{json .Containers}}' bridge | jq

3. สร้าง Custom Network

# สร้าง bridge network
docker network create my-network

# สร้าง network พร้อมกำหนด subnet
docker network create \
  --driver bridge \
  --subnet=172.20.0.0/16 \
  --gateway=172.20.0.1 \
  my-custom-network

# สร้าง network พร้อม options เพิ่มเติม
docker network create \
  --driver bridge \
  --subnet=172.25.0.0/16 \
  --ip-range=172.25.5.0/24 \
  --gateway=172.25.0.1 \
  --label env=production \
  prod-network

4. เชื่อมต่อและตัดการเชื่อมต่อ

# เชื่อมต่อ container เข้า network
docker network connect my-network my-container

# เชื่อมต่อพร้อมกำหนด IP
docker network connect --ip 172.20.0.10 my-network my-container

# เชื่อมต่อพร้อมกำหนด alias
docker network connect --alias db my-network mysql-container

# ตัดการเชื่อมต่อ
docker network disconnect my-network my-container

# บังคับตัดการเชื่อมต่อ
docker network disconnect -f my-network my-container

5. ลบ Networks

# ลบ network
docker network rm my-network

# ลบหลาย networks
docker network rm network1 network2

# ลบ networks ที่ไม่ได้ใช้งาน
docker network prune

# บังคับลบทั้งหมด
docker network prune -f

ตัวอย่างการใช้งาน Networks

ตัวอย่างที่ 1: Default Bridge Network

# รัน containers บน default bridge
docker run -d --name web1 nginx
docker run -d --name web2 nginx

# ตรวจสอบ IP ของ containers
docker inspect web1 | grep IPAddress
docker inspect web2 | grep IPAddress

# ทดสอบการเชื่อมต่อระหว่าง containers (ต้องใช้ IP)
docker exec web1 ping -c 3 <IP-ของ-web2>

# ⚠️ ไม่สามารถใช้ชื่อ container ได้
docker exec web1 ping web2  # จะไม่สำเร็จ

ตัวอย่างที่ 2: Custom Bridge Network (แนะนำ)

# สร้าง custom network
docker network create my-app-network

# รัน containers บน custom network
docker run -d --name web --network my-app-network nginx
docker run -d --name db --network my-app-network mysql:8.0

# ทดสอบการเชื่อมต่อ (ใช้ชื่อได้)
docker exec web ping -c 3 db

# ใช้ DNS resolution
docker exec web nslookup db

# รัน container ใหม่บน network เดียวกัน
docker run -d \
  --name api \
  --network my-app-network \
  -e DB_HOST=db \
  my-api-image

ตัวอย่างที่ 3: Host Network

# รัน container บน host network
docker run -d --network host nginx

# Container จะใช้ ports ของ host โดยตรง
# ไม่ต้อง publish ports (-p)

# ดู network interfaces
docker run --network host alpine ip addr show

ตัวอย่างที่ 4: None Network

# รัน container โดยไม่มี network
docker run -d --network none alpine sleep 3600

# ทดสอบว่าไม่มี network
docker exec <container-id> ip addr show
# จะเห็นแค่ loopback interface

ตัวอย่างที่ 5: Multi-Network Container

# สร้าง 2 networks
docker network create frontend-network
docker network create backend-network

# รัน database บน backend network
docker run -d \
  --name postgres-db \
  --network backend-network \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

# รัน API server เชื่อมต่อทั้ง 2 networks
docker run -d \
  --name api-server \
  --network frontend-network \
  my-api:latest

# เชื่อมต่อ API เข้า backend network
docker network connect backend-network api-server

# ตอนนี้ api-server สามารถเข้าถึง postgres-db ได้
# และรับ requests จาก frontend-network ได้

ตัวอย่างที่ 6: Application Stack

ตัวอย่างการสร้าง web application stack ที่สมบูรณ์:

# 1. สร้าง networks
docker network create frontend-net
docker network create backend-net

# 2. รัน database (backend เท่านั้น)
docker run -d \
  --name postgres \
  --network backend-net \
  -e POSTGRES_DB=myapp \
  -e POSTGRES_USER=appuser \
  -e POSTGRES_PASSWORD=apppass \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:15

# 3. รัน Redis cache (backend เท่านั้น)
docker run -d \
  --name redis \
  --network backend-net \
  -v redis-data:/data \
  redis:alpine

# 4. รัน API server (ทั้ง frontend และ backend)
docker run -d \
  --name api \
  --network backend-net \
  -e DATABASE_URL=postgresql://appuser:apppass@postgres:5432/myapp \
  -e REDIS_URL=redis://redis:6379 \
  my-api:latest

docker network connect frontend-net api

# 5. รัน web frontend (frontend เท่านั้น)
docker run -d \
  --name webapp \
  --network frontend-net \
  -p 80:80 \
  -e API_URL=http://api:8000 \
  my-webapp:latest

# 6. รัน Nginx reverse proxy
docker run -d \
  --name nginx \
  --network frontend-net \
  -p 443:443 \
  -v ./nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:alpine

โครงสร้าง Network:

graph TB
    Internet[Internet]
    
    subgraph "Frontend Network"
        Nginx[Nginx
Reverse Proxy] WebApp[Web App
Frontend] end subgraph "Backend Network" API[API Server] Postgres[PostgreSQL
Database] Redis[Redis
Cache] end Internet --> Nginx Nginx --> WebApp WebApp --> API API --> Postgres API --> Redis style Frontend Network fill:#e3f2fd style Backend Network fill:#fff3e0

DNS Resolution ใน Docker Networks

# สร้าง network และ containers
docker network create test-net
docker run -d --name server1 --network test-net nginx
docker run -d --name server2 --network test-net nginx

# ทดสอบ DNS resolution
docker exec server1 ping -c 2 server2
docker exec server1 nslookup server2

# ดู DNS entries
docker exec server1 cat /etc/hosts
docker exec server1 cat /etc/resolv.conf

# ใช้ network alias
docker run -d --name db \
  --network test-net \
  --network-alias database \
  --network-alias mysql-server \
  mysql:8.0

# ตอนนี้สามารถเข้าถึงได้ทั้ง 3 ชื่อ:
# - db
# - database
# - mysql-server

Docker Volumes

Volumes เป็นกลไกสำหรับเก็บข้อมูลถาวร (persistent data) และแชร์ข้อมูลระหว่าง containers

graph LR
    subgraph "Host Filesystem"
        HostDir["/host/data"]
        DockerVolumes["/var/lib/docker/volumes/"]
    end
    
    subgraph "Container 1"
        App1[Application]
        Mount1["/app/data"]
    end
    
    subgraph "Container 2"
        App2[Application]
        Mount2["/app/data"]
    end
    
    HostDir -.Bind Mount.-> Mount1
    DockerVolumes -->|Named Volume| Mount2
    
    style DockerVolumes fill:#bbdefb
    style HostDir fill:#c8e6c9

ประเภทของ Volume Mounts

1. Named Volumes (แนะนำ)

2. Bind Mounts

3. tmpfs Mounts

คำสั่งจัดการ Volumes

1. แสดงรายการ Volumes

# แสดง volumes ทั้งหมด
docker volume ls

# กรอง dangling volumes
docker volume ls --filter dangling=true

# แสดงแบบ custom format
docker volume ls --format "table {{.Name}}\t{{.Driver}}\t{{.Mountpoint}}"

2. สร้าง Volumes

# สร้าง named volume
docker volume create my-volume

# สร้าง volume พร้อม label
docker volume create --label env=production prod-data

# สร้าง volume พร้อม driver options
docker volume create \
  --driver local \
  --opt type=none \
  --opt device=/path/on/host \
  --opt o=bind \
  custom-volume

3. ตรวจสอบ Volume

# ดูข้อมูล volume
docker volume inspect my-volume

# ดูตำแหน่งบน host
docker volume inspect --format='{{.Mountpoint}}' my-volume

# ดูว่า volume ใช้โดย containers ใดบ้าง
docker ps -a --filter volume=my-volume

4. ลบ Volumes

# ลบ volume
docker volume rm my-volume

# ลบหลาย volumes
docker volume rm vol1 vol2 vol3

# ลบ volumes ที่ไม่ได้ใช้งาน
docker volume prune

# ลบ volumes ทั้งหมดที่ไม่ได้ใช้ (ระวัง!)
docker volume prune -a

# บังคับลบ
docker volume prune -f

ตัวอย่างการใช้งาน Volumes

ตัวอย่างที่ 1: Named Volume

# สร้าง volume
docker volume create mysql-data

# รัน MySQL พร้อม named volume
docker run -d \
  --name mysql-db \
  -e MYSQL_ROOT_PASSWORD=secret \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

# ตรวจสอบว่า volume ถูกใช้งาน
docker volume inspect mysql-data

# รัน container ตัวใหม่ใช้ volume เดียวกัน
docker run -d \
  --name mysql-backup \
  -v mysql-data:/var/lib/mysql:ro \
  mysql:8.0

# ข้อมูลจะยังอยู่แม้ลบ container
docker rm -f mysql-db
docker volume ls  # mysql-data ยังอยู่

ตัวอย่างที่ 2: Bind Mount (Development)

# สร้าง directory บน host
mkdir -p ~/my-website/html
echo "<h1>Hello Docker</h1>" > ~/my-website/html/index.html

# Mount directory จาก host
docker run -d \
  --name dev-server \
  -p 8080:80 \
  -v ~/my-website/html:/usr/share/nginx/html \
  nginx

# แก้ไขไฟล์บน host
echo "<h1>Updated Content</h1>" > ~/my-website/html/index.html
# การเปลี่ยนแปลงจะเห็นทันทีที่ http://localhost:8080

# Mount แบบ read-only
docker run -d \
  --name prod-server \
  -p 8081:80 \
  -v ~/my-website/html:/usr/share/nginx/html:ro \
  nginx

ตัวอย่างที่ 3: Sharing Volumes ระหว่าง Containers

# สร้าง volume สำหรับ shared data
docker volume create shared-data

# Container 1: เขียนข้อมูล
docker run -d \
  --name writer \
  -v shared-data:/data \
  alpine \
  sh -c "while true; do echo $(date) >> /data/log.txt; sleep 5; done"

# Container 2: อ่านข้อมูล
docker run -d \
  --name reader \
  -v shared-data:/data:ro \
  alpine \
  sh -c "while true; do tail -f /data/log.txt; sleep 1; done"

# ดู logs ของ reader
docker logs -f reader

# Container 3: Backup data
docker run --rm \
  -v shared-data:/source:ro \
  -v $(pwd)/backup:/backup \
  alpine \
  tar czf /backup/shared-data-backup.tar.gz -C /source .

ตัวอย่างที่ 4: Volume สำหรับ Database

# PostgreSQL
docker run -d \
  --name postgres \
  -e POSTGRES_PASSWORD=secret \
  -e POSTGRES_DB=myapp \
  -v postgres-data:/var/lib/postgresql/data \
  -p 5432:5432 \
  postgres:15

# MongoDB
docker run -d \
  --name mongodb \
  -e MONGO_INITDB_ROOT_USERNAME=admin \
  -e MONGO_INITDB_ROOT_PASSWORD=secret \
  -v mongo-data:/data/db \
  -v mongo-config:/data/configdb \
  -p 27017:27017 \
  mongo:7.0

# Redis with persistence
docker run -d \
  --name redis \
  -v redis-data:/data \
  -p 6379:6379 \
  redis:alpine redis-server --appendonly yes

ตัวอย่างที่ 5: Backup และ Restore Volumes

Backup Volume:

# สร้างและใช้งาน volume
docker volume create app-data
docker run -d --name app -v app-data:/data alpine sleep 3600

# เพิ่มข้อมูลทดสอบ
docker exec app sh -c "echo 'Important data' > /data/file.txt"

# Backup volume เป็น tar file
docker run --rm \
  -v app-data:/source:ro \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/app-data-backup-$(date +%Y%m%d).tar.gz -C /source .

# ตรวจสอบ backup file
ls -lh app-data-backup-*.tar.gz

Restore Volume:

# สร้าง volume ใหม่
docker volume create app-data-restored

# Restore จาก backup file
docker run --rm \
  -v app-data-restored:/target \
  -v $(pwd):/backup \
  alpine \
  sh -c "cd /target && tar xzf /backup/app-data-backup-20241104.tar.gz"

# ตรวจสอบข้อมูล
docker run --rm -v app-data-restored:/data alpine cat /data/file.txt

ตัวอย่างที่ 6: tmpfs Mount

# Mount tmpfs สำหรับข้อมูลชั่วคราว
docker run -d \
  --name app-with-tmpfs \
  --tmpfs /tmp:rw,size=100m,mode=1777 \
  --tmpfs /run:rw,size=50m \
  nginx

# ข้อมูลใน /tmp และ /run จะหายเมื่อหยุด container
docker exec app-with-tmpfs sh -c "echo 'temp data' > /tmp/temp.txt"
docker restart app-with-tmpfs
docker exec app-with-tmpfs cat /tmp/temp.txt  # ไฟล์หายไป

ตัวอย่างที่ 7: Copy Data ระหว่าง Volumes

# สร้าง source และ destination volumes
docker volume create source-vol
docker volume create dest-vol

# เพิ่มข้อมูลใน source volume
docker run --rm -v source-vol:/data alpine \
  sh -c "echo 'Original data' > /data/file.txt"

# Copy ข้อมูลจาก source ไป destination
docker run --rm \
  -v source-vol:/source:ro \
  -v dest-vol:/dest \
  alpine \
  cp -av /source/. /dest/

# ตรวจสอบผลลัพธ์
docker run --rm -v dest-vol:/data alpine cat /data/file.txt

Best Practices สำหรับ Volumes

1. ตั้งชื่อ Volume อย่างชัดเจน

# ดี - ชื่อบอกจุดประสงค์
docker volume create postgres-prod-data
docker volume create redis-cache-dev

# ไม่ดี - ชื่อไม่ชัดเจน
docker volume create vol1
docker volume create data

2. ใช้ Labels สำหรับการจัดกลุ่ม

# สร้าง volumes พร้อม labels
docker volume create \
  --label env=production \
  --label app=myapp \
  --label backup=daily \
  myapp-prod-data

# Filter volumes ตาม label
docker volume ls --filter label=env=production

3. Backup Volumes เป็นประจำ

# Script สำหรับ backup ทุกวัน
#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d)

for VOLUME in $(docker volume ls -q); do
  docker run --rm \
    -v $VOLUME:/source:ro \
    -v $BACKUP_DIR:/backup \
    alpine \
    tar czf /backup/${VOLUME}-${DATE}.tar.gz -C /source .
done

4. ทำความสะอาด Unused Volumes

# แสดง volumes ที่ไม่ได้ใช้งาน
docker volume ls --filter dangling=true

# ลบ volumes ที่ไม่ได้ใช้งาน
docker volume prune

# ตรวจสอบก่อนลบ
docker volume prune --dry-run

แนวทางปฏิบัติที่ดี (Best Practices)

1. Security Best Practices

ใช้ Official Images

# ดี - ใช้ official image
docker pull nginx
docker pull postgres:15

# ระวัง - third-party images
docker pull randomuser/nginx

รัน Containers ในฐานะ Non-root User

# ใน Dockerfile
FROM node:18-alpine

# สร้าง user
RUN addgroup -g 1001 appgroup && \
    adduser -D -u 1001 -G appgroup appuser

# เปลี่ยนเป็น non-root user
USER appuser

WORKDIR /app
COPY --chown=appuser:appgroup . .

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

จำกัดทรัพยากร

# จำกัด memory และ CPU
docker run -d \
  --name limited-app \
  --memory="512m" \
  --memory-swap="1g" \
  --cpus="1.0" \
  --pids-limit=100 \
  my-app:latest

ใช้ Read-only Filesystem เมื่อเป็นไปได้

# รัน container แบบ read-only
docker run -d \
  --name readonly-app \
  --read-only \
  --tmpfs /tmp \
  nginx

2. Image Best Practices

ใช้ Specific Tags แทน Latest

# ดี - specific version
docker pull nginx:1.25.3
docker pull node:18.17-alpine

# หลีกเลี่ยง - latest tag
docker pull nginx:latest

ใช้ Multi-stage Builds

# Build stage
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package*.json ./

USER node
EXPOSE 3000
CMD ["node", "dist/index.js"]

เรียง Layers อย่างมีประสิทธิภาพ

# ดี - layers ที่เปลี่ยนน้อยไว้ด้านบน
FROM python:3.11-slim

# Dependencies (เปลี่ยนน้อย)
COPY requirements.txt .
RUN pip install -r requirements.txt

# Application code (เปลี่ยนบ่อย)
COPY . .

CMD ["python", "app.py"]

3. Container Management Best Practices

ตั้งชื่อ Containers อย่างชัดเจน

# ดี - ชื่อบอกจุดประสงค์
docker run -d --name web-frontend-prod nginx
docker run -d --name postgres-myapp-db postgres

# ไม่ดี - ชื่อไม่ชัดเจน
docker run -d --name c1 nginx
docker run -d --name test postgres

ใช้ Health Checks

FROM nginx:alpine

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD wget --quiet --tries=1 --spider http://localhost/ || exit 1

COPY html /usr/share/nginx/html

กำหนด Restart Policy

# Production - always restart
docker run -d --restart=always --name prod-app my-app

# Development - no restart
docker run -d --restart=no --name dev-app my-app

# Restart เฉพาะเมื่อ error
docker run -d --restart=on-failure:5 --name critical-app my-app

4. Network Best Practices

ใช้ Custom Networks แทน Default Bridge

# สร้าง custom network
docker network create app-network

# รัน containers บน custom network
docker run -d --name web --network app-network nginx
docker run -d --name api --network app-network my-api

แยก Frontend และ Backend Networks

# สร้าง networks แยกกัน
docker network create frontend
docker network create backend

# Database อยู่บน backend only
docker run -d --name db --network backend postgres

# API อยู่บนทั้งสอง networks
docker run -d --name api --network backend my-api
docker network connect frontend api

# Frontend อยู่บน frontend only
docker run -d --name web --network frontend nginx

5. Volume Best Practices

ใช้ Named Volumes แทน Bind Mounts ใน Production

# Production - named volume
docker run -d \
  --name prod-db \
  -v postgres-prod-data:/var/lib/postgresql/data \
  postgres:15

# Development - bind mount
docker run -d \
  --name dev-app \
  -v $(pwd)/src:/app/src \
  my-app:dev

Backup Volumes อย่างสม่ำเสมอ

# Backup script
#!/bin/bash
VOLUMES=("postgres-data" "redis-data" "app-uploads")
BACKUP_DIR="/backups/$(date +%Y%m%d)"

mkdir -p $BACKUP_DIR

for VOL in "${VOLUMES[@]}"; do
  docker run --rm \
    -v $VOL:/source:ro \
    -v $BACKUP_DIR:/backup \
    alpine \
    tar czf /backup/${VOL}.tar.gz -C /source .
  
  echo "Backed up $VOL"
done

6. Cleanup Best Practices

# สร้าง cleanup script
#!/bin/bash

echo "Cleaning up Docker resources..."

# ลบ stopped containers
docker container prune -f

# ลบ unused images
docker image prune -a -f

# ลบ unused volumes (ระวัง!)
docker volume prune -f

# ลบ unused networks
docker network prune -f

# ดูพื้นที่ที่ใช้
docker system df

echo "Cleanup completed!"

7. Monitoring และ Logging

ดูการใช้ทรัพยากร Real-time

# ดู stats ของ containers ทั้งหมด
docker stats

# ดู stats ของ specific containers
docker stats web api db

# แสดง stats ครั้งเดียว (ไม่ stream)
docker stats --no-stream

จัดการ Logs

# ดู logs พร้อม timestamp
docker logs -t my-container

# ดู logs แบบ follow
docker logs -f my-container

# จำกัด log lines
docker logs --tail 100 my-container

# ดู logs ในช่วงเวลา
docker logs --since 1h my-container
docker logs --until 2024-01-01T10:00:00 my-container

กำหนด Log Driver

# ใช้ json-file log driver พร้อม rotation
docker run -d \
  --name app \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  my-app

# ใช้ syslog
docker run -d \
  --name app \
  --log-driver syslog \
  --log-opt syslog-address=udp://192.168.0.1:514 \
  my-app

8. Development Workflow

# 1. สร้าง development environment
docker network create dev-network

# 2. รัน database
docker run -d \
  --name dev-db \
  --network dev-network \
  -e POSTGRES_PASSWORD=devpass \
  -v dev-db-data:/var/lib/postgresql/data \
  postgres:15

# 3. รัน application พร้อม hot reload
docker run -it \
  --name dev-app \
  --network dev-network \
  -p 3000:3000 \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/package.json:/app/package.json \
  -e DATABASE_URL=postgresql://postgres:devpass@dev-db:5432/myapp \
  my-app:dev npm run dev

# 4. รัน tests
docker run --rm \
  --network dev-network \
  -e DATABASE_URL=postgresql://postgres:devpass@dev-db:5432/test \
  my-app:dev npm test

คำสั่งที่ใช้บ่อย - Quick Reference

Container Management

# รัน container
docker run -d --name myapp -p 8080:80 nginx

# แสดงรายการ containers
docker ps                    # ที่กำลังรัน
docker ps -a                 # ทั้งหมด

# จัดการ lifecycle
docker start myapp
docker stop myapp
docker restart myapp
docker kill myapp
docker rm myapp

# เข้าไปใน container
docker exec -it myapp bash

# ดู logs
docker logs -f myapp

# Copy files
docker cp file.txt myapp:/path/
docker cp myapp:/path/file.txt .

Image Management

# Pull และ push
docker pull nginx:latest
docker push username/myapp:1.0

# Build
docker build -t myapp:1.0 .

# แสดงรายการ
docker images

# ลบ
docker rmi myapp:1.0
docker image prune -a

Network Management

# สร้างและจัดการ
docker network create mynet
docker network ls
docker network inspect mynet
docker network rm mynet

# เชื่อมต่อ container
docker network connect mynet myapp
docker network disconnect mynet myapp

Volume Management

# สร้างและจัดการ
docker volume create mydata
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune

# ใช้งาน
docker run -v mydata:/data myapp
docker run -v $(pwd):/app myapp

System Management

# ดูข้อมูลระบบ
docker info
docker version
docker system df

# ทำความสะอาด
docker system prune         # ลบ unused objects
docker system prune -a      # ลบทั้งหมดรวม images
docker system prune --volumes  # รวม volumes

สรุป

Docker เป็นเครื่องมือที่ทรงพลังสำหรับ containerization ที่ช่วยให้การพัฒนา การทดสอบ และการ deploy แอปพลิเคชันเป็นไปอย่างมีประสิทธิภาพ ในบทความนี้เราได้เรียนรู้:

ความรู้พื้นฐาน

Docker Images

Docker Containers

Docker Networks

Docker Volumes

Best Practices

Docker เป็นเพียงจุดเริ่มต้นของโลก containerization ซึ่งยังมีเครื่องมืออื่นๆ เช่น Kubernetes สำหรับ orchestration ขั้นสูง แต่การเข้าใจพื้นฐาน Docker อย่างแข็งแรงจะช่วยให้คุณก้าวไปสู่ระดับถัดไปได้อย่างมั่นใจ


แหล่งข้อมูลเพิ่มเติม


หมายเหตุ: บทความนี้เป็นคู่มือเบื้องต้นสำหรับ Docker ไม่รวม Docker Compose และ Docker Swarm ซึ่งเป็น advanced topics สำหรับ multi-container orchestration

เวอร์ชัน: Docker 24.x