如何给已经在运行的 Docker 容器添加数据卷?
Docker 不支持给运行中的容器直接加卷,只能基于原配置重建容器并加 -v 挂载。本文给出 docker commit 保留改动、compose 改文件重建等平滑迁移方法。
直接答案:做不到——卷的挂载在容器创建时确定,运行中的容器无法动态添加。标准做法是用相同配置 + 新挂载重新创建容器**:容器本是 disposable 的,数据放卷里,重建代价很小。**
标准流程:重建容器
# 1. 查看原容器的完整启动配置
docker inspect myapp # 记下镜像、环境变量、端口、其他卷
# 2. 停掉并改名(保留以防万一)
docker stop myapp && docker rename myapp myapp-old
# 3. 用原配置 + 新卷重建
docker run -d --name myapp \
-p 8080:80 \
-e ENV=prod \
-v existing-volume:/data \ # 原有挂载
-v my-new-volume:/var/log/app \ # 新增挂载
myimage:latest
# 4. 验证无误后删旧容器
docker rm myapp-old
容器里有未保存的改动?
先 commit 成临时镜像再重建:
docker commit myapp myapp:snapshot
# 然后基于 myapp:snapshot 启动新容器
(更好的做法是把这些改动补回 Dockerfile。)
用 --volumes-from 继承旧挂载
老容器挂载多、嫌逐个抄麻烦:
docker run -d --name myapp-new \
--volumes-from myapp-old \
-v my-new-volume:/var/log/app \
myimage:latest
--volumes-from 会把旧容器的全部挂载原样带过来。
docker-compose 场景
直接改 docker-compose.yml 加一行挂载,然后:
docker compose up -d
compose 检测到配置变化会自动重建该服务的容器,数据卷内容不受影响。
预防:一开始就把目录卷化
日志、上传文件、数据库数据目录,创建容器时就挂卷,哪怕暂时只挂到默认 named volume。之后扩挂载、迁主机、备份都轻松。
观测云对照
日志目录卷化后采集更稳。 应用日志目录挂在卷上,DataKit 无论从容器 stdout 还是宿主机路径采集都可靠,容器重建不丢历史日志;配合存储策略管理保留周期。
常见问题(FAQ)
Q:有没有什么 hack 能不重建?
A:没有安全通用的办法(改宿主机 mount 命名空间属于高危骚操作)。容器设计哲学就是可抛弃,重建是对的路。
Q:重建会丢数据吗?
A:卷里的数据不动;容器可写层里的数据会丢——这正是数据要卷化的原因。
Q:K8s 里能加卷吗?
A:同样不能给运行中的 Pod 加卷;改 Deployment 的 volumeMounts 触发滚动重建即可,数据在 PV 里不受影响。