Docker Compose不允许使用本地镜像。

163
以下命令失败,尝试从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

3
你能否验证“web-server”镜像是否已经在本地构建?请包含docker-compose.yml文件。 - Denis Tsoi
1
也许以下其中一种方法可行:重启docker服务;再次使用docker build构建Web服务器镜像;然后尝试运行docker-compose。 - Aliakbar Abbasi
1
是的 - 您可以。如果使用docker-compose,您可以使用相对路径。删除现有的 docker容器 - docker rm -f chat-server:stagingdocker rm -f web-server:staging。- 使用下面的检查答案添加相对路径。 - Denis Tsoi
1
同时使用 docker-compose imagesdocker-compose ps 命令来查看你的镜像和容器是否在 docker-compose 中。 - Denis Tsoi
1
你想试试使用部分ID image: b94573990687 吗? - SangminKim
显示剩余6条评论
10个回答

114

总的来说,这应该按照你描述的方式工作。我试图重现它,但它只是起作用了...

文件夹结构:

.
├── docker-compose.yml
└── 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上运行良好,每次运行之前我会清除所有容器和镜像,但在我的开发机上无法运行... - mik3fly-4steri5k
你可能需要使用以下命令来构建镜像并强制创建新容器:docker-compose up --build --force-recreate - n2o

57

版本 >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

1
非常好的答案,谢谢。docker-compose会将生成的容器标记为custom_1:latest,这样您就可以轻松地引用它了。 - András Aszódi
“docker-compose up” 不会重新构建镜像吗? - Indika K
我的问题是我没有在image:指令中指定图像的标签。它可以在docker images命令的第二列中找到。但在我看来,这个解决方案甚至更好,因为它让Docker Compose管理服务容器的构建和编排,并自动使用docker compose build获取所有服务容器的Dockerfile所做的最新更改并根据需要重新构建它们。 - aderchox

29

在你的docker-compose.yml文件中,你可以使用build: .来代替build: <username>/repo>进行本地构建(而不是从Docker Hub拉取) - 我还无法验证,但我相信你可能能够对多个服务使用相对路径到docker-compose文件。

services:
  app:
    build: .

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


4
我知道可以在本地构建镜像,但我认为这不是一个好主意。在我看来,最好按照这里提到的将构建和运行步骤分开:https://12factor.net/build-release-run - Aliakbar Abbasi
2
这是一个很好的观点,我同意 - 在任何正常情况下都不应该使用它,但是,与本地构建然后推送到Docker Hub相比,我认为这是一个快速步骤(特别是如果您想检查服务之间是否通信)- - Denis Tsoi
14
我来自未来,我确认了build: ./app ... build: ./other-app是可行的。 - Josiah
1
如果您想快速测试本地更改(例如稍后使用Git存储库),那么这非常棒。 - java-addict301

23

2020年3月9日编辑:

我发现只需创建一个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}

然后只需执行-upd命令

$ 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的已知问题

最终,我通过运行本地注册表,将镜像推送到本地注册表并使用注册表标签从本地注册表中拉取镜像,使其工作。

$ 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提到的那样,斜杠前面的部分不一定是主机名,可以简单地写成local/your-image-name - Robert K. Bell
@RobertK.Bell 我注意到这并不像local/your-image-name那么简单,我不得不加一个点,比如foo.local/your-image-name,否则我会自动得到docker.io/local/your-image-name... - kubi

14

对我来说,只需要添加 "build: ." 即可。我的Docker Compose文件如下所示:

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

1
我发现这个解决方案是最简单的,而且它对我很有效。谢谢你! - alneven
确认:与 docker-compose version 1.29.2, build 5becea4c 完美配合。 - saulius2
哇,为什么这个东西是一个解决方案?我删除了每个图像/卷和所有内容,但我仍然有“docker使用图像”错误,并且当我尝试构建时,它正在尝试从dockerhub拉取。无法弄清原因。 - Mehmet Burak Sayıcı
1
这确实是最简单的解决方案,但如果您想在Azure应用程序服务上部署您的应用程序,则会失败,因为AAS不支持docker-compose.yml中的构建选项。 - Shaida Muhammad

12

你可能需要更改图像标签,使其由两个部分用斜杠/分隔。因此,不是

chat-server:staging

做一些类似于以下的事情:

victor-dombrovsky/chat-server:staging

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


11
您可以使用pull_policy
image: img:tag
pull_policy: if_not_present

1
仍然无法工作。 - aderchox
可以的。必须是被接受的答案。 - undefined
对于意识到的价值,现在是“missing”,“if_not_present”适用于向后兼容,但已被弃用 - 链接. - undefined

11

您在.env文件中有一个DOCKER_HOST条目

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

DOCKER_HOST=tcp://***.***.**.**:2376
此外,这个 .env 文件只会被 docker-compose 加载,而不是 docker。因此,在这种情况下,运行 docker-compose 时,docker images 命令输出的内容并不代表你在运行 docker-compose 时所能使用的镜像。
当你运行 docker-compose 时,实际上是在远程主机 tcp://***.***.**.**:2376 上运行 Docker,而单独运行 docker 时,则是在本地运行 Docker。
当你运行 docker images 命令时,你确实会看到存储在本地计算机上的镜像列表。但是,docker-compose up -d 命令将尝试在 ***.***.**.**:2376 上启动容器,而不是在本地机器上启动。如果不设置 DOCKER_HOST 环境变量,则 docker images 命令将不会显示远程 Docker 主机上可用的镜像。例如,可以像这样设置环境变量:
DOCKER_HOST=tcp://***.***.**.**:2376 docker images
显然,远程Docker主机没有存储web-server:staging镜像,也没有这个镜像在Docker hub上。这就是为什么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

请注意,对于大型图片,特别是在慢速连接下,此过程可能需要一些时间。


3
在我看来,这是唯一解决实际问题的答案。我不明白为什么它没有更多的票数...... - robert

2
我的问题是在没有使用sudo的情况下使用docker构建,然后在使用sudo运行docker compose。运行docker images和sudo docker images会给我两组不同的镜像,其中sudo docker compose up只允许我访问后者。

0

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