如何给已经在运行的 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 成临时镜像再重建(接上文,旧容器已改名为 myapp-old):
docker commit myapp-old myapp:snapshot
# 然后基于 myapp:snapshot 启动新容器
commit 不包含卷或绑定挂载中的数据,也不是数据库一致性备份;应先备份数据。更好的做法是把可重复的系统改动补回 Dockerfile。
用 --volumes-from 继承旧挂载
老容器挂载多、嫌逐个抄麻烦:
docker run -d --name myapp-new \
--volumes-from myapp-old \
-v my-new-volume:/var/log/app \
myimage:latest
--volumes-from 可复用受支持的卷/绑定挂载,但不会复制全部启动配置,也不应假定包括 tmpfs 等所有挂载类型;重建后用 inspect 核对。
docker-compose 场景
直接改 docker-compose.yml 加一行挂载,然后:
docker compose up -d
compose 检测到配置变化会自动重建该服务的容器,复用同一持久卷时数据通常保留,但新增挂载会遮蔽目标目录原内容;不会自动把旧容器可写层的数据迁入新卷。
预防:一开始就把目录卷化
日志、上传文件、数据库数据目录,创建容器时就挂卷,哪怕暂时只挂到默认 named volume。之后扩挂载、迁主机、备份都轻松。
常见问题(FAQ)
Q:有没有什么 hack 能不重建?
A:没有安全通用的办法(改宿主机 mount 命名空间属于高危骚操作)。容器设计哲学就是可抛弃,重建是对的路。
Q:重建会丢数据吗?
A:保留并复用卷时数据通常保留;旧容器可写层不会自动迁到新容器,删除旧容器前必须备份并验证。
Q:K8s 里能加卷吗?
A:同样不能给运行中的 Pod 加卷;改 Deployment 的 volumeMounts 触发滚动重建即可,还需核对 PVC、卷类型、访问模式和回收策略,不能保证所有卷或发布方式都无损。