【问题标题】:Docker Compose does not allow to use local imagesDocker Compose 不允许使用本地镜像
【发布时间】:2018-02-12 10:00:07
【问题描述】:

以下命令失败,尝试从 Docker Hub 拉取镜像:

$ docker-compose up -d
Pulling web-server (web-server:staging)...
ERROR: repository web-server not found: does not exist or no pull access

但我只想使用本地版本的图像,它存在:

$ docker images
REPOSITORY           TAG                 IMAGE ID            CREATED             SIZE
web-server           staging             b94573990687        7 hours ago         365MB

为什么 Docker 不在本地存储的图像中搜索?


这是我的 Docker Compose 文件:

version: '3'
services:
  chat-server:
    image: chat-server:staging
    ports:
      - "8110:8110"
  web-server:
    image: web-server:staging
    ports:
      - "80:80"
      - "443:443"
      - "8009:8009"
      - "8443:8443"

还有我的 .env 文件:

DOCKER_HOST=tcp://***.***.**.**:2376
DOCKER_TLS_VERIFY=true 
DOCKER_CERT_PATH=/Users/Victor/Documents/Development/projects/.../target/docker

【问题讨论】:

  • 你能验证'web-server'镜像是在本地构建的吗?请包含docker-compose.yml文件
  • 也许其中一项工作:重新启动 docker 服务;使用 docker build 再次构建 web-server 映像;然后,尝试 docker-compose run。
  • 是的 - 你可以。如果使用 docker-compose,您可以使用相对路径。删除现有的docker containers - docker rm -f chat-server:stagingdocker rm -f web-server:staging。 - 使用下面的检查答案添加相对路径。
  • 也可以使用docker-compose images docker-compose ps 查看您的图像/容器是否在docker-compose
  • 用部分ID试一试怎么样image: b94573990687

标签: docker docker-compose


【解决方案1】:

你的 .env 中有一个 DOCKER_HOST 条目?

从 .env 文件的外观看来,您似乎已将 docker-compose 配置为使用远程 docker 主机:

DOCKER_HOST=tcp://***.***.**.**:2376

此外,这个 .env 仅由 docker-compose 加载,而不是由 docker 加载。所以在这种情况下,您的docker images 输出并不代表运行docker-compose 时可用的图像。

当运行 docker-compose 时,您实际上是在远程主机 tcp://***.***.**.**:2376 上运行 Docker,而在单独运行 docker 时,您是在本地运行 Docker。

当您运行docker images 时,您确实会看到存储在您机器上本地的图像列表。但是docker-compose up -d 将尝试不在您的本地机器上启动容器,而是在***.***.**.**:2376 上。 docker images 不会向您显示远程 Docker 主机上可用的映像,除非您设置 DOCKER_HOST 环境变量,例如:

DOCKER_HOST=tcp://***.***.**.**:2376 docker images

显然,远程 Docker 主机没有存储web-server:staging 映像,Docker 集线器上也没有可用的映像。这就是为什么 Docker 抱怨它找不到镜像的原因。

解决方案

在本地运行容器

如果您打算在本地运行容器,则只需从 .env 中删除 DOCKER_HOST=... 行并重试。

将图像推送到存储库。

但是,如果您计划在给定的 DOCKER_HOST 上远程运行映像,那么您可能应该将其推送到存储库。你可以在 Docker Hub 创建一个免费的仓库,或者你可以在某个地方托管你自己的仓库,然后使用docker push 将镜像推送到那里,然后确保你的 docker-compose.yml 引用了正确的仓库。

保存图片,远程加载。

如果您不想将映像推送到 Docker Hub 或托管自己的存储库,您也可以使用 docker image savedocker image load 的组合来传输映像:

docker image save web-server:staging | DOCKER_HOST=tcp://***.***.**.**:2376 docker image load

请注意,对于大图像,这可能需要一段时间,尤其是在连接速度较慢的情况下。

【讨论】:

  • 恕我直言,这是解决实际问题的唯一答案。我不明白为什么它没有更多的选票...
【解决方案2】:

版本 >1.23(2019 及更高版本)

最简单的方法是将image改为build:,并在相关目录中引用Dockerfile,如下图:

version: '3.0'
services:
  custom_1:
    build:
      context: ./my_dir
      dockerfile: Dockerfile

这允许docker-compose 在单个命令中管理整个构建和映像编排。

# Rebuild all images
docker-compose build
# Run system
docker-compose up

【讨论】:

  • 很好的答案,谢谢。 docker-compose 很好地将生成的容器标记为custom_1:latest,以便您可以轻松引用它。
  • docker-compose up 不会重建图像吗?
【解决方案3】:

对我来说,放 "build: ." 就可以了。我的工作 docker compose 文件看起来像这样,

version: '3.0'
services:
  terraform:
    build: .
    image: tf:staging
    env_file: .env
    working_dir: /opt
    volumes:
      - ~/.aws:/.aws

【讨论】:

  • 我发现这个解决方案是最简单的,它对我有用。谢谢你!
【解决方案4】:

在我的测试中,你必须指定一个数字标签,否则 docker 将尝试远程检查最新版本。

将您的本地图像重命名为“web-server:1”而不是“web-server:staging”,并相应地更改您的撰写文件。

【讨论】:

    【解决方案5】:

    可以引用本地图片名称​​也可以不加标签

    docker build -t imagename .
    

    可以引用为:

    version: "3"
    services:
      web:
        image: imagename
    

    在 docker-compose yaml 中。

    【讨论】:

    • 这个问题存在的原因是上面的行不通。
    【解决方案6】:

    2020 年 3 月 9 日编辑:

    (docker 版本 18.09.9-ce build 039a7df, dockercompose 版本 1.24.0,构建 0aa59064)

    我发现要创建一个 docker 容器,您可以在使用伪造的本地注册表服务器标签 (localhost:5000/{image}) 标记容器后 docker-compose 'up -d'。

    $ docker tag {imagename}:{imagetag} localhost:5000/{imagename}:{imagetag}
    

    你不需要运行本地注册服务器,但需要将dockercompose yaml文件中的镜像url更改为伪造的本地注册服务器url:

    version: '3'
    services:
    web-server:
      image: localhost:5000/{your-image-name} #change from {imagename}:{imagetag} to localhost:5000/{imagename}:{imagetag}
      ports:
        - "80:80"
    

    从 {imagename}:{imagetag} 到 localhost:5000/{imagename}:{imagetag}

    只是向上 -d

    $ docker-compose -f {yamlfile}.yaml up -d 
    

    如果您的本地计算机中已经有图像 (localhost:5000/{imagename}),则会创建容器。


    添加到@Tom Saleeba 的回复中,

    用“/”标记容器后仍然出现错误 (例如:victor-dombrovsky/docker-image:latest) 它一直在从远程 docker.io 服务器中寻找图像。

    registry_address/docker-image
    

    似乎“/”之前的url是注册地址,“/”之后是图像名称。如果没有提供“/”,docker-compose 默认会从远程 docker.io 中查找图像。

    它猜测它是带有 docker-compose 的 known bug

    我终于通过running the local registry 让它工作了,使用注册表标签将图像推送到本地注册表,并从本地注册表中提取图像。

    $ docker run -d -p 5000:5000 --restart=always --name registry registry:2
    $ docker tag your-image-name:latest localhost:5000/your-image-name
    $ docker push localhost:5000/your-image-name
    

    然后修改dockerfile中的图片url:

    version: '3'
    services:
      chat-server:
        image: chat-server:staging
        ports:
          - "8110:8110"
      web-server:
        image: localhost:5000/{your-image-name} #####change here
        ports:
          - "80:80"
          - "443:443"
          - "8009:8009"
          - "8443:8443"
    

    对于聊天服务器图像也是如此。

    【讨论】:

    • 你的解决方案帮助了我
    • 很好的解决方案!
    • 不错!和Tom Saleeba mentions, 一样,/ 之前的部分不必是主机名,它可以像local/your-image-name 一样简单。
    【解决方案7】:

    您可能需要更改您的图片标签,使其两部分由斜线/ 分隔。所以不是

    chat-server:staging
    

    做一些类似的事情:

    victor-dombrovsky/chat-server:staging
    

    我认为 Docker 标签背后有一些逻辑,“一部分”标签被解释为来自 DockerHub 的官方图像。

    【讨论】:

      【解决方案8】:

      一般来说,这应该如您所描述的那样工作。试图重现它,但它只是工作......

      文件夹结构:

      .
      ├── docker-compose.yml
      └── Dockerfile
      

      Dockerfile 的内容:

      FROM alpine
      CMD ["echo", "i am groot"]
      

      构建和标记图像:

      docker build -t groot .
      docker tag groot:latest groot:staging
      

      使用 docker-compose.yml:

      version: '3.1'
      services:
        groot:
          image: groot:staging
      

      并启动 docker-compose:

      $ docker-compose up
      Creating groot_groot ... 
      Creating groot_groot_1 ... done
      Attaching to groot_groot_1
      groot_1  | i am groot
      groot_groot_1 exited with code 0
      

      【讨论】:

      • 这个解决方案在我的 gocd ci 上工作,我在每次运行之前擦除所有容器和图像,但不在我的开发机器上工作......
      • 您可能需要使用此命令来构建映像并强制创建新容器:docker-compose up --build --force-recreate
      【解决方案9】:

      在您的 docker-compose.yml 中,您可以为本地构建指定 build: . 而不是 build: <username>/repo>(而不是从 docker-hub 中提取) - 我还无法验证这一点,但我相信您 可能 可以为 docker-compose 文件的多个服务做相对路径。

      services:
        app:
          build: .
      

      参考:https://github.com/gvilarino/docker-workshop

      【讨论】:

      • 我知道可以在本地构建映像,但我认为这不是一个好主意。在我看来,最好将构建和运行步骤分开,如下所述:12factor.net/build-release-run
      • 这是一个很好的观点,我同意 - 这不应该在任何正常情况下使用,但是,与在本地构建然后推送到 docker hub 相比,我相信这是一个快速的步骤(特别是如果你想检查服务是否相互通信)-
      • 我来自未来,我验证build: ./app ... build: ./other-app 有效
      • 如果您想快速测试本地更改(例如稍后使用 git repo),这非常有用