Docker容器运行失败排查及代码更新后镜像处理咨询
一、Docker Run命令报错的原因及解决方法
你执行docker run 10fc47e065ff:0.0.1-SNAPSHOT后出现如下报错:
Unable to find image '10fc47e065ff:0.0.1-SNAPSHOT' locally
docker: error response from daemon: pull access denied for 10fc47e065ff, repository does not exist or may require 'docker login': denied: requested access to the resource is denied.
错误原因是Docker的语法规则限制:
- 镜像ID是镜像的唯一标识,直接使用ID即可运行容器,不需要额外添加标签。当你在ID后追加
:0.0.1-SNAPSHOT时,Docker会把10fc47e065ff识别为远程仓库名称,尝试去DockerHub拉取该仓库下标签为0.0.1-SNAPSHOT的镜像,而这个仓库实际不存在,因此触发报错。
正确的运行方式任选其一即可:
- 仅使用镜像ID:
docker run 10fc47e065ff - 使用仓库名+标签:
docker run backend:0.0.1-SNAPSHOT或docker run testName/backend:0.0.1-SNAPSHOT
从你的docker images输出能看到,testName/backend:0.0.1-SNAPSHOT和backend:0.0.1-SNAPSHOT是同一个镜像(ID完全相同),所以用哪个命令都可以正常启动容器。
二、代码修改后是否需要重新创建镜像?
必须重新构建镜像,docker run不会自动覆盖现有镜像或获取最新代码,原因如下:
- Docker镜像是静态只读的文件集合,构建时会把编译好的Spring Boot jar包(以及Angular打包后的静态文件,如果包含在构建流程内)复制到镜像内部,一旦镜像构建完成,里面的内容就固定下来了。
- 从你的Dockerfile和build.gradle配置来看,镜像构建阶段会把本地编译好的jar包COPY进镜像,所以代码修改后,必须重新执行镜像构建命令(比如通过Gradle的
docker任务),生成包含最新代码的镜像,再用新镜像运行容器才能获取应用的最新版本。
如果想在开发阶段减少频繁重建镜像的操作,可以采用本地目录挂载的方式:将本地代码的编译输出目录(比如Spring Boot的build/libs、Angular的dist目录)挂载到容器内对应的文件路径,这样修改代码并本地编译后,容器内就能直接读取到最新文件。但这种方式仅适合开发环境,生产环境仍建议通过重新构建镜像来保证应用的一致性和稳定性。
配置文件补充问题
你的Dockerfile存在路径不匹配的问题:
COPY ${JAR_FILE} backend.jar ENTRYPOINT ["java","-jar","/backend-0.0.1-SNAPSHOT.jar"]
你把jar包复制到容器内命名为backend.jar,但ENTRYPOINT里指定运行的是/backend-0.0.1-SNAPSHOT.jar,这会导致容器启动时找不到文件而失败。需要把ENTRYPOINT改成:
ENTRYPOINT ["java","-jar","/backend.jar"]
内容的提问来源于stack exchange,提问作者Krktester23

