Linux 下更改 Docker 数据目录的完整教程

前言

Docker 默认数据目录位于 /var/lib/docker,随着容器和镜像增多,该目录会占用大量磁盘空间。当系统盘空间不足时,需要将 Docker 数据目录迁移到数据盘。本文详细介绍多种更改 Docker 数据目录的方法。

一、为什么需要更改 Docker 数据目录

1.1 常见场景

  • 系统盘空间不足,需要迁移到大容量数据盘
  • 使用 SSD 作为系统盘,HDD 作为数据盘,需要分离存储
  • 多磁盘环境,需要负载均衡
  • 需要更好的 IO 性能

1.2 默认目录结构

/var/lib/docker/
├── containers/      # 容器数据
├── image/          # 镜像数据
├── volumes/        # 卷数据
├── network/        # 网络配置
├── plugins/        # 插件
├── swarm/          # Swarm 配置
└── overlay2/       # 存储驱动(可能是 aufs、btrfs 等)

二、更改前的准备工作

2.1 检查当前 Docker 使用情况

# 查看 Docker 根目录
docker info | grep "Docker Root Dir"

# 查看当前磁盘使用
du -sh /var/lib/docker

# 查看磁盘空间
df -h

# 查看 Docker 存储驱动
docker info | grep "Storage Driver"

2.2 停止 Docker 服务

# 停止所有容器
docker stop $(docker ps -aq)

# 停止 Docker 服务
sudo systemctl stop docker

# 或者使用 service
sudo service docker stop

# 验证服务已停止
sudo systemctl status docker

2.3 准备新的数据目录

# 创建新目录(假设迁移到 /data/docker)
sudo mkdir -p /data/docker

# 设置权限
sudo chown -R root:root /data/docker
sudo chmod -R 755 /data/docker

# 验证目录
ls -ld /data/docker

三、方法一:修改 daemon.json(推荐)

3.1 备份原配置

# 备份配置文件
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak

# 如果配置文件不存在,创建新文件
sudo touch /etc/docker/daemon.json

3.2 编辑配置文件

sudo vim /etc/docker/daemon.json

# 添加或修改 data-root 配置
{
  "data-root": "/data/docker",
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://registry.docker-cn.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  }
}

3.3 迁移现有数据

# 方法 1:使用 rsync(推荐,保留权限)
sudo rsync -avz /var/lib/docker/ /data/docker/

# 方法 2:使用 cp(较慢)
sudo cp -rp /var/lib/docker/* /data/docker/

# 验证迁移
du -sh /var/lib/docker
 du -sh /data/docker

3.4 启动 Docker 服务

# 启动服务
sudo systemctl start docker

# 设置开机自启
sudo systemctl enable docker

# 查看状态
sudo systemctl status docker

3.5 验证配置

# 查看新的数据目录
docker info | grep "Docker Root Dir"

# 应该显示:Docker Root Dir: /data/docker

# 查看容器是否正常运行
docker ps -a

# 测试创建容器
docker run --rm hello-world

四、方法二:修改 systemd 配置

4.1 编辑 systemd 配置

# 编辑 Docker systemd 配置
sudo vim /etc/systemd/system/docker.service.d/override.conf

# 如果目录不存在,先创建
sudo mkdir -p /etc/systemd/system/docker.service.d/

4.2 添加配置内容

[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --data-root=/data/docker

4.3 重新加载配置

# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 迁移数据
sudo rsync -avz /var/lib/docker/ /data/docker/

# 启动服务
sudo systemctl start docker

# 验证
docker info | grep "Docker Root Dir"

五、方法三:使用符号链接

5.1 停止 Docker 服务

sudo systemctl stop docker

5.2 迁移数据

# 迁移现有数据
sudo rsync -avz /var/lib/docker/ /data/docker/

# 验证数据完整性
du -sh /var/lib/docker
du -sh /data/docker

5.3 创建符号链接

# 备份原目录(可选)
sudo mv /var/lib/docker /var/lib/docker.bak

# 创建符号链接
sudo ln -s /data/docker /var/lib/docker

# 验证链接
ls -l /var/lib/docker

# 应该显示:/var/lib/docker -> /data/docker

5.4 启动服务

sudo systemctl start docker
docker info | grep "Docker Root Dir"

六、方法四:使用挂载点(LVM/磁盘挂载)

6.1 准备新磁盘

# 查看新磁盘
lsblk

# 格式化磁盘(假设新磁盘为 /dev/sdb1)
sudo mkfs.ext4 /dev/sdb1

# 创建挂载点
sudo mkdir -p /data/docker

6.2 挂载磁盘

# 临时挂载
sudo mount /dev/sdb1 /data/docker

# 验证挂载
df -h | grep docker

6.3 配置开机自动挂载

# 获取磁盘 UUID
sudo blkid /dev/sdb1

# 编辑 fstab
sudo vim /etc/fstab

# 添加以下内容(替换 UUID)
UUID=xxxx-xxxx /data/docker ext4 defaults 0 2

# 验证配置
sudo mount -a
df -h | grep docker

6.4 修改 Docker 配置

# 编辑 daemon.json
sudo vim /etc/docker/daemon.json

# 添加配置
{
  "data-root": "/data/docker"
}

# 重启 Docker
sudo systemctl restart docker

七、迁移后的验证与清理

7.1 验证容器和镜像

# 查看所有镜像
docker images

# 查看所有容器
docker ps -a

# 测试运行容器
docker run --rm -it alpine echo "Hello Docker"

# 查看存储使用情况
docker system df

7.2 清理旧数据

# 确认新配置正常后,删除旧数据
sudo rm -rf /var/lib/docker.bak

# 或者删除空目录
sudo rmdir /var/lib/docker

# 清理系统缓存
sudo docker system prune -a

# 查看清理后的空间
df -h

7.3 性能测试

# 测试镜像拉取速度
time docker pull ubuntu:latest

# 测试容器启动速度
time docker run --rm alpine echo "test"

# 测试磁盘 IO(可选)
dd if=/dev/zero of=/data/docker/test bs=1G count=1 oflag=direct

八、常见问题排查

8.1 Docker 无法启动

# 查看错误日志
sudo journalctl -u docker -f

# 查看 Docker 日志
sudo cat /var/log/docker.log

# 检查配置文件语法
sudo dockerd --validate

# 检查目录权限
ls -ld /data/docker
sudo chown -R root:root /data/docker

8.2 容器无法启动

# 查看容器日志
docker logs 

# 检查存储驱动
docker info | grep "Storage Driver"

# 清理无效容器
docker container prune

# 重建容器
docker rm -f 
docker run ...

8.3 权限问题

# 检查目录权限
ls -la /data/docker

# 修复权限
sudo chown -R root:root /data/docker
sudo chmod -R 755 /data/docker

# 检查 SELinux(CentOS/RHEL)
getenforce
setenforce 0

# 检查 AppArmor(Ubuntu)
sudo aa-status

8.4 磁盘空间不足

# 查看 Docker 磁盘使用
docker system df

# 清理未使用的镜像
docker image prune -a

# 清理未使用的容器
docker container prune

# 清理未使用的卷
docker volume prune

# 清理构建缓存
docker builder prune

# 一键清理所有
docker system prune -a --volumes

九、最佳实践建议

9.1 数据目录规划

# 推荐的目录结构
/data/
├── docker/          # Docker 数据
│   ├── containers/  # 容器
│   ├── image/      # 镜像
│   └── volumes/    # 卷
├── backups/        # 备份
└── logs/           # 日志

9.2 定期清理脚本

#!/bin/bash
# docker_cleanup.sh

# 清理停止的容器
docker container prune -f

# 清理悬空镜像
docker image prune -f

# 清理未使用的卷
docker volume prune -f

# 清理构建缓存
docker builder prune -f

# 记录日志
echo "Docker cleanup completed at $(date)" >> /var/log/docker_cleanup.log

9.3 监控脚本

#!/bin/bash
# docker_monitor.sh

echo "=== Docker 磁盘使用 ==="
docker system df

echo "\n=== Docker 目录大小 ==="
du -sh /data/docker

echo "\n=== 运行中的容器 ==="
docker ps --format "table {{.Names}}\t{{.Status}}"

echo "\n=== 磁盘空间 ==="
df -h /data

十、不同发行版的注意事项

10.1 Ubuntu/Debian

# 使用 systemd 管理系统服务
sudo systemctl daemon-reload
sudo systemctl restart docker

# 配置文件位置
/etc/docker/daemon.json

10.2 CentOS/RHEL

# 可能需要关闭 SELinux
sudo setenforce 0
sudo vim /etc/selinux/config  # SELINUX=permissive

# 或者配置 SELinux 规则
sudo semanage fcontext -a -t var_lib_t "/data/docker(/.*)?"
sudo restorecon -Rv /data/docker

10.3 使用 Snap 安装的 Docker

# Snap 版本配置位置不同
/var/snap/docker/common/config/daemon.json

# 数据目录
/var/snap/docker/common/var-lib-docker/

总结

本文介绍了四种更改 Docker 数据目录的方法:

  • 方法一(daemon.json) - 官方推荐,配置简单
  • 方法二(systemd) - 适合高级用户
  • 方法三(符号链接) - 快速临时方案
  • 方法四(磁盘挂载) - 适合多磁盘环境

推荐使用方法一,通过修改 daemon.json 配置,简单且易于维护。

参考链接

发表回复

后才能评论