Dockerfile
就像一个编译文件。它以层的形式构建,从包含基本设置的基础层开始。这通常是我们使用 FROM
指令的层。每个后续层都添加到前一个层之上,进行小的调整或添加。这些层堆叠在另一个层之上,每个层都会构建前一层所做的更改。
创建 Docker
映像后,其所有层都变为只读。但是,当你从此映像启动 Docker
容器时,Docker
会在它们之上添加一个新层。这个新层是容器操作期间所做的任何更改或更新的存储位置。它就像一个薄的可写层,可以捕获对容器文件系统所做的所有修改。
本质上,Docker
镜像提供了创建一致环境的蓝图,而容器允许你在该环境中工作并根据需要进行更改,而不会影响原始镜像。
此镜像构建过程由 Docker CLI
初始化并由 Docker
守护程序执行。 要生成 Docker
镜像,Docker
守护程序需要访问 Dockerfile
、任何源代码以及该 Dockerfile
中引用的文件。 这些文件存储在称为构建上下文的目录中。 执行 docker image build
命令时需要指定此上下文目录。
docker image build
命令采用以下格式:
1 | docker image build <context> |
如果我们想指定当前目录作为上下文,我们可以使用点(.
)作为目录:
1 | docker image build . |
我们来创建一个简单的 Dockerfile
来演示 Docker
镜像的构建过程:
1 | FROM ubuntu:latest |
此 Dockerfile
执行以下操作。它以 FROM
命令开头,指定应在 Docker Hub
存储库中提供的最新版本的 Ubuntu
之上构建映像。此基础映像是我们自定义映像的起点。
LABEL
命令用于提供有关映像的元数据。在本例中,它分配维护者标签,指示谁维护或负责此特定映像。提供的电子邮件地址 (webape@example.com) 用作联系信息。
最后,CMD
命令设置从此映像启动容器时要执行的默认命令。在这里,它指定当容器启动时,它应该执行命令 echo “Hello World”。此命令只是将“Hello World”打印到容器的标准输出。
导航到你创建 Dockerfile
的目录,并使用以下命令:
1 | docker image build . |
你将看到类似以下内容的输出:
1 | [+] Building 3.5s (6/6) FINISHED docker:default |
现在,让我们使用 docker image list
命令访问本地可用的 Docker
镜像:
1 | docker image list |
该命令应返回以下输出:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
请注意,我们的自定义 Docker
映像没有名称。这是因为我们在构建过程中没有指定任何存储库或标记。我们可以使用 docker image tag
命令标记现有映像。
让我们将 IMAGE ID 为 f14484d3185f 的映像标记为 my-tagged-image:v1.0:
1 | docker image tag f14484d3185f my-tagged-image:v1.0 |
现在,如果我们再次列出我们的镜像,我们可以在 REPOSITORY
和 TAG
列下看到 Docker
镜像名称和标签:
1 | REPOSITORY TAG IMAGE ID CREATED SIZE |
我们还可以通过指定 -t
标志在构建过程中标记图像:
1 | docker image build -t my-tagged-image:v2.0 . |
上述命令将打印以下输出:
1 | [+] Building 5.8s (6/6) FINISHED docker:default |
这次,除了写入 image sha256:f14484d3185f92d2d7896904300502be4f3c6d0df4ebba61b127d630d74b6f0d 行之外,我们还可以看到 naming to docker.io/library/my-tagged-image:v2.0 行,这表示我们的 Docker
镜像上有标记。
总结
在这篇文章中,我们讨论了如何从 Dockerfile
构建 Docker
镜像。我们还讨论了 Dockerfile
和 Docker
镜像之间的区别。然后,我们讨论了 Docker
镜像是如何由多个层组成的。最后,我们标记了 Docker
镜像。