在搭建容器化平台时,我们经常会遇到内部镜像仓库使用自签名证书甚至纯 HTTP 协议的情况。此时容器运行时出于安全策略默认拒绝与之通信,必须显式声明 insecure-registries 才能建立连接。不同运行时的配置路径和语法存在明显区别,若处理不当会导致服务无法启动或节点间镜像分发失败。

Docker 环境下的 daemon.json 配置实践
Docker 是最早广泛使用 insecure-registries 概念的容器引擎。其配置核心在于修改守护进程配置文件,通常位于 /etc/docker/daemon.json。该文件采用 JSON 格式,我们需要在其中增加一个键为 insecure-registries 的数组,把内部仓库的地址和端口写进去。地址既可以写 IP 加端口,也可以写域名加端口,但不能包含协议头。
例如企业内部搭建了一个 Harbor 仓库,地址是 192.168.10.5:5000,且未配置受信任的 TLS 证书。我们可以在 daemon.json 中写入如下内容。修改完成后必须重启 docker 服务,配置才会被重新加载,仅重载配置而不重启进程往往不会生效。
{
"insecure-registries": [
"192.168.10.5:5000",
"registry.internal.company.com:5000"
]
}
重启命令在不同系统中有差异,Systemd 系统使用 systemctl restart docker,而老版本 Upstart 使用 service docker restart。重启后可通过 docker info 命令查看输出中是否包含我们配置的仓库地址,以此验证是否生效。如果 JSON 格式写错,比如少了逗号或引号,Docker 会启动失败,此时需要检查 /var/log/docker.log 中的报错。
使用 insecure-registries 的主要优势是免去申请证书的繁琐,适合测试和隔离网络。但风险在于通信不再加密且无法验证对方身份,攻击者若身处同一网络可劫持流量。因此在生产环境,我们仍建议用权威 CA 签发证书,或采用私有 PKI 并让节点信任该根证书,而非长期依赖不安全注册表配置。
Containerd 与 Kubernetes 节点的适配方式
随着 Kubernetes 弃用 Docker Shim,Containerd 成为更主流的运行时。它的配置不在 daemon.json,而是位于 /etc/containerd/config.toml。Containerd 使用 TOML 格式,insecure-registries 相关设置嵌套在 plugins."io.containerd.grpc.v1.cri".registry 段落中,结构比 Docker 更复杂。
我们需要先找到 config.toml 中的 [plugins."io.containerd.grpc.v1.cri".registry] 区块,在其中添加 configs 数组,为每个不安全仓库指定 skip_verify 或 tls 配置。如果只是纯 HTTP,可设置 endpoint 并使用不加密方式。下面示例展示了如何对 192.168.10.5:5000 关闭校验。
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.10.5:5000".tls]
insecure_skip_verify = true
修改后同样需要重启 Containerd 服务,命令为 systemctl restart containerd。在 Kubernetes 中,如果节点使用 Containerd,kubelet 拉取镜像实际调用的是 Containerd 的能力,因此仅配置 Docker 无效。很多运维人员误以为两个运行时配置互不干扰,结果节点仍报 ImagePullBackOff,排查时才发现是 Containerd 未放开限制。
从架构角度看,Containerd 将镜像仓库配置细化到每个 endpoint,比 Docker 的全局数组更灵活,但也更容易因格式缩进错误导致解析失败。TOML 对缩进不敏感但要求段落归属明确,建议使用 containerd config default > config.toml 生成基础模板再修改,避免手工拼写出错。
常见错误排查与安全替代方案
配置 insecure-registries 后最常见的问题是地址写法和协议混用。例如在 Docker 中写成 https://192.168.10.5:5000,引擎会认为格式非法;在 Containerd 中忘记加端口,也会匹配不到实际仓库。此外,若防火墙未放行仓库端口,即使配置正确也会拉取超时,此时容易被误判为配置未生效。
另一个隐蔽错误是混合云场景中节点系统时间偏差过大,即便使用正规证书也会校验失败,有人便一律改用 insecure 模式绕过。这其实掩盖了时间同步问题,正确做法是用 NTP 服务校准时钟,而非关闭安全机制。我们可以用 date 命令快速比对节点时间,或用 openssl s_client 测试证书链。
openssl s_client -connect 192.168.10.5:5000 -showcerts
如果确实需要在内网长期使用自签仓库,更安全的替代方案是向所有节点分发自签 CA 证书,并在运行时配置 trusted-ca-file,而不是标记仓库为不安全。Docker 可把 CA 放在 /etc/docker/certs.d/仓库地址/ca.crt,Containerd 则在 tls 段指定 ca_file。这样既保留加密与身份验证,又免去公开证书申请流程,是兼顾效率与安全的折中办法。
总体来看,insecure-registries 是一把双刃剑。理解各运行时的字段语义与加载机制,配合网络和时间等基础设施排查,才能用得稳而不留隐患。在自动化运维中,可用配置管理工具统一下发上述文件,确保集群所有节点行为一致,避免个别机器因手工遗漏而引发诡异的镜像拉取故障。
insecure-registriesDockercontainer_registry修改时间:2026-08-15 22:14:17