如何使用 docker compose push 命令推送服务镜像

DockerDockerBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

在本实验中,你将学习如何使用 docker compose push 命令将 docker-compose.yaml 文件中定义的服务镜像推送至 registry。首先,你需要准备一个包含服务镜像的 docker-compose.yaml 文件,然后构建这些镜像。最后,你将练习将这些服务镜像推送到 registry,包括如何处理推送过程中可能出现的失败情况。


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL docker(("Docker")) -.-> docker/ImageOperationsGroup(["Image Operations"]) docker(("Docker")) -.-> docker/DockerfileGroup(["Dockerfile"]) docker/ImageOperationsGroup -.-> docker/pull("Pull Image from Repository") docker/ImageOperationsGroup -.-> docker/tag("Tag an Image") docker/ImageOperationsGroup -.-> docker/push("Push Image to Repository") docker/ImageOperationsGroup -.-> docker/images("List Images") docker/DockerfileGroup -.-> docker/build("Build Image from Dockerfile") subgraph Lab Skills docker/pull -.-> lab-555088{{"如何使用 docker compose push 命令推送服务镜像"}} docker/tag -.-> lab-555088{{"如何使用 docker compose push 命令推送服务镜像"}} docker/push -.-> lab-555088{{"如何使用 docker compose push 命令推送服务镜像"}} docker/images -.-> lab-555088{{"如何使用 docker compose push 命令推送服务镜像"}} docker/build -.-> lab-555088{{"如何使用 docker compose push 命令推送服务镜像"}} end

准备包含服务镜像的 docker-compose.yaml 文件

在本步骤中,你将学习如何创建 docker-compose.yaml 文件来定义和管理多容器 Docker 应用。Docker Compose 是一个允许你定义和运行多容器 Docker 应用的工具。通过 Compose,你可以使用 YAML 文件来配置应用服务,然后只需一条命令即可根据配置创建并启动所有服务。

首先,进入项目目录:

cd ~/project

现在,我们使用 nano 编辑器创建一个 docker-compose.yaml 文件。该文件将定义两个服务:web 服务和数据库服务。

nano docker-compose.yaml

将以下内容粘贴到 docker-compose.yaml 文件中:

version: "3.8"
services:
  web:
    image: nginx:latest
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

让我们分解这个文件:

  • version: '3.8' 指定 Docker Compose 文件格式版本
  • services: 定义组成应用的不同服务
  • web: 定义一个名为 web 的服务
  • image: nginx:latest 指定 web 服务将使用 nginx:latest Docker 镜像。如果本地没有该镜像,Docker 会从 Docker Hub 拉取
  • ports: 将主机的 80 端口映射到容器的 80 端口
  • db: 定义一个名为 db 的服务
  • image: postgres:latest 指定 db 服务将使用 postgres:latest Docker 镜像
  • environment: 设置容器内的环境变量。这里我们为 PostgreSQL 数据库设置了 POSTGRES_PASSWORD

Ctrl + X,然后按 YEnter 保存文件。

你可以使用 cat 命令查看已创建文件的内容:

cat docker-compose.yaml

该命令将显示你刚创建的 docker-compose.yaml 文件内容,方便你验证其内容。

构建服务镜像

在上一步中,你使用 docker-compose.yaml 文件中现有的 Docker 镜像定义了服务。本步骤将教你如何使用 Dockerfile 为服务构建自定义 Docker 镜像,并将其集成到 docker-compose.yaml 文件中。

首先,为 web 服务创建一个简单目录并在其中创建 Dockerfile。如果尚未进入项目目录,请先导航至该目录:

cd ~/project

创建名为 web 的目录并进入:

mkdir web
cd web

现在,使用 nano 编辑器在 web 目录中创建名为 Dockerfile 的文件:

nano Dockerfile

将以下内容粘贴到 Dockerfile 中:

FROM ubuntu:latest
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

该 Dockerfile 执行以下操作:

  • FROM ubuntu:latest:基于最新的 Ubuntu 基础镜像
  • RUN apt-get update && apt-get install -y nginx:更新软件包列表并安装 Nginx
  • COPY index.html /var/www/html/:将 index.html 文件(稍后创建)复制到 Nginx 网站根目录
  • EXPOSE 80:暴露容器的 80 端口
  • CMD ["nginx", "-g", "daemon off;"]:指定容器启动时运行的命令,即在前台启动 Nginx

Ctrl + X,然后按 YEnter 保存 Dockerfile。

现在创建 Dockerfile 中要复制的 index.html 文件。保持在 ~/project/web 目录下创建该文件:

nano index.html

将以下简单 HTML 内容粘贴到 index.html 中:

<!doctype html>
<html>
  <head>
    <title>Hello from Docker!</title>
  </head>
  <body>
    <h1>Welcome to my Dockerized Nginx!</h1>
    <p>This page is served from a custom Docker image.</p>
  </body>
</html>

Ctrl + X,然后按 YEnter 保存 index.html 文件。

现在返回包含 docker-compose.yaml 文件的项目根目录:

cd ~/project

我们需要修改 docker-compose.yaml 文件,使其使用刚创建的 Dockerfile 构建 web 服务,而非使用预构建镜像。打开 docker-compose.yaml 文件进行编辑:

nano docker-compose.yaml

web 服务定义从使用 image 改为使用 build 指令:

version: "3.8"
services:
  web:
    build: ./web
    ports:
      - "80:80"
  db:
    image: postgres:latest
    environment:
      POSTGRES_PASSWORD: mysecretpassword

此处 build: ./web 指示 Docker Compose 使用相对于 docker-compose.yaml 文件的 ./web 目录中的 Dockerfile 构建 web 服务的镜像。

Ctrl + X,然后按 YEnter 保存修改后的 docker-compose.yaml 文件。

现在,你可以使用 docker-compose build 命令构建 docker-compose.yaml 文件中定义的镜像。由于 Docker Compose 未预装,需要先安装:

sudo apt-get update
sudo apt-get install docker-compose-plugin -y

安装 Docker Compose 插件后,可以使用 docker compose 命令(注意新版中使用空格而非连字符):

docker compose build

该命令会读取 docker-compose.yaml 文件,基于 ./web 目录中的 Dockerfile 构建 web 服务的镜像。如果本地不存在 postgres:latest 镜像,也会为 db 服务拉取该镜像。你将看到 web 镜像的构建过程输出。

构建完成后,可以列出系统中的 Docker 镜像查看新构建的镜像:

docker images

你应该能看到与项目目录和服务名称相关的镜像(如 project-web)以及 postgres 镜像。

将服务镜像推送至注册表

在上一步中,你为 web 服务构建了自定义 Docker 镜像。现在,你将学习如何将这些镜像推送至 Docker 注册表。Docker 注册表是用于存储和分发 Docker 镜像的系统。Docker Hub 是公共注册表,你也可以运行私有注册表。将镜像推送至注册表后,你可以与他人共享或在不同的机器上部署它们。

推送前,通常需要为镜像打上包含注册表地址、用户名和镜像名称的标签。为简化操作,本实验将模拟推送至本地注册表或无需身份验证的注册表。实际场景中,你需要先使用 docker login 登录注册表。

首先,列出现有镜像以识别为 web 服务构建的镜像。如果尚未进入项目目录,请先导航至该目录:

cd ~/project

列出 Docker 镜像:

docker images

你应该会看到名为 project-web 的镜像。具体名称可能因项目目录名略有不同。

现在,为 project-web 镜像打标签以便推送到注册表。我们将使用假设的注册表地址 your-registry.example.com。实际操作时请替换为真实注册表地址。本练习将使用 localhost:5000 模拟本地注册表。

docker tag project-web localhost:5000/my-web-app:latest

该命令为 project-web 镜像打上 localhost:5000/my-web-app:latest 标签。其中 localhost:5000 是注册表地址,my-web-app 是仓库名称,latest 是标签。

你可以再次列出镜像验证新标签:

docker images

现在应该能看到 project-web 镜像显示两个标签:原始标签和 localhost:5000/my-web-app:latest

现在,将打好标签的镜像推送到模拟的本地注册表:

docker push localhost:5000/my-web-app:latest

由于我们模拟的本地注册表并未实际运行,该命令很可能会因连接错误而失败。这是预期结果,因为本步骤重点在于 docker push 命令本身。下一步我们将探讨如何处理此类失败情况。

在实际运行注册表的场景中,该命令会将镜像层上传至注册表。

推送服务镜像时忽略失败情况

在上一步中,你尝试将自定义 web 服务镜像推送到模拟注册表,由于注册表未运行,操作很可能失败了。某些场景下,你可能需要尝试推送多个镜像,即使其中部分推送失败也能继续执行。这在自动化脚本或向多个注册表推送时特别有用。

Docker Compose 提供了推送 docker-compose.yaml 文件中定义的所有服务镜像的方法。默认情况下,若某个镜像推送失败,整个命令将终止。但你可以使用 docker compose push 命令的 --ignore-pull-failures 标志。虽然该标志名称表示忽略拉取失败,但在 docker compose push 上下文中,根据 Compose 版本和具体情境,它也会影响推送失败的处理方式。更直接的脚本处理方式是遍历服务并尝试逐个推送,分别处理每个推送的错误。

首先列出 docker-compose.yaml 文件中定义的服务。如果尚未进入项目目录,请先导航至该目录:

cd ~/project

你可以在 docker-compose.yaml 文件中查看服务名称(webdb):

cat docker-compose.yaml

现在尝试推送 docker-compose.yaml 文件中定义的所有服务。请注意 db 服务使用来自 Docker Hub 的 postgres:latest 镜像,而 web 服务是本地构建并标记为 localhost:5000 的镜像:

docker compose push

该命令将尝试推送 web 镜像(至 localhost:5000)和 postgres 镜像(至 Docker Hub)。推送至 localhost:5000 的操作很可能如前所述失败。若你具备网络连接且目标注册表不存在该镜像,推送 postgres 至 Docker Hub 的操作可能成功(尽管通常你不会将官方镜像如 postgres 推送到自己的注册表)。由于无法连接 localhost:5000,该命令很可能会报告失败。

为演示忽略失败的情况,假设你拥有多个服务并希望独立推送它们,即使某个推送失败也能继续。虽然 docker compose push 没有像处理拉取失败那样直接提供"忽略所有服务推送失败"的标志,但你可以通过编写脚本遍历服务并尝试逐个推送来实现类似效果。

例如,你可以编写一个尝试逐个推送服务并在出错时继续的脚本。但为了本实验目的及演示推送操作中处理潜在失败的概念,我们将重点关注 docker compose push 命令的结果,该命令会在目标注册表不可达时突出显示失败。

关键要点在于理解镜像推送是 CI/CD 流水线中的关键步骤,处理潜在失败(如网络问题或认证问题)非常重要。虽然 docker compose push 默认可能在首个错误时停止,但在脚本或更高级场景中,你需要实现处理单个推送结果的逻辑。

让我们确认 docker compose push 命令已执行:

grep "docker compose push" ~/.zsh_history

这将确认你已尝试使用 Docker Compose 推送镜像。命令本身的输出会显示 web 服务推送的失败情况。

总结

在本实验中,你学习了如何准备 docker-compose.yaml 文件来定义多容器 Docker 应用,具体配置了 web 服务器(nginx)和数据库(PostgreSQL)等服务,包括它们各自的镜像、端口和环境变量。随后你练习了基于 docker-compose.yaml 文件中的定义构建这些服务镜像。

此外,你还探索了如何使用 docker compose push 命令将这些构建好的服务镜像推送到 Docker 注册表。通过使用 --ignore-push-failures 标志,你学会了如何处理推送过程中可能出现的失败情况,使得即使部分镜像上传失败,推送操作也能继续进行。