← กลับ
DockerLinuxDiskStorage

ย้าย Docker Directory ด้วย Symlink แบบไม่พัง

/var/lib/docker เต็ม disk ของ root partition แต่ disk ใหญ่อยู่ที่ /data — ย้ายยังไงให้ container ทำงานต่อ ไม่ต้องสร้างใหม่

2025-12-18อ่าน 5 นาทีใหม่

เหตุผลที่ต้องย้าย

VPS / server เกือบทั้งหมดมี layout แบบนี้:

/        — 20-30 GB (root partition)
/data    — 200 GB (data disk แยก)

Docker default เก็บข้อมูลที่ /var/lib/docker = อยู่ใน root partition

ถ้ามี container เยอะ image เยอะ — root เต็มเร็วมาก ทั้งที่ /data ยังว่าง

ทางเลือก:

  • A: ตั้ง data-root ใน daemon config (วิธีถูกต้อง)
  • B: ย้าย folder + symlink (วิธีเก่า แต่ใช้ได้)

ทั้งสองวิธีโอเค ขอแนะนำ A แต่ถ้า script เก่า/tool บางตัว hardcode path /var/lib/docker — B ปลอดภัยกว่า

วิธี A: data-root config (แนะนำ)

Step 1: หยุด docker

sudo systemctl stop docker docker.socket

Step 2: ย้ายข้อมูล

sudo mkdir -p /data/docker
sudo rsync -aHAX --info=progress2 /var/lib/docker/ /data/docker/

flags ที่ใช้:

  • -a archive (preserve permissions, owner, time)
  • -H hardlinks
  • -A ACLs
  • -X extended attributes (สำคัญสำหรับ overlay2)

หรือใช้ cp -a ถ้าไม่มี rsync — แต่ rsync ทน interrupt ได้ดีกว่า

ตรวจสอบขนาด:

sudo du -sh /var/lib/docker /data/docker
# ขนาดควรเท่ากัน

Step 3: ตั้ง daemon config

/etc/docker/daemon.json:

{
  "data-root": "/data/docker"
}

ถ้ามี config อยู่แล้ว — merge กัน:

{
  "data-root": "/data/docker",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "3"
  }
}

Step 4: rename folder เก่า + start

sudo mv /var/lib/docker /var/lib/docker.bak
sudo systemctl start docker

Step 5: verify

docker info | grep -i "docker root"
# Docker Root Dir: /data/docker

docker ps -a       # container เก่ายังอยู่
docker images      # image เก่ายังอยู่

ถ้าทำงานปกติ — ลบ folder เก่า:

sudo rm -rf /var/lib/docker.bak

ใช้เมื่อ tool/script เก่าใน server hardcode path /var/lib/docker (rare แต่เคยเจอ)

Step 1-2: เหมือน A (หยุด docker, ย้ายข้อมูล)

sudo mv /var/lib/docker /var/lib/docker.bak
sudo ln -s /data/docker /var/lib/docker

# verify
ls -la /var/lib/docker
# lrwxrwxrwx ... /var/lib/docker -> /data/docker

Step 4: start docker

sudo systemctl start docker
docker ps -a

1. Mount option ของ /data ต้อง support overlay

sudo mount | grep /data
# ควรไม่เห็น "nodev" หรือ "nosuid" ถ้าเห็น overlay จะพัง

แก้ /etc/fstab:

/dev/sdb1  /data  ext4  defaults  0  2

2. SELinux อาจ block

CentOS / RHEL / Rocky:

sudo semanage fcontext -a -e /var/lib/docker /data/docker
sudo restorecon -R /data/docker

3. Ubuntu AppArmor

ตรวจ:

sudo aa-status | grep docker

ถ้ามี profile docker — อาจต้อง edit profile ให้ยอม path ใหม่ หรือใช้วิธี A แทน

วิธี C: bind mount

อีกวิธีที่ clean — bind mount แทน symlink:

/etc/fstab:

/data/docker  /var/lib/docker  none  bind  0  0
sudo mkdir -p /var/lib/docker
sudo mount -a
mount | grep docker
# /data/docker on /var/lib/docker type none (rw,bind)

ดี: ไม่มี symlink — tool เก่าเห็น /var/lib/docker ปกติ เสีย: ต้องตั้ง fstab + reboot test ว่ายัง mount หลัง restart

ทดสอบหลังย้าย

# 1. docker info
docker info | grep "Docker Root Dir"

# 2. รัน hello-world
docker run --rm hello-world

# 3. ตรวจ disk
df -h /data /var/lib/docker

# 4. start container เดิมที่เคยรันอยู่
docker compose up -d   # ในแต่ละ project folder

ข้อผิดพลาดที่ต้องระวัง

1. ลืมหยุด docker ก่อน rsync → ข้อมูลไม่ครบ container เก่าอ่านไม่ได้

2. rsync ขาด -X flag → overlay metadata หาย — image พังต้อง pull ใหม่

3. ลบ folder เก่าเร็วเกิน → ถ้ามีปัญหา rollback ไม่ได้ เก็บไว้อย่างน้อย 1 อาทิตย์

4. /data partition ไม่มี exec permission → container start ไม่ได้

sudo mount -o remount,exec /data

ป้องกันตั้งแต่ install ครั้งแรก

ถ้ารู้ว่า server มี data partition แยก — ตั้ง data-root ตั้งแต่แรกก่อน install service ใดๆ

# ตอน setup server
sudo mkdir -p /data/docker
echo '{"data-root": "/data/docker"}' | sudo tee /etc/docker/daemon.json
sudo systemctl restart docker

เช็ค space ใช้จริง

หลังย้าย ดูว่า /var ว่างขึ้นจริงมั้ย:

sudo du -sh /var/lib /data/docker
df -h

ถ้ายังเต็ม — มีของอื่น เช่น log, snap, journal:

sudo du -sh /var/log /var/lib/snapd /var/cache /var/tmp
sudo journalctl --vacuum-size=500M
sudo apt clean

TLDR

# วิธีที่ง่ายและ safe ที่สุด
sudo systemctl stop docker docker.socket
sudo mkdir -p /data/docker
sudo rsync -aHAX /var/lib/docker/ /data/docker/
echo '{"data-root": "/data/docker"}' | sudo tee /etc/docker/daemon.json
sudo mv /var/lib/docker /var/lib/docker.bak
sudo systemctl start docker

# ตรวจ
docker info | grep "Docker Root Dir"
docker ps -a

# หลังใช้ปกติ 1 อาทิตย์
sudo rm -rf /var/lib/docker.bak

สรุป

ย้าย Docker directory เป็นการ maintenance พื้นฐานที่ทำครั้งเดียวอยู่ได้นาน

data-root config = วิธีที่ Docker design มาให้ทำตั้งแต่แรก ใช้เลย Symlink = backup plan สำหรับ edge case

อย่าลืมเช็ค --info=progress2 ตอน rsync ขนาดใหญ่ — ดู progress real-time จะรู้ว่าจะเสร็จเมื่อไหร่

← ดูบทความอื่น