如何在Dockerfile中使用本地镜像作为基础镜像?

251

我正在处理一个dockerfile。

我刚意识到,我一直在使用带有索引的镜像 FROM

所以我想知道:

  • 我如何使用一个本地(定制的)镜像作为我的基础镜像 (FROM),而不必将其 推送 到索引中?
14个回答

243

您可以直接使用而无需进行任何特殊处理。如果您有一个名为 blah 的本地镜像,则可以执行 FROM blah 。如果您在Dockerfile中执行 FROM blah ,但是没有名为 blah 的本地镜像,则Docker将尝试从注册表中拉取它。

换句话说,如果一个Dockerfile执行了 FROM ubuntu ,但是您有一个不同于官方版本的名为 ubuntu 的本地镜像,则您的镜像将覆盖它。


14
对我来说无法工作 - 可能是与boot2docker有关的问题吗?我有最新版本1.3.1... Docker似乎不会先从本地检查(或者可能没有报告它),而是直接尝试从注册表中提取。http://stackoverflow.com/q/27046118/202168 - Anentropic
17
不,这是不正确的。尽管我在“docker image list”中列出了一个同名的本地镜像,但Docker仍然试图从远程注册表拉取镜像。 - John Smith Optional
4
请记得引用完整的图片名称,格式为"<image_name>:<tag>"。您可以在命令 docker image ls 的输出中,在“REPOSITORY”列下找到图像名称,在“TAG”列下找到标签。请注意,不要更改原意,让翻译更通俗易懂。 - codeman48
30
这些都不起作用,Docker 仍然会在镜像名称前添加 docker.io/blabla。 - Ivan Kara
11
在我的测试中,这适用于 Intel Mac 操作系统,而不适用于 M1 Mac 操作系统。 - alberto56
显示剩余8条评论

154

如果未来有人面临此问题,即使您已经在本地拥有图像,但docker build仍尝试从docker hub拉取图像,则问题可能是因为架构类型不同。

Trying to pull from docker.io even though image exists

您可以使用以下命令检查图像的架构:

docker inspect --format='{{.Os}}/{{.Architecture}}' IMAGE_NAME

现在在您的Dockerfile中将FROM IMAGE_NAME更改为类似于FROM --platform=linux/amd64 IMAGE_NAME,Docker现在将使用本地镜像。


48
这对于如今的 Mac M1 来说非常重要。1+ - Eugene
4
对于MacBook M1来说,确实是这种情况。 - Guo
1
这不是我寻找的,但是知道这个真是很方便!+1 - stevec
太棒了,做得好! - Wayne E. Seguin
我花了1.5到2个小时才找到这个解决方案,需要通过“重新启动”来实现。 - ssi-anik
对我来说,即使提供了平台,也没有起作用。必须使用以下参数运行命令: DOCKER_BUILDKIT=0 docker build -t <新镜像名称> .参考链接:https://stackoverflow.com/a/74023547/3962816Docker版本:20.10.7,Mac M1芯片。 - undefined

53

已验证:它可以在Docker 1.7.0中正常工作。

运行docker build命令时,请不要指定--pull=true

参考此Dockerfile中使用FROM引用本地构建的镜像主题:

如果您想使用本地镜像作为基础镜像,请不要使用--pull=true选项。
--pull=true将始终尝试拉取更新版本的镜像。


12
如果你的镜像名称中含有"-"字符(例如,my-image),则你的docker将无法在本地解析此镜像。我不知道为什么会这样,但是要解决这个问题,简单地不使用"-"字符即可。此方法已在docker-compose 1.8和docker 1.11上进行了测试。 - deFreitas
3
我在 Docker 版本 17.06.2-ce, build cec0b72 上使用有连字符的名称没有问题,但是请确保如果你标记了你的镜像,你需要将标记作为镜像规范的一部分包含进去(FROM localimage:tag)。 - Scott
1
@deFreitas 看起来是真的,我有一个带有连字符名称的图像,Docker 正试图从远程注册表中拉取它,尽管本地存在一个具有该名称的图像。如果这个关于名称中连字符的规则被证明是真的,那将是纯粹的疯狂。 - John Smith Optional
3
@deFreitas:根据我上次的评论,我尝试使用下划线而不是连字符,但仍然遇到了相同的问题,即使本地已经存在镜像,Docker 仍然试图从远程拉取镜像。至少在我的情况下,连字符不是问题所在。 - John Smith Optional
来晚了,但如果仍然遇到此问题,请确保您正在构建的图像与您正在构建的架构匹配。我曾试图使用arm64本地图像为amd64目标构建。请确保本地图像架构与构建架构匹配。 - r_robotics

16

我在M1芯片的Mac上必须禁用BUILDKIT才能使用本地镜像。

您可以通过将DOCKER_BUILDKIT环境变量设置为0来完成它。

DOCKER_BUILDKIT=0 docker build -t YOUR_TAG --pull=false .


有任何想法为什么会发生这种情况吗?我今天更新了最新版本的 Docker,第一次遇到了这个问题。我不得不禁用 BUILDKIT 才能使其正常工作。 - ray sn0w
@raysn0w 我的猜测是新的BUILDKIT默认使用为本地平台构建的镜像,例如M1的arm64。这就是它比旧版快得多的原因。如果您的本地镜像不是为arm64构建的,则无法使用它。 - Armut
如果您正在尝试使用buildx构建多架构镜像呢? - agirault

9

您的图片中可以包含“-”字符。假设您有一个本地镜像(而不是本地注册表),名称为centos-base-image,标签为7.3.1611。

docker version 
      Client:
       Version:         1.12.6
       API version:     1.24
       Package version: docker-common-1.12.6-16.el7.centos.x86_64
       Go version:      go1.7.4

      Server:
       Version:         1.12.6
       API version:     1.24
       Package version: docker-common-1.12.6-16.el7.centos.x86_64
       Go version:      go1.7.4

docker images
 REPOSITORY            TAG
 centos-base-image     7.3.1611

Dockerfile

FROM centos-base-image:7.3.1611
RUN yum -y install epel-release libaio bc flex

结果

Sending build context to Docker daemon 315.9 MB
Step 1 : FROM centos-base-image:7.3.1611
  ---> c4d84e86782e
Step 2 : RUN yum -y install epel-release libaio bc flex
  ---> Running in 36d8abd0dad9
...

在上面的示例中,FROM正在获取您的本地镜像,您可以提供其他指令以从您的自定义注册表中获取图像(例如FROM localhost:5000/my-image:with.tag)。请参阅https://docs.docker.com/engine/reference/commandline/pull/#pull-from-a-different-registryhttps://docs.docker.com/registry/#tldr 最后,如果在提供名称时无法解析您的镜像,请尝试在创建镜像时添加标签 此 GitHub 线程描述了类似未按名称找到本地镜像的问题

通过省略特定的标签,docker将查找已标记为“latest”的镜像,因此要么创建带有 :latest 标签的镜像,要么更改您的 FROM


6

请记得不仅要放置标签,还要放置该标签所在的存储库,如下:

docker images
REPOSITORY                                TAG                       IMAGE ID            CREATED             SIZE
elixir                                    1.7-centos7_3             e15e6bf57262        20 hours ago        925MB

您应该这样引用它:
elixir:1.7-centos7_3

6

对于使用 MAC os m1 架构的任何人,我需要在基础镜像之前添加 --platform=linux/amd64 参数。例如:

FROM --platform=linux/amd64 baseImage:tag

1
非常感谢!你帮了我很大的忙! - Gleb Egunov

4
在 M1 Mac 上,我不仅需要指定镜像平台还要指定名称和标签。
FROM --platform=linux/amd64 myimagename:2.0.0.a

i.e.

  1. 如果使用平台进行 docker 构建
    docker build . --tag chrome-nodejs-java --platform=linux/amd64,那么在 FROM 之后应该指定平台。
  2. 如果你在 docker images 中有一个特定名称和标签的镜像(不是标记为 latest),那么必须指定该标签。

更简单的方法可能就是只使用 IMAGE ID。

FROM c08a03a92df0

无论如何,经常使用docker images
它不列出镜像的平台信息。 为此,请使用docker inspect imagenameOrIDdocker inspect --format='{{.Os}}/{{.Architecture}}' imagenameOrID
所以在我的情况下,它对于myimagename(因为没有latest,即没有标签构建)不起作用,但对于myimagename:2.0.0.a起作用。
换句话说,如果docker images中没有带有latest标签的镜像,则不能在不指定版本标签的情况下使用FROM

感谢@jpetazzo、@Anuj Bansal和@SomeGuy的高票回答。


3

对于 Docker >= 23.0

自 Docker 23.0 版本开始,docker build 已成为 docker buildx build 的别名。

如果您正在使用自定义的构建器实例,请使用以下命令将构建器实例设置为 default,然后再次运行构建命令。

docker buildx use default

更多细节

您可以使用以下命令列出您的构建器实例:

docker buildx ls

你应该在默认构建器旁边看到一个通配符。
NAME/NODE    DRIVER/ENDPOINT             STATUS  BUILDKIT             PLATFORMS
mybuilder    docker-container
  mybuilder0 unix:///var/run/docker.sock running v0.12.1              linux/arm64*, linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386
default *    docker
  default    default                     running v0.11.6+0a15675913b7 linux/amd64, linux/amd64/v2, linux/amd64/v3, linux/386

2

这是一个愚蠢的解决方法,但是...如果您的图像名称为blah并且具有b2d34289abae的ID,则可以更改Docker文件中的FROM行:

FROM blah

变成

FROM b2d34289abae

您可以通过执行docker images来获取图像ID。

然而,我建议您将其视为临时解决方法,仅用于本地测试或类似情况。


1
这实际上很聪明,因为这样我们可以选择非常特定的图像构建,即使它没有名称或标签。 - Paul Verest

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