本文介绍如何使用 MySQL 和 Docker Compose创建多容器应用。 使用具有多个容器的应用可以将容器专用于专用任务,因此每个容器都可以专注于单个任务。 使用多容器应用有许多优点:
- 使用单独的容器可以不同于数据库来管理 API 和前端资源。
- 使用多个容器可以在隔离环境中管理和更新不同版本。
- 本地数据库可以在用于生产中的数据库的容器和托管服务中维护。
- 与使用进程管理器运行多个进程相比,多容器应用更高效,这增加了容器启动/关闭的复杂性。
在本教程中,你将:
- 启动 MySQL
- 使用 MySQL 运行多容器应用
- 为应用创建 Docker Compose 文件
- 使用 Docker Compose 运行应用程序堆栈
先决条件
本文是教程系列的一部分。 这些过程建立在一个已建立的示例之上,该示例需要适用于 Linux 的 Docker Desktop 容器。
建议的方法是完成第一个教程: 创建容器应用,包括满足先决条件,以及教程: 在应用中保存数据。 完成这些教程后,请继续阅读本文中所述的过程。
本文中的示例使用 Docker Compose。
适用于 Windows 的 Docker Desktop 包括 Docker Compose。
运行以下命令来验证 Docker 安装:
docker-compose version
Visual Studio Code
本教程系列介绍了 Visual Studio Code(VS Code)的过程。 查看以下注意事项,了解如何在此环境中工作:
使用左侧菜单在 容器资源管理器 或 EXPLORER (文件和文件夹)视图之间切换:
通过选择 终端>新终端,在 VS Code 中打开命令行窗口。 也可以使用 Ctrl+Shift+`(反引号)键盘快捷方式。
除非另有指定,否则请在 Bash 窗口中运行命令。 标记为
Bash
的大多数命令在 Bash 窗口或 VS Code 命令行窗口中运行。
启动 MySQL 数据库管理系统
默认情况下,容器以隔离方式运行。 容器不知道同一台计算机上的其他进程或其他容器。
若要在容器之间启用通信,需要连接到同一网络。 同一网络上的多个容器可以相互共享数据和处理信息。
可通过两种方法将容器附加到网络。 可以在创建期间将容器附加到网络,或稍后将现有容器附加到网络。
在此示例中,你将创建网络并在启动时附加 MySQL 容器。
创建名为
todo-app
的网络:docker network create todo-app
启动名为
todo-mysql-data
的 MySQL 容器,并将其附加到todo-app
网络。 该命令为 MySQL 数据库mysql
创建网络别名todos
。运行此命令时,输入
<your-password>
占位符的 MySQL 根密码。docker run -d --network todo-app --network-alias mysql -v todo-mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=<your-password> -e MYSQL_DATABASE=todos mysql:lts
此命令还定义
MYSQL_ROOT_PASSWORD
和MYSQL_DATABASE
环境变量。 有关详细信息,请参阅 MySQL Docker 中心列表。警告
本教程演示了使用 MySQL 数据库进行身份验证的密码凭据,该数据库不是最安全的方法。 请参阅 MySQL 文档,了解更安全的身份验证方法。
获取容器 ID,以便在下一步中使用。
docker ps
确认可以连接到
mysql
网络上的容器。运行命令时,输入
<mysql-container-id>
占位符的容器 ID。docker exec -it <mysql-container-id> mysql -p
在提示符下,输入创建
todo-mysql-data
容器时提供的密码。在 MySQL shell 中,列出数据库并验证是否看到
todos
数据库。SHOW DATABASES;
应会看到以下输出:
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | todos | +--------------------+ 5 rows in set (0.00 sec)
若要结束连接并返回到命令行提示符,请输入 退出。
使用 MySQL 运行应用
todo
应用支持设置某些环境变量来指定 MySQL 连接设置。 下表列出了支持的变量,以及本部分介绍的示例中使用的值。
变量名称 | 示例值 | 描述 |
---|---|---|
MYSQL_HOST |
mysql |
MySQL 服务器的主机名。 |
MYSQL_USER |
root |
用于连接的用户名。 |
MYSQL_PASSWORD |
<your-password> |
用于连接的密码。 在此示例中,请将根密码替换为 <your-password> 占位符。 |
MYSQL_DATABASE |
todos |
建立连接后要使用的数据库的名称。 |
警告
使用环境变量设置连接设置对于开发是可以接受的,但不建议在生产环境中运行应用程序。 有关详细信息,请参阅 为何不应将环境变量用于机密数据。
更安全的机制是使用容器业务流程框架提供的机密支持。 在大多数情况下,这些机密作为文件装载在正在运行的容器中。
在以下示例中,启动应用并将应用容器连接到 MySQL 容器。
运行以下
docker
命令。 请注意该命令如何指定前面所述的环境变量。运行命令时,请记得输入
<your-password>
占位符的 MySQL 根密码。docker run -dp 3000:3000 -w /app -v ${PWD}:/app --network todo-app -e MYSQL_HOST=mysql -e MYSQL_USER=root -e MYSQL_PASSWORD=<your-password> -e MYSQL_DB=todos node:lts-alpine sh -c "yarn install && yarn run dev"
在 VS Code 编辑器中,打开容器资源管理器,右键单击应用容器,然后选择“ 查看日志”。
还可以使用
docker logs
命令从命令行查看日志。查看日志输出。 请注意指示应用已连接到 MySQL 数据库的行:
Connected to mysql db at host mysql
。# Previous log messages omitted $ nodemon src/index.js [nodemon] 1.19.2 [nodemon] to restart at any time, enter `rs` [nodemon] watching dir(s): *.* [nodemon] starting `node src/index.js` Connected to mysql db at host mysql Listening on port 3000
在 Internet 浏览器中,转到正在运行的应用程序:
http://localhost:3000
。在正在运行的应用程序中,将一些项添加到待办事项列表中。
连接到
mysql
网络上的 MySQL 容器数据库,以便检查数据库。运行命令时,输入
<mysql-container-id>
占位符的容器 ID。docker exec -ti <mysql-container-id> mysql -p todos
在提示符下,输入创建
todo-mysql-data
容器时提供的密码。在 MySQL shell 中,验证你添加的
todo_items
是否已写入todos
数据库。use todos; select * from todo_items;
应会看到类似于以下示例的输出:
+--------------------------------------+--------------------+-----------+ | id | name | completed | +--------------------------------------+--------------------+-----------+ | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! | 0 | | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome! | 0 | +--------------------------------------+--------------------+-----------+
现在,你有一个应用程序,用于在单独的容器中运行的外部数据库中存储数据。 此过程演示如何使用网络在容器之间启用通信。
创建 Docker Compose 文件
Docker Compose 可帮助定义和共享多容器应用程序。 Docker Compose 文件可以指定所有必需的服务,以便可以使用单个命令启动或结束所有相关进程。 可以在项目存储库根目录的 Docker Compose 文件中定义应用程序堆栈,并在版本控制下维护配置。 此方法允许其他人在克隆存储库时为项目做出贡献。
在以下示例中,为多容器应用程序配置 Docker Compose 文件 todo
。
在
todo
应用项目的根目录中,创建名为 docker-compose.yml的 Docker Compose 文件。注意
默认情况下,YAML 架构版本设置为最新版本。 运行应用时,如果架构版本已过时,将收到警告消息。 若要查看当前架构版本和兼容性矩阵,请参阅 概述(撰写文件)。
在 docker-compose.yml 文件中,添加以下元素。 指定应用
name
并启动要作为应用程序的一部分运行的services
(或容器)列表。name: todo services:
服务列表对于你的应用是唯一的。 示例包括
app
、web
、db
、proxy
等。 在后面的步骤中扩展services
元素的定义。提示
缩进在 .yml 文件中非常重要。 如果在 VS Code 中编辑,Intellisense 会指示格式或语法中的任何错误。
返回到
services
文件中的 定义。 通过添加一个条目来扩展定义app
服务元素,其中包括容器的映像。services: app: image: node:lts-alpine
可以为服务选取任何名称。 该名称会自动成为网络别名,在定义 MySQL 服务时非常有用。
扩展
app
元素定义以指定要执行的command
。app: image: node:lts-alpine command: sh -c "yarn install && yarn run dev"
定义要用于
ports
服务的app
。 请注意,这些端口对应于用于使用 MySQL 运行应用的命令的-p 3000:3000
参数。app: image: node:lts-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000
标识
working_dir
服务的工作目录app
以及映射的volumes
。app: image: node:lts-alpine command: sh -c "yarn install && yarn run dev" ports: - 3000:3000 working_dir: /app volumes: - ./:/app
定义 Docker Compose 卷时可以使用基于当前目录的相对路径。
指定在为
environment
服务执行命令时要使用的app
变量定义。app: image: node:lts-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: <your-password> MYSQL_DB: todos
务必输入
<your-password>
占位符中的 MySQL 根密码(root password)。在
mysql
服务定义后添加 MySQL 服务app
的定义。 按所示指定元素名称和值并使用相同的缩进。services: app: ... mysql: image: mysql:lts
mysql
服务定义对应于你之前用于启动 MySQL 的命令。 定义服务时,它会自动接收网络别名。标识
volumes
服务的映射的mysql
。services: app: ... mysql: image: mysql:lts volumes: - todo-mysql-data:/var/lib/mysql
指定在为
environment
服务执行命令时要使用的mysql
变量定义。services: app: ... mysql: image: mysql:lts volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: <your-password> MYSQL_DATABASE: todos
务必输入
<your-password>
占位符中的 MySQL 根密码(root password)。定义整个应用的卷映射。 在
volumes:
部分后添加services:
部分,并使用相同的缩进。services: ... volumes: todo-mysql-data:
确认已完成的 docker-compose.yml 文件如以下示例所示。 您应该能查看到
<your-password>
占位符的 MySQL 根密码。name: todo services: app: image: node:lts-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: <your-password> MYSQL_DB: todos mysql: image: mysql:lts volumes: - todo-mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: <your-password> MYSQL_DATABASE: todos volumes: todo-mysql-data:
使用 Docker Compose 运行应用程序堆栈
现在可以尝试运行 docker-compose.yml 文件。
停止应用程序和数据库的任何正在运行的实例。
按照 VS Code 中的以下步骤操作:
打开 容器资源管理器 (容器工具扩展)。
对于每个正在运行的容器,右键单击该容器并选择 “删除”。
启动多容器应用和所有服务。
按照 VS Code 中的以下步骤操作:
打开 EXPLORER(文件和文件夹)视图。
右键单击 docker-compose.yml 文件,然后选择“撰写启动”。
应会看到类似于以下示例的输出:
[+] Building 0.0s (0/0) [+] Running 2/2 ✔ Container app-app-1 Started 0.9s ✔ Container app-mysql-1 Running
此操作为应用和网络创建映射卷。 默认情况下,Docker Compose 会专门为应用程序堆栈创建网络。
查看正在运行的容器的日志。
按照 VS Code 中的以下步骤操作:
打开 容器资源管理器 (容器工具扩展)。
右键单击应用容器,然后选择“查看日志”。
应会看到类似于以下示例的输出:
mysql_1 | 2019-10-03T03:07:16.083639Z 0 [Note] mysqld: ready for connections. mysql_1 | Version: '5.7.27' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL) app_1 | Connected to mysql db at host mysql app_1 | Listening on port 3000
日志显示服务名称和实例编号,例如每行开头
app_1
。 此格式可帮助你按服务和实例区分消息。 每个服务的日志被整合到一个流中。 此方法使你能够监视与计时相关的问题。现在可以在 Internet 浏览器中打开正在运行的应用程序:
http://localhost:3000
。
停止 Docker Compose 并运行容器
完成应用和容器后,可以将其删除。
按照 VS Code 中的以下步骤操作:
打开 EXPLORER(文件和文件夹)视图。
右键单击 docker-compose.yml 文件,然后选择“撰写停止”。
此操作会停止所有正在运行的容器并删除网络。
默认情况下,不会移除 compose 文件中已命名的卷。 如果要删除这些卷,可以使用 docker-compose down --volumes
命令。
清理资源
如果将本教程系列中的 先决条件 组件应用到安装,则可以重复使用配置以供将来的 Docker 开发使用。 删除或卸载任何组件并不重要。