在Ubuntu 22基础的docker镜像上,apt-get update失败

36

我正在尝试将我们的一个docker基础镜像升级到最新稳定版本的Ubuntu。我已经将问题隔离到了一个简单的可重现案例中。我有一个类似于以下的Dockerfile:

FROM ubuntu:22.04

MAINTAINER mep-dev@zulily.com

# Install java and clean-up
RUN apt-get update

当我在本地构建时,没有任何问题。然而,当我在我的CICD上构建时,有时会出现这个错误:

第3步/3:运行apt-get update
---> 正在运行6ca01b60de64中
获取:1 http://archive.ubuntu.com/ubuntu jammy InRelease [270 kB]
获取:2 http://security.ubuntu.com/ubuntu jammy-security InRelease [110 kB]
获取:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease [109 kB]
获取:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease [99.8 kB]
错误:1 http://archive.ubuntu.com/ubuntu jammy InRelease
由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
错误:3 http://archive.ubuntu.com/ubuntu jammy-updates InRelease
由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
错误:4 http://archive.ubuntu.com/ubuntu jammy-backports InRelease
由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
错误:2 http://security.ubuntu.com/ubuntu jammy-security InRelease
由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
正在读取软件包列表...
W:http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg。
W:http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg。
W:GPG错误:http://archive.ubuntu.com/ubuntu jammy InRelease:由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
E:存储库'http://archive.ubuntu.com/ubuntu jammy InRelease'未经过签名。
W:http://archive.ubuntu.com/ubuntu/dists/jammy-updates/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg。
W:http://archive.ubuntu.com/ubuntu/dists/jammy-updates/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg。
W:GPG错误:http://archive.ubuntu.com/ubuntu jammy-updates InRelease:由于公钥不可用,以下签名无法验证:NO_PUBKEY 871920D1991BC93C
E:存储库'http://archive.ubuntu.com/ubuntu jammy-updates InRelease'未经过签名。
W:http://archive.ubuntu.com/ubuntu/dists/jammy-backports/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg。
W:http://archive.ubuntu.com/ubuntu/dists/jammy-backports/InRelease:由于文件对用户“_apt”执行apt-key不可读,因此忽略密钥环中的密钥/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg。
W:GPG错误:http://archive.ubuntu.com/ubuntu jammy-backports InRelease:由于公钥不可用

如果我注释掉RUN apt-get update,然后成功了,我可以进入容器并查看/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg/etc/apt/trusted.gpg.d/ubuntu-keyring-2018-archive.gpg确实存在且对所有权限都有读取权限:

root@b778220b39d8:/# ls -l /etc/apt/trusted.gpg.d
total 8
-rw-r--r-- 1 root root 2794 Mar 26 2021 ubuntu-keyring-2012-cdimage.gpg
-rw-r--r-- 1 root root 1733 Mar 26 2021 ubuntu-keyring-2018-archive.gpg

我还检查了父目录,它们至少具有所有的r-x权限。 这个答案可能相关,但是为什么当基础图像在一个环境中使用时,文件具有正确的结构而在另一个环境中却没有呢?
更新:
通过使用--pull,我可以看到它正在使用的确切镜像。

$ docker build --pull -t $EMAIL_DELIVERABILITY_ARN .
Step 1/3 : FROM ubuntu:22.04
22.04: 从library/ubuntu中拉取
Digest: sha256:b6b83d3c331794420340093eb706a6f152d9c1fa51b262d9bf34594887c2c7ac
Status: 已下载新的镜像ubuntu:22.04
---> 27941809078c

这是与本地构建时看到的相同的sha和镜像ID,可以正常工作。
我在ubuntu:20.04上没有遇到同样的问题。

2
你的CICD环境是否有旧版本的镜像?在尝试构建镜像之前,你可以明确地执行 docker pull ubuntu:22.04 吗? - larsks
@larsks 我认为你的答案是正确的。想把它作为答案吗,这样你就可以获得声望分数了? - morningstar
你可以告诉我们有关你的CI/CD环境的任何信息吗? - larsks
你使用的 Docker 版本是哪个? - Tuxity
注意以下一行代码:W: http://security.ubuntu.com/ubuntu/dists/jammy-security/InRelease: The key(s) in the keyring /etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg are ignored as the file is not readable by user '_apt' executing apt-key.尝试使用 --security-opt seccomp:unconfined,这可能会产生安全风险,但可以解决此问题。$ docker run --security-opt seccomp:unconfined -it ubuntu:22.04参考链接: https://bugs.launchpad.net/cloud-images/+bug/1889311 https://github.com/tianon/docker-brew-ubuntu-core/issues/183 - Craig Comstock
这个回答解决了你的问题吗?为什么我无法在全新的ubuntu:22.04中运行'apt update'? - Per Lundberg
4个回答

32

在花费半天时间尝试修复Ubuntu镜像(它们并没有损坏)后,我最终开始调试主机。

这是一个docker问题。Ubuntu使用系统调用来提高密钥安全性,但Docker尚未支持。 解决方法是更新docker …或者使用nerdctl、runc或类似工具。

与其说是因为系统调用不受支持而导致的错误提示信息,实际上是权限被拒绝,这就导致了令人困惑的错误消息。

你可以在技术上对Ubuntu进行补丁修复以降低安全性并与旧版docker配合使用,但这不是长期的解决方案。

是解决Docker(/moby)项目中此问题PR的链接。请注意,由于glibc的更改与Docker的默认seccomp配置不兼容,该问题也可能出现在其他Docker镜像(或Ubuntu中的其他软件)中。


你的回答可以通过提供更多支持信息来改进。请编辑以添加进一步的细节,例如引用或文档,以便他人可以确认你的答案是正确的。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community
2
我通过更新 Docker 和 Docker Compose 来解决了这个问题。 - zoro
你升级后使用的 Docker 版本是哪个? - iggie
1
我也遇到了Docker Engine 19的这个bug,后来发现在Docker Engine 20上可以正常工作。 - wearego
非常感谢。我在我的Gitlab Ci/CD流水线中使用版本19.0.2运行Dind时遇到了相同的问题。我将docker更新到24.0.7后问题得以解决。 - undefined

8

对于一些Docker黑客来说,一个非常肮脏但可能可接受的技巧是这样的:

apt update --allow-insecure-repositories

这将忽略签名。错误仍然会被打印出来,但软件包存储库会得到更新,之后您可以安装新的软件包。即使您收到警告并被询问是否真的想要这样做。


这会导致后续出现其他错误。因此,最终我决定冒险,在主机系统上运行“apt update; apt upgrade”,更新到最新的Docker版本,从而解决了这个问题... - ineiti

4

完全相同的问题

错误:3 http://security.ubuntu.com/ubuntu jammy-security InRelease 以下签名无法验证,因为公钥不可用:NO_PUBKEY 871920D1991BC93C 正在读取软件包列表... [91mW: http://archive.ubuntu.com/ubuntu/dists/jammy/InRelease:由于文件对用户'_apt'执行apt-key不可读,因此忽略密钥环中的键/etc/apt/trusted.gpg.d/ubuntu-keyring-2012-cdimage.gpg。

Dockerfile(简单的重现方法)docker版本:18.x或19.03/

FROM ubuntu:latest
RUN apt-get -y update 

使用最新的 Docker 版本 20.10.9,我没有发现这个问题。
几种尝试解决问题的选项:
  1. sed -i 's/jammy/focal/g' /etc/apt/sources.list
  2. RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 871920D1991BC93C 但这会出现另一个子问题,在此之前需要安装 gnupg、gnupg2 和 gnupg1 中的一个。
所以,解决方案似乎是更新 Docker 版本或使用之前可以正常工作的标记图像。

同样的问题。如果您不想更新docker版本(或者您无法更新),您可以使用标记为ubuntu:20.04的镜像,它将运行apt-get update而不会出现任何问题。 - Steven de Salas

1
当您按名称引用Docker镜像时,Docker仅检查其是否存在于本地,而不会检查更新。因此,即使可能过时,如果已经有可用的命名图像版本,它也会使用该版本。我怀疑这就是您看到的情况:您的一些CI节点必须具有存在问题的缓存镜像版本。
处理此问题有几种方法:
  1. Explicitly docker pull ubuntu:22.04 before calling docker run; this will pull down a newer version of the image if one exists.

  2. Add --pull always to your docker run command line. This accomplishes the same thing but without requiring an extra command execution.

  3. Reference an image by digest rather than by tag. If you use an image reference like this:

    FROM ubuntu@sha256:bace9fb0d5923a675c894d5c815da75ffe35e24970166a48a4460a48ae6e0d19
    

然后Docker将使用这个确切的镜像。您可以在Docker Hub上找到镜像摘要。


谢谢。--pull 帮助我解决了一些混乱的结果,这与我的实际用例有关,其中包括我自己创建的中间基础镜像,并经常在解决这些问题时进行更新。然而,这三种方法都没有解决问题。我将使用我的其他发现编辑这个问题。 - morningstar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接