APT 更新 Docker 软件源时报 Signed-By 冲突
APT 更新 Docker 软件源时报 Signed-By 冲突。定位同一仓库的重复 .list 与 .sources 条目,备份后只停用确认多余的配置,保留签名验证,并核对索引更新、软件包来源和回退路径。
执行 sudo apt-get update,APT 没有开始下载软件包索引,就报:
E: Conflicting values set for option Signed-By regarding source https://download.docker.com/linux/debian/ bullseye: /usr/share/keyrings/docker-ce-archive-keyring.gpg != /usr/share/keyrings/docker-archive-keyring.gpg
E: The list of sources could not be read.
错误信息列出了冲突对象:同一个仓库地址、同一个发行版代号,出现了两个不同的 Signed-By 配置。需要找到重复的源条目,保留正确的一份,而不是反复导入公钥。
先后使用不同安装步骤,可能同时留下 docker-ce.list、docker.list 或 docker.sources。它们若指向同一个仓库和发行版,却设置了不同的 keyring 路径,就需要处理重复条目。删除密钥或重启机器不会改变源文件里的冲突。
下面处理 Debian、Ubuntu 中 APT 默认源目录下的配置冲突,以当前报错中的仓库、代号和路径为准,不需要卸载 Docker 或删除容器数据。
找出两份源配置
APT 通常读取 /etc/apt/sources.list,以及 /etc/apt/sources.list.d/ 下的 .list 和 .sources 文件。旧教程常用一行式 .list,新配置可能是多行的 deb822 .sources,只查 docker.list 容易漏掉另一份。
先搜索默认源目录。下面的命令只读取配置;如果机器没有 /etc/apt/sources.list,去掉这个路径参数,保留目录参数即可:
sudo grep -RnE --include='*.list' --include='*.sources' \
'download[.]docker[.]com|[Ss]igned-[Bb]y' \
/etc/apt/sources.list /etc/apt/sources.list.d
搜索结果带文件名和行号。随后阅读命中的完整文件,尤其是 .sources 文件中由空行分隔的条目。例如检查这两份文件:
sudo cat /etc/apt/sources.list.d/docker-ce.list \
/etc/apt/sources.list.d/docker.list
文件名只是示例,应换成搜索实际找到的路径。有 docker.sources 时也要读取它;重复条目也可能藏在主 sources.list、面板生成的源文件或其他名称的文件里。
对照报错检查仓库 URI、Suite,以及 Signed-By。一行式配置中的 bullseye 是 Suite,stable 是 Component;deb822 对应 URIs:、Suites:、Components: 和 Signed-By:。不要因为文件名不同,就以为它们指向不同的仓库。
命中的条目还要核对是否生效。.list 中以 # 注释掉的源不参与更新;.sources 中设置了 Enabled: no 的条目也已停用。还要区分不同的 Suite,不能把同一域名下的其他发行版条目误当作这次冲突。若实际调用通过 -c 或 APT 配置更改了源目录,需要在对应目录继续查找。
APT 要求,同一 URI 和 Suite 的部分选项在各源条目之间保持一致。APT 对 Signed-By 的配置做规范化后比较,值不一致时会返回这条错误。即使两个文件里装的是同一把公钥,不同的引用路径也不会自动变成同一个配置值。
备份后停用确认重复的条目
保留的源应匹配系统、仓库和架构,并引用可用的签名密钥,不能只按文件时间选择。Docker 当前的 Debian、Ubuntu 安装示例使用 docker.sources 和 /etc/apt/keyrings/docker.asc;已有 .list 或 .gpg 配置仍应按实际内容核对,不必为这次冲突一律迁移。
如果源由 NAS 面板、安装脚本或配置管理工具生成,先核对对应的管理入口,避免手工停用后又被自动写回来。可以用下面的命令检查文件是否登记在某个软件包中:
dpkg-query -S /etc/apt/sources.list.d/docker-ce.list
没有找到归属,也不能证明它一定是手工创建的:dpkg-query -S 不列出维护脚本额外创建的所有文件。文件头的生成说明和管理工具配置仍要核对。
备份当前源文件,使用 APT 源目录之外的新目录,避免备份本身再次被读取。以下示例在 /root 下保存权限为 0700 的目录;任何一步失败都应先处理,再继续修改:
apt_backup_dir="/root/apt-sources-backup-$(date +%Y%m%d-%H%M%S)"
sudo test ! -e "$apt_backup_dir" && sudo test ! -L "$apt_backup_dir" || { echo '备份目录已存在,请换一个新目录'; exit 1; }
sudo install -d -m 0700 "$apt_backup_dir" || exit 1
sudo cp -a /etc/apt/sources.list.d "$apt_backup_dir/" || exit 1
if sudo test -f /etc/apt/sources.list; then
sudo cp -a /etc/apt/sources.list "$apt_backup_dir/" || exit 1
fi
printf '备份目录:%s\n' "$apt_backup_dir"
记下打印出来的路径。这个备份保存源配置,本次不修改或删除密钥文件。如果源文件是符号链接,还要备份它实际指向的配置文件;cp -a 会保留链接本身。
如果确认 docker-ce.list 只包含需要停用的旧 Docker 源,而另一份正确配置仍然生效,可以把它移到备份目录:
sudo mv /etc/apt/sources.list.d/docker-ce.list \
"$apt_backup_dir/docker-ce.list.disabled"
如果一个文件混有多个仓库,只停用冲突的那条,不能移动整个文件。一行式 .list 在该行前加 #;deb822 .sources 则在要停用的条目中加入:
Enabled: no
Enabled: no 是条目字段,应放在对应的 Types:、URIs: 等字段所在段落中,不是往文件末尾随意追加一行。一个段落如果同时定义多个 URI 或 Suite,停用会影响这个段落的全部来源,要先分清范围。deb822 格式由 APT 1.1 起支持。
如果两条配置确实各有用途,需要保留不同 Component 或 deb、deb-src,则核对它们的完整内容,让同一 URI 和 Suite 的签名限制保持一致。不要用“把两份源都删掉再试”代替这个判断。
更新索引并核对 Docker 的来源
修改后重新执行:
sudo apt-get update
apt-cache policy docker-ce
确认 Signed-By 冲突和 The list of sources could not be read 消失后,还要查看 Docker 仓库的索引是否获取成功,以及 apt-cache policy 列出的版本来源是否符合预期。
只看到命令退出,或看到其他仓库更新成功,不足以说明 Docker 源恢复了。如果还有 DNS、TLS、NO_PUBKEY 或密钥不可读错误,应继续处理对应的问题;APT 可能保留旧索引,apt-cache 展示的也可能是缓存中的信息。apt-get update 用于同步索引,apt-cache 中的元数据可能过期。
若你之前已经删过密钥,需要恢复保留条目引用的正确密钥,或按当前官方文档重新设置对应仓库。只把 .gpg 的文件名改成 .asc,不能替代内容和格式的核对。签名密钥还必须可供 _apt 用户读取;不要通过 trusted=yes、关闭验证或扩大整个目录权限来绕过错误。
更新源文件和执行 apt-get update 不会升级已安装的 Docker,也不需要为这次配置修正重启 Docker 服务。确认仓库恢复后,再安排原本要做的安装或升级。
回退这次源配置变更
对于上面移出的独立文件,在确认原路径没有被其他操作重新创建后,可以移回:
sudo test ! -e /etc/apt/sources.list.d/docker-ce.list && \
sudo test ! -L /etc/apt/sources.list.d/docker-ce.list || {
echo '原路径已有文件,请先核对,不要覆盖'
exit 1
}
sudo mv "$apt_backup_dir/docker-ce.list.disabled" \
/etc/apt/sources.list.d/docker-ce.list
如果已经换了终端,先把 apt_backup_dir 设成此前记录的实际备份目录。用注释或 Enabled: no 停用的条目,则只恢复本次修改的内容,避免覆盖期间新增的其他源设置。
恢复重复条目会把原来的冲突带回来;回退的作用是恢复变更前的配置,不能算修复完成。若停用后 Docker 源完全消失,说明保留条目的选择有误,应从备份重新核对两份配置,而不是删掉全部 APT 源文件。


