镜像更新后,如何升级正在运行的 Docker 容器?
镜像更新不会自动作用到已建容器:先拉取新镜像,记录配置并备份,再停止旧容器、按原配置重建。卷可保留数据,但升级兼容性仍需验证;Compose 可拉取并重建指定服务。
核心认知:容器创建时绑定的是当时镜像的 ID,镜像更新不会自动更新已有容器。升级流程:①docker pull 镜像:标签 拉取新版;②记录完整配置、备份数据并停止旧容器;③用原参数创建新版。持久卷或绑定挂载可保留数据,但不保证升级兼容或无损。
手动升级四步
set -e
# 1. 拉取新镜像
docker pull registry.example.com/team/myapp:1.3
# 2. 记录完整配置与原重启策略,保留旧容器作回退参考
docker inspect myapp > myapp-before.json
# 此文件可能包含密钥,限制权限
chmod 600 myapp-before.json
docker update --restart=no myapp
docker stop myapp
docker rename myapp myapp-old
# 3. 按原配置重建
docker run -d --name myapp \
--restart unless-stopped \
-p 8080:80 \
-v app-data:/data \
registry.example.com/team/myapp:1.3
# 4. 验证
docker logs -f myapp
新容器启动后,先执行关键请求,并在应用日志中记录当前版本。已有观测云采集时,可按 DataKit实际解析的服务与版本字段比较更新前后的错误记录;保留旧镜像及回退步骤,监控结果只用于辅助判断是否恢复业务。
compose 场景(省心版)
docker compose pull app
docker compose up -d --no-deps app # 依赖兼容时仅更新目标服务
自建镜像(build 型)则是:
docker compose up -d --build
减少停机时间
- 先拉后换:pull 完成再停旧容器,可缩短停机,但实际还取决于启动、迁移和就绪时间
- 蓝绿式:新容器用不同端口/名字先起来验证,切流后再下线旧的
- 健康检查兜底:配置健康/就绪检查辅助切流和发布判断;Compose 不会仅因 unhealthy 自动回滚,K8s 回退也需明确策略
防丢数据清单
- 数据库、上传目录必须挂卷(
docker inspect看 Mounts 确认) - 可写层临时改动先受控拷出或 commit,但 commit 不备份挂载数据;数据库回退还需考虑 schema 和数据格式,恢复旧容器也要还原其重启策略
- 数据库升级注意版本兼容(大版本跨升可能要迁移步骤)
常见问题(FAQ)
Q:标签没变(都是 latest)怎么确认拉到新版?
A:docker pull 会显示各层状态,有更新会下载;分别记录容器实际镜像 ID 与仓库 digest;两者不是同一个标识,不应混比。
Q:有没有自动升级工具?
A:Watchtower 可监控镜像更新并自动重建容器,测试环境好用;生产慎用自动升级。
Q:K8s 里怎么升级?
A:kubectl set image deployment/myapp myapp=myapp:1.3 触发滚动更新;零停机取决于副本、探针、容量和应用行为,回退需保留修订并主动操作或配置发布控制。