如何解决“无法检索 .使用 Jenkins 管道构建 Docker 映像时的 Id from docker

How to resolve "Cannot retrieve .Id from docker" when building Docker image using Jenkins pipeline

提问人:fuzzi 提问时间:8/4/2018 更新时间:9/27/2019 访问量:14011

问:

我正在使用 Jenkins 管道来构建 Dockerfile。

dockerfile 成功完成所有步骤,并创建 docker 映像。

如图所示:

Step 16/19 : FROM base AS final
 ---> <id>
Step 17/19 : WORKDIR /app
 ---> Using cache
 ---> <id>
Step 18/19 : COPY --from=publish /app .
 ---> Using cache
 ---> <id>
Step 19/19 : ENTRYPOINT ["", "myapp.dll"]
 ---> Using cache
 ---> <id>
Successfully built cb3y81938e88
Successfully tagged myapp:latest

但是,在此之后,shell 失败并出现以下错误:

java.io.IOException: Cannot retrieve .Id from 'docker inspect base AS final'

为什么尽管成功构建了 docker 映像,但它还是会抛出此错误? 当我在本地计算机上执行此命令时,该命令在“已成功标记 myapp:latest”时退出

我的 docker 版本是 18.03.1-ce。

关于这个问题的任何帮助将不胜感激!

docker Jenkins dockerfile jenkins-pipeline

评论

2赞 mkobit 8/4/2018
我的猜测是 Jenkins Docker 插件没有正确支持多阶段 Docker 构建。
0赞 David Bensoussan 4/18/2019
这里有一个 PR 解决了这个问题: github.com/jenkinsci/docker-workflow-plugin/pull/162 您可以构建插件并手动加载它,直到维护者检查为止

答:

23赞 Robert 8/7/2018 #1

该 Jenkins 插件中似乎存在错误。

您可以尝试删除多阶段构建名称(“”,因为您不需要它):AS final

FROM base
(....)

但是,如果您确实需要引用以前构建的映像(多阶段),则可以使用解决方法(对应于 0,1,2,而不是别名)--copy-from 0

Jenkins 中的相关问题


编辑

这里记录了OP找到的解决方案:

我没有使用 Jenkinsfile 管道文件,而是在 Jenkins 作业中执行 Shell 来执行 Docker 构建命令。(docker build -t latest-build 。

评论

0赞 fuzzi 8/8/2018
感谢@Robert我删除了刚刚的,但是现在错误已更改为我没有在我的 Dockerfile 中检查,但怀疑运行仍然存在问题??我来看看相关问题。AS finalFROM baseCannot retrieve .Id from 'docker inspect base'FROM base
0赞 Robert 8/8/2018
其中一张票提到了一个非常奇怪的解决方法,即在 Dockerfile 的最顶部添加这个“从头开始”,然后在每个后面的“FROM”之前附加一个空格。你能试试吗?
1赞 fuzzi 8/8/2018
谢谢,我试过了,但是我仍然得到错误,使用两种潜在的解决方案(FROM scratch,带有FROM缩进和删除AS final),我得到了错误Cannot retrieve .Id from 'docker inspect base AS final' Cannot retrieve .Id from 'docker inspect base'
2赞 fuzzi 8/8/2018
我没有使用 Jenkinsfile 管道文件,而是在 Jenkins 作业中执行 Shell 来执行 Docker 构建命令。
0赞 Deacon 1/9/2019
使用索引对我来说效果很好。谢谢!COPY --from=0
1赞 Andrew Schlei 2/19/2019 #2

我在 Docker 18.09 中遇到了同样的问题,但我没有使用多阶段构建。就我而言,我得到了:

java.io.IOException: Cannot retrieve .Id from 'docker inspect centos:7'

我的 Dockerfile 的第一步是:

FROM centos:7

我能够解决这个问题;之后,Jenkins 构建能够成功完成。docker pull centos:7

评论

0赞 Arnold Balliu 3/16/2019
这奏效了。澄清一下,因为这个答案并不完整:你需要运行“docker pull...”在不同的阶段中,以便在分阶段使用不同的代理时,它会在代理指令之前运行。如果您只使用一个代理,那么我建议您考虑使用多个代理来解决问题,方法是将其与此处的答案耦合。
2赞 Steve Mason 5/7/2019 #3

我之所以遇到这个问题,是因为我只在某个点上构建我的形象。--target=<foo>

所以我的 Dockerfile 看起来像这样

FROM maven:3.6-jdk-8 AS BUILD

.. do build ..

FROM openjdk:8

COPY --from=BUILD /myapp/bin my_jar_file

我的构建失败了:docker.build(<tag>, "--target=BUILD .")

java.io.IOException: Cannot retrieve .Id from 'docker inspect openjdk:8'

这是因为 Jenkins 正在尝试检查 Dockerfile 中的第二个目标,并且由于该目标未运行,Docker 未拉下该映像,因此它不可用FROM openjdk:8docker inspect

我有很多可用的解决方法:

  1. 在生成之前运行,确保映像仍然可用docker pull openjdk:8
  2. 从我的命令中删除并让它构建整个东西(对我来说没什么大不了的,因为构建是最昂贵的部分)--target=BUILDdocker.build
  3. 避免使用,只是docker.buildsh "docker build --target=BUILD .

目前我不确定我会选择哪一个

0赞 Jmyc 9/27/2019 #4

上述想法都不适用于我的情况,我终于让它像下面的管道一样工作,而无需在 Dockerfile 上吟唱任何内容:

  1. 像“latest”这样对构建标签进行硬编码,
  2. 通过 sh 获取你自己的标签,
  3. 首先使用硬编码标签推送您的图像,
  4. 使用自定义标签再次推送图像。
def my_own_tag = "unknown"
my_own_tag = sh ( script: 'git tag | tail -n1', returnStdout: true ).trim()
docker_img = docker.build("latest")
docker_img.push("latest")
docker_img.push("${my_own_tag}")