สอน Docker Volumes จัดการ Data Persistence สำหรับ Container 2026

ปัญหา Data ใน Container — ทำไมต้อง Volumes?

Container เป็น Ephemeral (ชั่วคราว) เมื่อ Container ถูกลบ ข้อมูลทั้งหมดใน Container จะหายไปด้วย ถ้าคุณรัน Database ใน Container แล้วลบ Container ข้อมูลทั้งหมดจะ หายหมด! Docker Volumes แก้ปัญหานี้โดยเก็บข้อมูลไว้นอก Container

# ปัญหา: ไม่ใช้ Volume
docker run -d --name mydb mysql:8.0
# → ข้อมูล MySQL อยู่ใน Container
docker rm -f mydb
# → ข้อมูลทั้งหมดหายไป!

# วิธีแก้: ใช้ Volume
docker run -d --name mydb -v mysql-data:/var/lib/mysql mysql:8.0
# → ข้อมูล MySQL อยู่ใน Volume "mysql-data"
docker rm -f mydb
# → Volume ยังอยู่! ข้อมูลไม่หาย!
docker run -d --name mydb2 -v mysql-data:/var/lib/mysql mysql:8.0
# → Container ใหม่ใช้ข้อมูลเดิมได้ทันที!

3 วิธีจัดการ Data ใน Docker

วิธี คำสั่ง ข้อดี ข้อเสีย เหมาะกับ
Named Volumes -v mydata:/app/data Docker จัดการให้ พกพาง่าย Backup ง่าย ไม่รู้ว่าเก็บไว้ที่ไหนบน Host Database, Application Data
Bind Mounts -v /host/path:/container/path ควบคุม Path เอง แก้ไขจาก Host ได้ ขึ้นกับ Host Path, ปัญหา Permission Development, Config Files
tmpfs Mounts –tmpfs /app/temp เร็วมาก (RAM) ปลอดภัย ข้อมูลหายเมื่อ Container Stop Sensitive Data, Cache

Named Volumes — วิธีที่แนะนำ

# สร้าง Volume:
docker volume create myapp-data
docker volume create mydb-data

# ดู Volumes ทั้งหมด:
docker volume ls
# DRIVER    VOLUME NAME
# local     myapp-data
# local     mydb-data

# ดูรายละเอียด Volume:
docker volume inspect myapp-data
# [
#     {
#         "CreatedAt": "2026-04-16T10:00:00Z",
#         "Driver": "local",
#         "Labels": {},
#         "Mountpoint": "/var/lib/docker/volumes/myapp-data/_data",
#         "Name": "myapp-data",
#         "Options": {},
#         "Scope": "local"
#     }
# ]

# ใช้ Volume กับ Container:
docker run -d --name webapp \
    -v myapp-data:/app/uploads \
    -v mydb-data:/var/lib/mysql \
    -p 8080:80 \
    myapp:latest

# ลบ Volume (ระวัง! ข้อมูลจะหายถาวร):
docker volume rm myapp-data

# ลบ Volumes ที่ไม่ได้ใช้:
docker volume prune
# → ลบเฉพาะ Volumes ที่ไม่มี Container ใช้อยู่

Bind Mounts — Mount Path จาก Host

# Bind Mount: เชื่อม Directory บน Host กับ Container
#
# ใช้ -v flag:
docker run -d --name nginx \
    -v /home/user/website:/usr/share/nginx/html:ro \
    -p 80:80 \
    nginx:latest
# → :ro = Read-Only (Container อ่านได้อย่างเดียว)

# ใช้ --mount flag (ชัดเจนกว่า):
docker run -d --name nginx \
    --mount type=bind,source=/home/user/website,target=/usr/share/nginx/html,readonly \
    -p 80:80 \
    nginx:latest

# Development: Mount Source Code
docker run -d --name devapp \
    -v $(pwd)/src:/app/src \
    -v $(pwd)/config:/app/config \
    -p 3000:3000 \
    node:20
# → แก้ Code บน Host → เห็นผลใน Container ทันที!

# ข้อควรระวัง:
# 1. Path บน Host ต้องมีอยู่จริง (ไม่สร้างให้อัตโนมัติ)
# 2. Permission: Container ใช้ UID/GID ต่างจาก Host
# 3. Performance: บน macOS/Windows ช้ากว่า Linux
# 4. Security: Container เข้าถึงไฟล์บน Host ได้

Docker Compose กับ Volumes

# docker-compose.yml สำหรับ WordPress + MySQL:
version: '3.8'

services:
  wordpress:
    image: wordpress:latest
    ports:
      - "8080:80"
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppass2026
      WORDPRESS_DB_NAME: wordpress
    volumes:
      - wp-content:/var/www/html/wp-content
      - ./custom-theme:/var/www/html/wp-content/themes/custom
    depends_on:
      - db
    restart: unless-stopped

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpass2026
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppass2026
    volumes:
      - db-data:/var/lib/mysql
      - ./mysql-config/my.cnf:/etc/mysql/conf.d/custom.cnf:ro
    restart: unless-stopped

volumes:
  wp-content:
    driver: local
  db-data:
    driver: local

# คำสั่ง:
# docker compose up -d        → Start ทั้งหมด
# docker compose down         → Stop (Volumes ยังอยู่)
# docker compose down -v      → Stop + ลบ Volumes (ระวัง!)
# docker compose ps           → ดู Status

Backup & Restore Volumes

# Backup Volume ด้วย tar:
# =============================================

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

# อธิบาย:
# → สร้าง Container ชั่วคราว (--rm = ลบเมื่อเสร็จ)
# → Mount Volume ที่ต้องการ Backup เป็น /source (Read-Only)
# → Mount Directory บน Host เป็น /backup
# → ใช้ tar บีบอัดข้อมูล

# 2. Restore Volume จาก tar.gz:
docker volume create mydb-data-restored

docker run --rm \
    -v mydb-data-restored:/target \
    -v $(pwd)/backups:/backup:ro \
    alpine \
    tar xzf /backup/mydb-backup-20260416.tar.gz -C /target

# 3. Automated Backup Script:
#!/bin/bash
BACKUP_DIR="/backups/docker"
DATE=$(date +%Y%m%d_%H%M%S)

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

# ลบ Backup เก่ากว่า 30 วัน:
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +30 -delete
echo "Backup completed!"

# ตั้ง Cron:
# 0 2 * * * /opt/scripts/backup-volumes.sh >> /var/log/docker-backup.log

Volume Drivers — เก็บข้อมูลที่อื่น

# Docker รองรับ Volume Driver หลายตัว:
#
# local (default):
# → เก็บบน Host Machine
# → เหมาะกับ Single Server
#
# nfs:
# → เก็บบน NFS Server
# → เหมาะกับ Shared Storage
docker volume create --driver local \
    --opt type=nfs \
    --opt o=addr=192.168.1.100,rw \
    --opt device=:/exports/docker-data \
    nfs-volume

# cifs (SMB/Windows Share):
docker volume create --driver local \
    --opt type=cifs \
    --opt o=username=user,password=pass,addr=192.168.1.100 \
    --opt device=//192.168.1.100/share \
    smb-volume

# PlugIns สำหรับ Cloud Storage:
# → rexray/s3fs (AWS S3)
# → rexray/ebs (AWS EBS)
# → azure-file (Azure File Share)
# → local-persist (Persistent local path)

Volume Permission Problems & Solutions

# ปัญหา Permission ที่พบบ่อย:
#
# 1. Container ใช้ UID ต่างจาก Host:
# Container user = UID 1000
# Host user = UID 501
# → Permission Denied!

# วิธีแก้ 1: กำหนด User ใน Dockerfile:
# FROM node:20
# RUN groupadd -g 1000 appgroup && \
#     useradd -u 1000 -g appgroup appuser
# USER appuser

# วิธีแก้ 2: ใช้ --user flag:
docker run -d --user $(id -u):$(id -g) \
    -v mydata:/app/data \
    myapp:latest

# วิธีแก้ 3: Init Container (Docker Compose):
services:
  init-permissions:
    image: alpine
    command: chown -R 1000:1000 /data
    volumes:
      - mydata:/data
  app:
    image: myapp:latest
    volumes:
      - mydata:/app/data
    depends_on:
      init-permissions:
        condition: service_completed_successfully

# วิธีแก้ 4: SELinux (CentOS/RHEL):
docker run -v /host/data:/container/data:Z myapp:latest
# → :Z = SELinux relabel (Single Container)
# → :z = Shared between Containers

Volume Best Practices

Practice คำอธิบาย
ใช้ Named Volumes สำหรับ Production Docker จัดการให้ ไม่ขึ้นกับ Host Path
ใช้ Bind Mounts สำหรับ Development แก้ไข Code ได้สะดวก เห็นผลทันที
Backup เป็นประจำ ตั้ง Cron Backup อย่างน้อยวันละครั้ง
ใช้ :ro เมื่อ Container ไม่ต้องเขียน ลด Risk ข้อมูลถูกแก้ไข
ตั้งชื่อ Volume ให้มีความหมาย ใช้ project-service-type เช่น myapp-db-data
อย่าเก็บ Sensitive Data ใน Image ใช้ Volume หรือ Docker Secrets แทน
ทดสอบ Restore จาก Backup Backup ที่ Restore ไม่ได้ = ไม่มี Backup
Monitor Volume Usage ดู Disk Space เป็นประจำ docker system df

Volume สำหรับ Database Containers

# MySQL:
docker run -d --name mysql \
    -v mysql-data:/var/lib/mysql \
    -v ./mysql-init:/docker-entrypoint-initdb.d:ro \
    -v ./mysql-conf:/etc/mysql/conf.d:ro \
    -e MYSQL_ROOT_PASSWORD=rootpass \
    mysql:8.0

# PostgreSQL:
docker run -d --name postgres \
    -v pg-data:/var/lib/postgresql/data \
    -v ./pg-init:/docker-entrypoint-initdb.d:ro \
    -e POSTGRES_PASSWORD=pgpass \
    postgres:16

# MongoDB:
docker run -d --name mongo \
    -v mongo-data:/data/db \
    -v mongo-config:/data/configdb \
    -e MONGO_INITDB_ROOT_USERNAME=admin \
    -e MONGO_INITDB_ROOT_PASSWORD=mongopass \
    mongo:7

# Redis (with persistence):
docker run -d --name redis \
    -v redis-data:/data \
    redis:7 redis-server --appendonly yes

# Volume Paths สำคัญ:
# MySQL:      /var/lib/mysql
# PostgreSQL: /var/lib/postgresql/data
# MongoDB:    /data/db
# Redis:      /data
# Elasticsearch: /usr/share/elasticsearch/data
# Prometheus: /prometheus

Monitoring Docker Volumes

# ดู Disk Usage ของ Docker:
docker system df
# TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
# Images          15        5         3.2GB     1.8GB (56%)
# Containers      8         5         50MB      20MB (40%)
# Volumes         10        6         5.5GB     1.2GB (21%)
# Build Cache     20        0         800MB     800MB (100%)

# ดู Volume Usage รายตัว:
docker system df -v | grep -A5 "VOLUME NAME"

# ดูขนาดจริงบน Disk:
sudo du -sh /var/lib/docker/volumes/*

# ลบ Resource ที่ไม่ใช้:
docker system prune              # ลบ Container, Network, Image ที่ไม่ใช้
docker system prune --volumes    # รวม Volumes ด้วย (ระวัง!)
docker volume prune              # ลบเฉพาะ Volumes ที่ไม่ใช้

# Alert เมื่อ Disk เต็ม:
#!/bin/bash
USAGE=$(df /var/lib/docker | tail -1 | awk '{print $5}' | tr -d '%')
if [ "$USAGE" -gt 80 ]; then
    echo "Docker disk usage: ${USAGE}%" | mail -s "Docker Disk Alert" [email protected]
fi

สรุป: Docker Volumes สำหรับ Data Persistence

Docker Volumes เป็นวิธีมาตรฐานในการจัดการ Data ใน Container ทั้ง Named Volumes สำหรับ Production, Bind Mounts สำหรับ Development และ tmpfs สำหรับ Sensitive Data การเข้าใจ Volumes อย่างลึกซึ้งจะช่วยให้คุณรัน Container ได้อย่างมั่นใจ ไม่ต้องกังวลเรื่องข้อมูลหายเมื่อ Container ถูกลบหรือ Restart

.

.
.
.

จัดส่งรวดเร็วส่งด่วนทั่วประเทศ
รับประกันสินค้าเคลมง่าย มีใบรับประกัน
ผ่อนชำระได้บัตรเครดิต 0% สูงสุด 10 เดือน
สะสมแต้ม รับส่วนลดส่วนลดและคะแนนสะสม

© 2026 SiamLancard — จำหน่ายการ์ดแลน อุปกรณ์ Server และเครื่องพิมพ์ใบเสร็จ

SiamLancard
Logo
Free Forex EA — XM Signal · SiamCafe Blog · SiamLancard · Siam2R · iCafeFX
iCafeForex.com - สอนเทรด Forex | SiamCafe.net
Shopping cart