Docker 安装 + 数据目录迁移到 /data 完整指南
适用:Ubuntu 20.04 / 22.04 / 24.04,root 或 sudo 权限
目标:Docker 与 containerd 数据都落到 /data,避免撑爆系统盘
目录
0. 前置说明
为什么要把数据目录迁到 /data?
Docker 默认把数据写在 /var/lib/docker,containerd 写在 /var/lib/containerd。
- 这两个目录都在系统盘(
/)上 - 系统盘通常较小(10~50G)
- Docker 镜像层非常占空间,几十 G 很常见
结论:只要机器有独立数据盘(如 /data),就必须迁移,否则迟早磁盘满。
迁移后数据流向
| 组件 | 默认目录 | 迁移后 |
|---|---|---|
| Docker 引擎 | /var/lib/docker | /data/docker |
| containerd | /var/lib/containerd | /data/containerd |
1. 环境准备
# 切到 root(可选)
sudo -i
# 更新系统
apt update && apt upgrade -y
# 安装依赖
apt install -y apt-transport-https ca-certificates curl \
software-properties-common gnupg lsb-release
# 卸载旧版本(如果之前装过)
apt remove -y docker docker-engine docker.io containerd runc \
docker-compose docker-compose-plugin
# 清理旧数据(⚠️ 只在确认无数据需要保留时执行)
rm -rf /var/lib/docker
rm -rf /var/lib/containerd
验证:docker --version 应报 command not found。
准备数据目录
mkdir -p /data/docker
mkdir -p /data/containerd
df -h /data
验证:/data 剩余空间应远大于系统盘。
2. 安装 Docker
2.1 添加官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
验证:
gpg --no-default-keyring \
--keyring /usr/share/keyrings/docker-archive-keyring.gpg \
--list-keys
应输出 Docker 的签名密钥信息。
2.2 添加官方源
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" \
| tee /etc/apt/sources.list.d/docker.list > /dev/null
2.3 安装
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
验证:
docker --version # Docker version 27.x.x
docker compose version # Docker Compose version v2.x.x
3. 迁移数据目录到 /data
⚠️ 关键章节。漏掉 containerd 的配置,会重蹈"系统盘被撑爆"的覆辙。
3.1 配置 Docker 数据目录
mkdir -p /etc/docker
cat > /etc/docker/daemon.json <<'EOF'
{
"data-root": "/data/docker",
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
}
}
EOF
关键点:
data-root:Docker 引擎数据目录log-driver+log-opts:限制每个容器日志 50M × 3 份,防止日志无限涨- 不要在这里加
registry-mirrors,第 4 节单独加
3.2 配置 containerd 数据目录(最易漏)
mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml
编辑 /etc/containerd/config.toml,找到并修改这两行:
root = "/data/containerd"
state = "/run/containerd"
说明:
root:镜像层数据,必须放在 /data,否则会撑爆系统盘state:运行时状态,必须放在 /run(tmpfs),重启自动清空
改完必须重启 containerd 才生效:
systemctl restart containerd
systemctl status containerd --no-pager | grep -E "Active|root"
验证:
grep -E "^root|^state" /etc/containerd/config.toml
期望输出:
root = '/data/containerd'
state = '/run/containerd'
3.3 启动 Docker
systemctl enable --now docker
3.4 权限配置(可选,非 root 用户)
usermod -aG docker $USER
⚠️
newgrp docker只对当前 shell 会话生效。
正确做法:登出当前会话,重新登录,或执行su - $USER开新 shell。
验证:新开一个终端,运行 docker ps,不报权限错误即成功。
4. 配置镜像加速
4.1 检查镜像源可用性
国内公共源经常变动,先测再用:
for m in docker.1panel.live docker.1ms.run docker.xuanyuan.me docker.m.daocloud.io; do
printf "%-30s " "$m"
curl -s -m 5 -o /dev/null -w "%{http_code}\n" "https://$m/v2/" 2>/dev/null || echo "FAIL"
done
- 返回
200或401→ 可用 - 返回
000/FAIL→ 不可用,从配置里删掉
4.2 写入 daemon.json
把上面测通的源填进去,保留 3.1 节已有的配置:
cat > /etc/docker/daemon.json <<'EOF'
{
"data-root": "/data/docker",
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "3"
},
"registry-mirrors": [
"https://docker.1panel.live",
"https://docker.1ms.run",
"https://docker.xuanyuan.me",
"https://docker.m.daocloud.io"
]
}
EOF
systemctl daemon-reload && systemctl restart docker
5. 限制系统日志
Docker 的日志有 log-opts 限制,但 systemd journal 也会涨。一并限制:
# 查看当前配置行
grep -n "SystemMaxUse" /etc/systemd/journald.conf
# 如果被注释(#SystemMaxUse=xxx),替换
sed -i 's/^#\?SystemMaxUse=.*/SystemMaxUse=100M/' /etc/systemd/journald.conf
# 如果没有该行,追加
grep -q "^SystemMaxUse" /etc/systemd/journald.conf \
|| echo "SystemMaxUse=100M" >> /etc/systemd/journald.conf
systemctl restart systemd-journald
journalctl --disk-usage
用
#\?兼容"注释或未注释"两种情况,比原教程更健壮。
6. 完整验证清单
一次性跑完,全部通过才算成功:
echo "=== 1. Docker 数据目录 ==="
docker info | grep "Docker Root Dir"
# 期望: Docker Root Dir: /data/docker
echo "=== 2. containerd 配置 ==="
grep -E "^root|^state" /etc/containerd/config.toml
# 期望: root = '/data/containerd'
# state = '/run/containerd'
echo "=== 3. 实际占用 ==="
du -sh /data/docker /data/containerd
# 期望: 两个目录都在 /data 下
echo "=== 4. 系统盘干净 ==="
ls /var/lib/docker /var/lib/containerd 2>/dev/null
# 期望: 无输出
echo "=== 5. 镜像加速 ==="
docker info | grep -A5 "Registry Mirrors"
echo "=== 6. journal 限制 ==="
grep SystemMaxUse /etc/systemd/journald.conf
journalctl --disk-usage
echo "=== 7. 开机自启 ==="
systemctl is-enabled docker
systemctl is-enabled containerd
# 期望: enabled
echo "=== 8. 功能测试 ==="
docker run --rm hello-world
7. 常见问题
Q1:拉镜像报 no space left on device,路径是 /var/lib/containerd/...
原因:containerd 配置改了但没有重启 containerd,它还在往系统盘写。
修复:
grep "^root" /etc/containerd/config.toml # 确认配置是 /data/containerd
systemctl restart containerd # 关键
docker system prune -af # 清理残留
df -h / # 确认系统盘腾出空间
Q2:容器启动报 network xxx not found
原因:迁移或清理时 docker 网络定义丢失。
修复:在 compose 目录执行
docker compose down # 删容器和网络,不删挂载数据
docker compose up -d # 重建
Q3:容器能 ping 通外网,但连不上宿主机的 IP:端口
原因:ufw / firewalld 拦截了 docker bridge 网段到宿主机的流量。
修复:
# 查看 docker 网段
docker network ls --format '{{.Name}}' | while read n; do
subnet=$(docker network inspect "$n" --format '{{range .IPAM.Config}}{{.Subnet}}{{end}}' 2>/dev/null)
[ -n "$subnet" ] && echo "$n -> $subnet"
done
# 放行(一条覆盖所有 docker 网段)
ufw allow from 172.16.0.0/12 to any
ufw reload
Q4:docker ps 报 permission denied
原因:用户加入了 docker 组但当前 shell 没生效。
修复:登出重进,或:
newgrp docker
Q5:镜像源都失效了,怎么办
重新测一遍(4.1 节脚本),把 200/401 的替换进 daemon.json,然后:
systemctl daemon-reload && systemctl restart docker
Q6:已有环境想迁移数据(不是全新安装)
# 1. 停服务
systemctl stop docker docker.socket containerd
# 2. 复制数据
apt install -y rsync
rsync -aP /var/lib/docker/ /data/docker/
rsync -aP /var/lib/containerd/ /data/containerd/
# 3. 改配置(3.1 和 3.2 节)
# 4. 启动并验证
systemctl start containerd
systemctl start docker
docker ps # 容器应都在
# 5. 确认无误后删旧数据
rm -rf /var/lib/docker /var/lib/containerd
df -h /
2980



被折叠的 条评论
为什么被折叠?



