You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单机器上构建私有Docker镜像并在docker-compose中正常使用?

解决同docker-compose配置中使用私有Registry镜像的启动顺序问题

问题背景

我在服务器上用docker-compose管理服务栈,同时用drone.io构建项目的私有Docker镜像——因为不想把镜像推送到Docker Hub,所以打算在同一个docker-compose.yml里部署一个Registry容器,让CI自动把构建好的镜像推送到这个本地Registry,然后直接用这个镜像启动业务容器。

但执行docker-compose up -d时遇到了报错:

Network traefik_public is external, skipping
Pulling myimage (registry.example.com:5000/username/myimage:)...
ERROR: Get https://registry.example.com:5000/v2/: dial tcp MY-IP:5000: connect: connection refused

原因很明确:Docker在启动容器前会先尝试拉取镜像,这时候Registry容器还没启动,自然无法连接。depends_on只是控制容器启动的先后顺序,管不了镜像拉取这个前置步骤。目前的临时解决办法是分两次启动:先注释掉业务容器,启动Registry,再恢复注释启动业务容器,但这样完全失去了单配置文件管理的便捷性。

想请教:有没有更优雅的解决方案?用私有Registry这条路可行吗?


可行解决方案

1. 提前独立启动Registry容器

把Registry从主docker-compose.yml拆分出来,单独维护一个小配置文件(比如docker-compose.registry.yml):

version: "3.7"
services:
  registry:
    image: registry:2
    networks:
      - traefik_public
    ports:
      - '5000:5000'
    labels: # traefik labels 配置
networks:
  traefik_public:
    external: true

之后每次启动整个服务栈前,先启动Registry:

docker-compose -f docker-compose.registry.yml up -d

等Registry运行稳定后,再启动主服务:

docker-compose up -d

如果不想拆分文件,也可以用Docker Compose的profile功能给Registry打标记:

services:
  registry:
    image: registry:2
    profiles: ["registry"] # 添加profile标记
    # 其他配置...

启动时先单独拉起Registry:

docker-compose --profile registry up -d

再启动所有服务(此时Registry已经运行):

docker-compose up -d

2. 让构建的镜像直接存于本地Docker(无需Registry中转)

既然drone.io是在同一台服务器构建镜像,其实可以跳过Registry中转,直接把构建好的镜像留在本地Docker环境里:

  • 如果drone的runner运行在这台服务器上,构建完成后镜像会自动保存在本地,docker-compose直接使用镜像名称即可(不用带Registry前缀)。
  • 如果drone runner在其他机器,可以在构建流水线里添加步骤:用docker save把镜像导出为tar包,通过scp传到目标服务器,再用docker load导入到本地Docker。

这种方式完全绕开了Registry的启动顺序问题,是最省心的方案之一。

3. 配置Docker信任私有Registry(必做步骤)

如果你的私有Registry使用HTTP协议(或者自签名HTTPS证书),Docker默认会拒绝连接,这也可能是报错的隐藏原因。需要把Registry加入Docker的信任列表:

  1. 编辑/etc/docker/daemon.json(如果不存在就创建):
{
  "insecure-registries": ["registry.example.com:5000"]
}
  1. 重启Docker守护进程:
systemctl restart docker

4. 用健康检查+depends_on(适合镜像已存在的场景)

如果你的业务镜像已经通过CI推送到Registry过(或者手动拉取过一次),可以通过健康检查让业务容器等待Registry完全就绪后再启动:
给Registry添加健康检查配置:

registry:
  image: registry:2
  # 其他配置...
  healthcheck:
    test: ["CMD", "curl", "-f", "http://localhost:5000/v2/"]
    interval: 5s
    timeout: 5s
    retries: 3

然后修改业务容器的depends_on:

myimage:
  image: registry.example.com:5000/username/myimage
  depends_on:
    registry:
      condition: service_healthy
  # 其他配置...

注意:这个方法解决不了第一次拉取镜像的问题——因为镜像拉取发生在容器创建之前,这时候Registry还没完成健康检查。它只适用于镜像已经存在本地的场景。


总结

私有Registry完全可行,核心问题是解决镜像拉取时机早于Registry启动的矛盾。优先推荐的方案是:要么提前独立启动Registry,要么让CI直接把镜像部署到本地Docker环境,跳过Registry中转。

内容的提问来源于stack exchange,提问作者Filip Gdovin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:43:55