使用 Docker Compose

zr - 2024-02-04 22:52:41 - 所属文档:Docker 快速入门文档

[Docker Compose](https://docs.docker.com/compose/) 是一款旨在帮助定义和共享多容器应用程序的工具。通过 Compose,我们可以创建一个 YAML 文件来定义需要使用的所有服务,并且只需要一个命令就可以启动或停止所有服务。 使用 Compose 的最大优点是你只需在一个文件中定义自己的应用程序栈(即应用程序需要用到的所有服务),然后把这个 YAML 文件放在项目的根目录下,与源码一起受版本控制。其他人只需 clone 你的项目源码之后就可以快速启动服务。实际上,在 GitHub 或 GitLab 上已经有很多项目正在这样做。 我们也来为 todo 应用创建一个 YAML 文件吧。 ## 安装 Docker Compose 如果你使用的是 Windows 或者 Mac 桌面操作系统,在安装 Docker Desktop 之后就已经内置了 Docker Compose。如果你使用的是 Linux 系统,可以参照 [此处的说明](https://docs.docker.com/compose/install/) 安装 Docker Compose 安装完成之后,可以执行以下命令查看它的版本信息: ``` docker-compose version ``` ## 创建我们的 Compose 文件 1. 在 `todo-app` 项目的根目录下,创建一个名为 `docker-compose.yml` 的文件 2. 在 `docker-compose.yml` 文件的第一行定义 schema version。在大多数情况下,最好使用最新的受支持 schema version。你可以查看 [Compose file reference](https://docs.docker.com/compose/compose-file/) 以获得最新的 schema version 和兼容性列表。 ``` version: "3.7" ``` 3. 接下来,我们将定义 `todo-app` 应用程序依赖的一系列服务(或容器)列表。 ``` version: "3.7" services: ``` 接着,我们开始将之前通过命令行执行的命令,翻译成 compose 文件支持的格式。 ## 定义 `todo-app` 应用服务 回顾一下之前使用过的命令: ``` docker run -dp 3000:3000 \ -w /app \ -v "$(pwd):/app" \ --network todo-app \ -e MYSQL_HOST=mysql \ -e MYSQL_USER=root \ -e MYSQL_PASSWORD=secret \ -e MYSQL_DB=todos \ node:12-alpine \ sh -c "yarn install && yarn run dev" ``` 如果使用的是 PowerShell,之前使用的是下面这条命令(只是 `多行输入` 的分隔符不一样而已) ``` docker run -dp 3000:3000 ` -w /app ` -v "$(pwd):/app" ` --network todo-app ` -e MYSQL_HOST=mysql ` -e MYSQL_USER=root ` -e MYSQL_PASSWORD=secret ` -e MYSQL_DB=todos ` node:12-alpine ` sh -c "yarn install && yarn run dev" ``` 1. 首先,定义 `todo-app` 应用服务名称和使用的镜像,可以为它取任何名称,这里简单取成同名 `todo-app`。该名称将自动作为网络的别名,在后续定义 MySQL 服务时将很有用。 ``` version: "3.7" services: todo-app: image: node:12-alpine ``` 2. 接着我们把容器启动之后要执行的命令写在靠近定义 `image` 的地方,尽管不一定按照这样的顺序书写,但是通常都这样做。类似下面这样: ``` version: "3.7" services: todo-app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ``` 3. 接着定义端口映射 ``` version: "3.7" services: todo-app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 ``` 4. 再来将 `-w /app` **工作目录** 和 `-v "$(pwd):/app"` **volume** 通过 `working_dir` 和 `volumes` 这两个属性来定义。 在 Docker Compose 配置文件中定义 volume 的一个优点是我们可以使用基于 `docker-compose.yml` 文件所在目录的相对路径。 ``` version: "3.7" services: todo-app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app ``` 5. 最后,通过 `environment` 定义 `todo-app` 需要使用到的环境变量。 ``` version: "3.7" services: todo-app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: MySQL MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos ``` ### 定义 MySQL 服务 现在,是时候定义 MySQL 服务了。同样先回顾之前启动 MySQL 容器时使用的命令: ``` docker run -d \ --network todo-app --network-alias MySQL \ -v todo-mysql-data:/var/lib/mysql \ -e MYSQL_ROOT_PASSWORD=secret \ -e MYSQL_DATABASE=todos \ mysql:5.7 ``` 如果使用的是 PowerShell,之前使用的是下面这条命令(只是 `多行输入` 的分隔符不一样而已) ``` docker run -d ` --network todo-app --network-alias MySQL ` -v todo-mysql-data:/var/lib/mysql ` -e MYSQL_ROOT_PASSWORD=secret ` -e MYSQL_DATABASE=todos ` mysql:5.7 ``` 1. 先定义一个新服务并将它命名为 `mysql`,接着指定该服务使用的镜像。 ``` version: "3.7" services: todo-app: # The app service definition mysql: image: mysql:5.7 ``` 2. 接着定义 `named volume` 的映射关系。当我们使用 `docker run` 运行容器时,Docker 会自动创 `named volume`。但是,使用 Compose 运行时不会自动创建,所以我们需要在配置文件的顶层使用 `volumes` 属性定义 `named volume`,然后在 MySQL 服务下的 `volumes` 指定它的实际挂载点。 > 备注:这两个 `volumes` 出现的位置不一样。第一个是在 compose 文件的顶层,另外一个是在 MySQL 这个服务之下。 ``` version: "3.7" services: todo-app: # The app service definition mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql volumes: todo-mysql-data: ``` 3. 最后,指定启动 MySQL 服务需要的环境变量 ``` version: "3.7" services: todo-app: # The app service definition mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data: ``` 此时,完整的 `docker-compose.yml` 看起来像这样: ``` version: "3.7" services: todo-app: image: node:12-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app environment: MYSQL_HOST: MySQL MYSQL_USER: root MYSQL_PASSWORD: secret MYSQL_DB: todos mysql: image: mysql:5.7 volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: secret MYSQL_DATABASE: todos volumes: todo-mysql-data: ``` ## 启动我们的完整应用 现在我们已经有了 `docker-compose.yml` 文件,就可以启动它了! 1. 确保之前通过命令行启动的应用和 MySQL 容器已经停止并删除了。如何还运行着,可以通过 Docker Desktop 或者使用 docker ps 配合 docker rm -f <container-ids> 删除它们。 2. 使用 `docker-compose up` 命令启动应用程序栈(`todo-app` + `mysql`)。添加 `-d` 标志可以让它们保持在后台运行。 ``` docker-compose up -d ``` 运行此命令之后,应看到如下输出: ``` Creating network "app_default" with the default driver Creating volume "app_todo-mysql-data" with default driver Creating app_todo-app_1 ... done Creating app_mysql_1 ... done ``` 你应该已经注意到了,`volume` 和 `network` 都已经已创建成功。默认情况下,Docker Compose 会自动为应用程序栈自动创建一个网络,这就是为什么我们没有在 compose 文件中显式定义网络的原因。 3. 让我们使用 `docker-compose logs -f` 命令查看日志。每个服务的日志汇总统一输出在这里。`-f` 标志用于实时输出日志。 如果要查看特定服务的日志,可以将服务名称添加到 logs 命令的末尾(例如 `docker-compose logs -f mysql`)。 4. 至此,只用了一个命令就可以启动我们应用程序需要的所有服务了。 ## 在 Docker Dashboard 中查看我们的应用程序栈 如果现在查看 Docker Dashboard,将会看到有一个名为 `app` 的组,将所有使用到的容器组在一起了。默认情况下,项目名称是 `docker-compose.yml` 文件所在目录的名称。 ![Docker Dashboard with app project](https://bianxuebianzuo.oss-cn-shenzhen.aliyuncs.com/uploads/photos/1/2021/08/07/6rTMo1628305678_Docker_Dashboard_with_app_project1617270116.png) 如果点击 `app` 这个分组,将会看到我们在 `docker-compose.yml` 文件中定义的两个容器。名称也更具描述性,因为它们遵循 `< 项目名称 >_< 服务名称 >_< 副本编号 >` 的格式。因此,可以很方便的查看哪个容器是我们的 `todo` 服务以及哪个容器是 MySQL 数据库服务。 ![Docker Dashboard with app project expanded](https://bianxuebianzuo.oss-cn-shenzhen.aliyuncs.com/uploads/photos/1/2021/08/07/Zdsmk1628305678_Docker_Dashboard_with_app_project_expanded1617270117.png) ## 删除所有容器 如果要将它们全部删除,只需运行 `docker-compose down` 或在 Docker Dashboard 上点击垃圾桶图标即可。同时也会删除自动创建的网络。 删除 Volumes 默认情况下,运行 `docker-compose down` 命令,不会自动删除 `docker-compose.yml` 文件中定义的 `named volumes`。如果要删除 volumes,只需添加 `--volumes` 标志即可。 ## 回顾 在本节中,我们学习了如何利用 Docker Compose 帮助我们极大简化多服务应用程序的定义和分享。我们把之前使用的命令转换为对应的 compose 格式,写入新创建的 `docker-compose.yml` 文件中。然后,就可以只使用一条命令启动或者删除所有服务了。 下一节让我们更进一步,介绍一些构建镜像的最佳实践。 > 原始资料:[Using Docker Compose](https://docs.docker.com/get-started/08_using_compose/)