DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Docker 镜像已更新,网页仍显示旧内容:命名卷遮住了新版静态资源

镜像已经更新但网页仍是旧版本时,比较实际镜像 ID 和静态目录挂载;区分发布资源与持久数据,安全更新命名卷使用方式。

修改镜像中的 index.html 后重新构建,直接运行新镜像可以看到新版页面;用 Compose 启动却仍显示旧内容。若站点目录挂载了一个已经使用过的命名卷,先检查这层挂载。重新构建镜像不会替换卷里的文件。

本文适用于 Docker Engine 的普通命名卷及 Compose 服务。绑定挂载、Kubernetes 存储和应用自己的升级程序不能直接按同一机制判断。

先确认容器实际在读哪里

下面是容易出现这种现象的配置示例:

services:
  web:
    image: example-web:release-tag
    volumes:
      - html:/usr/share/nginx/html
volumes:
  html:

example-web:release-tag 表示自己的应用镜像。html 是持久存储,不是“每次从镜像取得最新网页”的开关。空卷首次挂入有文件的目录时,默认会复制该目录的内容;卷已有内容后,挂载内容会遮住镜像里的同名目录。设置 nocopy 可以禁止初始复制,但不能让旧卷自动更新。

在部署项目目录中查看目标容器;自定义文件、项目名等参数应与部署时一致:

docker compose ps -q web
docker inspect --format '{{json .Mounts}}' CONTAINER_ID
docker inspect --format '{{.Image}}' CONTAINER_ID
docker image inspect --format '{{.Id}}' example-web:release-tag

将 CONTAINER_ID 替换成第一条输出的容器 ID。先比较后两条镜像 ID:不同说明容器还没有切到目标镜像,要先处理容器更新。相同而 Mounts 中有 Type=volume、目标为静态资源目录,则继续检查卷,不要反复清构建缓存。

Mounts.Name 才是 Docker 实际卷名,它可能带 Compose 项目前缀。检查时记录这个名字,避免误操作另一个项目的同名逻辑卷。

代码和持久数据应采用不同更新办法

如果目录里只有随镜像发布的网页、程序或依赖,通常可以去掉这个目录的卷挂载,让容器直接读取镜像内容。修改前保存部署配置、旧镜像版本,并备份卷;确认没有上传文件、用户生成内容或其他写入数据。

只删除目标服务中的对应挂载项,保留数据库卷与其他持久目录。目标镜像已经准备好、依赖服务已运行时,可在维护窗口更新服务:

docker compose up -d --no-deps web

这会按新配置重建服务,期间可能中断请求。旧卷不需要删除;即使顶层卷声明暂时保留,没有服务挂它也不会继续遮住该目录。回退时恢复原挂载配置和旧镜像,再更新同一服务。

如果目录必须保存上传数据,直接移除挂载会让那些文件暂时不可见。应先把发布资源与用户数据分到不同目录,再按应用的迁移流程调整挂载。应用允许更新卷中资源时,也应使用明确的升级或同步步骤:先备份,核对覆盖范围,防止把用户文件当作旧代码覆盖。

仅用于可重建静态资源的卷,也可以换一个新的卷名作为发布版本。但这会生成独立数据副本、占用空间,必须保留旧卷供回退,并确认所有读取该卷的服务一起切换。它不是数据库或用户上传目录的通用升级方法。

不要用 docker compose down -v 作为网页更新办法。它可能连同数据库等卷一起删除。重建容器、删除容器和删除持久卷是三个不同动作。

怎样确认已经修正

更新后再次核对镜像 ID 和挂载列表,确认静态资源目录已经采用预期的存储方式。读取实际运行容器中的发布版本标识,再请求站点检查对应页面,两者都应与本次发布一致。

若容器内已经是新版,公网仍是旧版,再检查反向代理、CDN 或浏览器缓存;不要继续修改数据卷。如果容器内也还是旧版,先返回镜像与挂载检查,页面缓存不能解释容器里的文件内容。