简介
本教程将指导你完成 Docker 容器镜像的克隆过程。Docker 镜像是一种打包模板,其中包含运行应用程序所需的一切,克隆允许你创建可以自定义的副本。在本指南结束时,你将了解如何克隆 Docker 镜像、修改它,并将其共享以进行部署。
本教程将指导你完成 Docker 容器镜像的克隆过程。Docker 镜像是一种打包模板,其中包含运行应用程序所需的一切,克隆允许你创建可以自定义的副本。在本指南结束时,你将了解如何克隆 Docker 镜像、修改它,并将其共享以进行部署。
在开始克隆 Docker 镜像之前,了解 Docker 是什么以及验证我们的环境是否正确设置非常重要。
Docker 是一个使用容器来开发、部署和运行应用程序的平台。容器将应用程序与其所有依赖项打包在一起,确保它在不同的环境中一致地工作。这使得 Docker 对于开发和部署工作流程特别有用。
首先,让我们确保 Docker 已正确安装在我们的系统上。打开一个终端窗口并运行:
docker --version
你应该看到类似如下的输出:
Docker version 20.10.21, build baeda1f
接下来,检查 Docker 服务是否正在运行:
sudo systemctl status docker
输出应该表明 Docker 处于活动状态(正在运行)。如果它没有运行,你可以使用以下命令启动它:
sudo systemctl start docker
让我们运行一个简单的测试命令来验证 Docker 是否正常工作:
docker run hello-world
此命令下载并运行 hello-world
镜像,该镜像打印确认消息并退出。你应该看到类似如下的输出:
Hello from Docker!
This message shows that your installation appears to be working correctly.
要查看你的系统上当前可用的 Docker 镜像,请运行:
docker images
此命令列出当前存储在本地的所有 Docker 镜像。输出显示镜像仓库、标签、镜像 ID、创建日期和大小。
现在我们已经确认 Docker 正常工作,我们已准备好在下一步开始使用 Docker 镜像。
在这一步中,我们将从 Docker Hub 拉取一个 Docker 镜像,并在我们的本地系统上运行它。这是克隆 Docker 镜像过程中的第一步。
Docker Hub 是一个基于云的注册表服务,用户可以在其中查找和共享容器镜像。它包含由软件供应商维护的许多官方镜像以及社区贡献的镜像。
让我们从 Docker Hub 拉取官方的 Nginx Web 服务器镜像。Nginx 是一个流行的 Web 服务器,我们将在本教程中使用它作为示例。
运行以下命令以下载 Nginx 镜像:
docker pull nginx:latest
此命令下载最新版本的 Nginx 镜像。你应该看到显示下载进度的输出:
latest: Pulling from library/nginx
a2abf6c4d29d: Pull complete
a9edb18cadd1: Pull complete
589b7251471a: Pull complete
186b1aaa4aa6: Pull complete
b4df32aa5a72: Pull complete
a0bcbecc962e: Pull complete
Digest: sha256:0d17b565c37bcbd895e9d92315a05c1c3c9a29f762b011a10c54a66cd53c9b31
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
要确认镜像已成功下载,请再次列出你的 Docker 镜像:
docker images
你现在应该在列表中看到 Nginx 镜像:
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 605c77e624dd 2 weeks ago 142MB
现在让我们运行一个基于我们刚刚拉取的 Nginx 镜像的容器:
docker run --name my-nginx -d -p 8080:80 nginx
此命令执行以下操作:
--name my-nginx
:将我们的容器命名为 "my-nginx"-d
:在分离模式(后台)运行容器-p 8080:80
:将我们主机上的端口 8080 映射到容器中的端口 80nginx
:使用我们之前拉取的 Nginx 镜像你应该看到一个长字符串输出,这是容器 ID。
要检查容器是否正在运行:
docker ps
你应该看到类似如下的输出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f8d3e9c5b9a7 nginx "/docker-entrypoint.…" 30 seconds ago Up 29 seconds 0.0.0.0:8080->80/tcp my-nginx
你现在可以通过打开 Web 浏览器并导航到 http://localhost:8080
或使用 curl 来访问 Nginx 默认页面:
curl http://localhost:8080
你应该看到 Nginx 欢迎页面的 HTML 内容。
现在我们已经成功拉取并运行了 Docker 镜像,我们已准备好在下一步中基于它创建我们自己的自定义镜像。
现在我们有了一个正在运行的 Nginx 容器,我们将通过修改它来创建一个自定义镜像。这是克隆过程的核心。我们将:
Docker 镜像可以通过两种方式创建:
在本教程中,我们将使用第二种方法,因为它更直接地理解克隆过程。
首先,让我们创建一个自定义 HTML 文件来替换默认的 Nginx 欢迎页面。我们需要进入正在运行的容器并修改其文件。
使用以下命令在正在运行的容器内执行一个 shell:
docker exec -it my-nginx bash
这将在容器内打开一个交互式 bash shell。现在,让我们创建一个自定义 HTML 文件:
echo "<html><body><h1>My Custom Docker Image</h1><p>This is a custom Nginx image created in the LabEx tutorial.</p></body></html>" > /usr/share/nginx/html/index.html
你可以通过检查文件的内容来验证更改:
cat /usr/share/nginx/html/index.html
现在退出容器 shell:
exit
让我们测试一下我们的更改是否已应用,方法是再次访问 Nginx 服务器:
curl http://localhost:8080
你现在应该看到我们的自定义 HTML 内容,而不是默认的 Nginx 欢迎页面。
现在我们已经修改了容器,我们将创建一个包含这些更改的新镜像。这是使用 docker commit
命令完成的:
docker commit my-nginx my-custom-nginx:v1
此命令基于 my-nginx
容器的当前状态,创建一个名为 my-custom-nginx
且标签为 v1
的新镜像。
让我们验证一下我们的新镜像是否已创建:
docker images
你应该在列表中看到你的新镜像:
REPOSITORY TAG IMAGE ID CREATED SIZE
my-custom-nginx v1 a1b2c3d4e5f6 10 seconds ago 142MB
nginx latest 605c77e624dd 2 weeks ago 142MB
现在,让我们停止并删除原始容器,然后基于我们的自定义镜像运行一个新容器:
docker stop my-nginx
docker rm my-nginx
docker run --name my-custom-container -d -p 8081:80 my-custom-nginx:v1
这些命令:
让我们验证一下我们的新容器是否正在正确运行:
docker ps
你应该在列表中看到你的新容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
g9h8i7j6k5l4 my-custom-nginx:v1 "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 0.0.0.0:8081->80/tcp my-custom-container
现在,访问新端口上的 Nginx 服务器:
curl http://localhost:8081
你应该看到相同的自定义 HTML 内容,确认我们的新镜像包含我们所做的更改。
恭喜你!你已经成功克隆并自定义了一个 Docker 镜像。在下一步中,我们将学习如何共享这个自定义镜像。
现在我们已经创建了一个自定义 Docker 镜像,我们将学习如何正确地标记它并准备共享。在实际场景中,你将把镜像推送到像 Docker Hub 这样的注册表,但在本教程中,我们将专注于准备步骤。
Docker 镜像通过它们的仓库名称和标签来标识。标签有助于镜像的版本控制和组织。默认标签是 latest
,但使用有意义的版本标签是一个好习惯。
让我们为我们的自定义镜像添加更多标签:
docker tag my-custom-nginx:v1 my-custom-nginx:latest
docker tag my-custom-nginx:v1 my-custom-nginx:stable
这些命令为我们的镜像创建了两个额外的标签:latest
和 stable
。实际的镜像数据在所有三个标签之间共享,因此此操作非常有效。
让我们再次检查我们的镜像:
docker images
你现在应该看到 my-custom-nginx
的多个条目:
REPOSITORY TAG IMAGE ID CREATED SIZE
my-custom-nginx v1 a1b2c3d4e5f6 10 minutes ago 142MB
my-custom-nginx latest a1b2c3d4e5f6 10 minutes ago 142MB
my-custom-nginx stable a1b2c3d4e5f6 10 minutes ago 142MB
nginx latest 605c77e624dd 2 weeks ago 142MB
请注意,所有 my-custom-nginx
镜像都具有相同的 Image ID,这表明它们是具有不同标签的同一镜像。
在实际场景中,你将把你的镜像推送到像 Docker Hub 这样的注册表。为此,你需要:
为了演示目的,让我们假设你的 Docker Hub 用户名是 yourusername
。以下是你准备推送镜像的方式:
docker tag my-custom-nginx:v1 yourusername/my-custom-nginx:v1
要推送镜像(在实际场景中),你将使用:
## 这仅用于演示 - 我们实际上不会推送
## docker push yourusername/my-custom-nginx:v1
除了推送到注册表之外,你还可以将 Docker 镜像保存到文件以进行手动传输:
docker save -o my-custom-nginx.tar my-custom-nginx:v1
此命令将镜像保存到名为 my-custom-nginx.tar
的 tarball 文件中。你可以验证文件是否已创建:
ls -lh my-custom-nginx.tar
你应该看到类似如下的输出:
-rw------- 1 labex labex 142M Nov 10 12:34 my-custom-nginx.tar
要从另一台机器上的 tarball 加载镜像(或在删除镜像后在同一台机器上),你将使用:
## 我们实际上不会将此命令作为教程的一部分运行
## docker load -i my-custom-nginx.tar
为了帮助其他人理解你的自定义镜像,最好记录你所做的更改。让我们创建一个简单的文档文件:
cat > my-custom-nginx-doc.txt << EOF
## My Custom Nginx Image
This is a custom Nginx image created by cloning the official Nginx image.
### Changes Made
- Replaced the default welcome page with a custom HTML page
### How to Run
docker run --name my-custom-container -d -p 8080:80 my-custom-nginx:v1
### Version History
- v1: Initial custom version with modified welcome page
EOF
你现在有了一个关于你的自定义镜像的文档文件。
恭喜你!你已经学会了如何标记你的 Docker 镜像并准备共享。在下一步中,我们将介绍一些最佳实践并清理我们的环境。
在最后一步中,我们将介绍一些使用 Docker 镜像的最佳实践,并清理我们的环境。
始终使用特定的版本标签,而不是依赖于 latest
标签。这确保了你部署的一致性。
## 更好的方法
docker pull nginx:1.23.2
## 较不可预测的方法
docker pull nginx:latest
较小的镜像下载速度更快,并且占用更少的存储空间。尽可能考虑使用基于 alpine 的镜像:
## 让我们看看大小差异
docker pull nginx:alpine
docker images | grep nginx
你可能会看到如下输出:
nginx alpine 2bc7edbc3cf2 2 weeks ago 40.7MB
nginx latest 605c77e624dd 2 weeks ago 142MB
alpine 版本明显更小!
使用 Dockerfile 创建镜像时,使用多阶段构建以保持最终镜像小巧。这是一个简单的例子(你不需要运行它):
## Build stage
FROM golang:1.17 AS builder
WORKDIR /app
COPY . .
RUN go build -o app
## Final stage
FROM alpine:3.15
COPY --from=builder /app/app /app
CMD ["/app"]
始终为你的自定义镜像维护文档,包括:
我们在上一步中创建了一个简单的文档文件。
定期扫描你的镜像以查找漏洞:
## 扫描示例(Docker Desktop 内置了此功能)
## docker scan my-custom-nginx:v1
让我们探索一个用于检查 Docker 镜像的有用命令:
docker inspect my-custom-nginx:v1
此命令显示有关镜像的详细信息,包括其层、配置和环境变量。
你可以查看镜像的构建历史:
docker history my-custom-nginx:v1
这显示了镜像的每一层以及创建它们的命令。
现在让我们通过删除我们创建的容器和镜像来清理我们的环境:
docker stop my-custom-container
docker rm my-custom-container
docker rmi my-custom-nginx:v1 my-custom-nginx:latest my-custom-nginx:stable
docker rmi nginx:latest nginx:alpine
docker ps -a
docker images
Docker 提供了一个方便的命令来清理未使用的资源:
docker system prune
这将删除所有已停止的容器、未使用的网络、悬空的镜像和构建缓存。在继续之前,系统会要求你确认。
为了更积极的清理,你可以使用:
docker system prune -a
这还会删除所有未使用的镜像,而不仅仅是悬空的镜像。
你现在已经学会了如何:
这些技能构成了使用 Docker 镜像的基础,并且在你继续你的容器化之旅时将非常有用。
在这个实践教程中,你已经学习了克隆 Docker 容器镜像的完整过程。你首先了解了 Docker 的基础知识并验证了你的环境。然后,你拉取了一个官方的 Nginx 镜像并将其作为容器运行。接下来,你通过修改其内容来自定义此容器,并将这些更改提交以创建你自己的自定义镜像。
你还学习了如何正确地标记你的镜像以进行版本控制和分发,如何将镜像保存到文件以进行手动传输,以及如何记录你的更改。最后,你探索了使用 Docker 镜像的最佳实践并清理了你的环境。
这些技能为在开发和生产环境中与 Docker 合作奠定了坚实的基础。你现在可以自信地创建和自定义 Docker 镜像以满足你的特定需求,从而使你的应用程序在不同环境中更具可移植性和一致性。