到目前为止,我们一直在使用单容器应用程序。但是,我们现在想将 MySQL 添加到应用程序堆栈中。经常会伴随一些问题——“MySQL 将在哪里运行?安装在同一个容器中还是单独运行?”
一般来说,**每个容器都应该做一件事,并且做好。**几个原因:
- 你很有可能必须以不同于数据库的方式扩展 API 和前端
- 单独的容器让你可以隔离版本和更新版本
- 虽然你可以在本地为数据库使用容器,但你可能希望在生产环境中为数据库使用托管服务。而且,你不想将数据库引擎与你的应用程序一起提供。
- 运行多个进程将需要一个进程管理器(容器只启动一个进程),这增加了容器启动/关闭的复杂性
还有更多的原因。因此,我们将更新我们的应用程序,使其像这样工作:
容器网络
默认情况下,容器是独立运行的,对同一台机器上的其他进程或容器一无所知。那么,我们如何让一个容器与另一个容器通信呢?答案是 网络
如果两个容器在同一个网络上,它们可以相互通信。反之,他们就不能相互通信。
使用Docker启动MySQL
有两种方法可以将容器放在网络上:在开始时分配容器
或 连接现有容器
。现在,我们首先创建网络并在启动时附加 MySQL 容器。
1、创建网络。
docker network create todo-app
2、启动 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
如果使用的是基于 ARM 的芯片,如苹果的Mac,则使用此命令。
docker run -d \
--network todo-app --network-alias mysql \
--platform "linux/amd64" \
-v todo-mysql-data:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=todos \
mysql:5.7
如果使用的是 Windows,请在 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
- 使用了一个名为
todo-mysql-data
的数据卷
,并将其安装在 MySQL 存储数据的位置/var/lib/mysql
MYSQL_ROOT_PASSWORD
必需,指定 MySQLroot
超级用户帐户设置的密码MYSQL_DATABASE
可选,指定在映像启动时创建的数据库的名称mysql:5.7
中的5.7
是tag
指定的 MySQL 版本的标签
3、要确认我们已启动并运行数据库,请连接到数据库并验证它是否已连接。
$ docker exec -it <mysql-container-id> mysql -u root -p
出现密码提示时,输入secret。
在 MySQL shell 中列出数据库,可以看到todos
数据库。
mysql> SHOW DATABASES;
应该看到如下所示的输出:
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| todos |
+--------------------+
5 rows in set (0.00 sec)
退出 MySQL shell 以返回到我们机器上的 shell。
mysql> exit
已经创建好todos
数据库。
连接到MySQL
现在 MySQL 已经启动并运行了,但是我们如何去使用它?如果我们在同一个网络上运行另一个容器,我们如何找到该容器?(每个容器都有自己的 IP 地址)
为了解决这个问题,我们将使用nicolaka/netshoot容器,它附带了许多对故障排除或调试网络问题的工具。
1、使用 nicolaka/netshoot
镜像启动一个新容器。确保将其连接到同一网络。
$ docker run -it --network todo-app nicolaka/netshoot
2、在容器内部使用dig
命令,这是一个很有用的 DNS 工具。我们将查找主机名为mysql
的 IP 地址。
$ dig mysql
输出如图所示:
在ANSWER SECTION
中,你将看到解析为 172.23.0.2 的 mysql 的 A 记录( IP 地址可能有不同的值)。
虽然 mysql 通常不是有效的主机名,但 Docker 能够将其解析为具有该网络别名的容器的 IP 地址(我们之前使用的 --network-alias
标志)。
这意味着,我们的应用程序只需要连接到一个名为 mysql
的主机,它就会与数据库对话。
应用程序支持设置一些环境变量来指定 MySQL 连接设置
MYSQL_HOST
正在运行的 MySQL 服务器的主机名MYSQL_USER
用于连接的用户名MYSQL_PASSWORD
用于连接的密码MYSQL_DB
连接后使用的数据库
1、注意:对于 MySQL 8.0 及更高版本,请确保在 mysql中运行以下命令:
mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'secret';
mysql> flush privileges;
2、我们将指定上面的每个环境变量,并将容器连接到我们的应用程序网络。在应用程序目录运行:
$ 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"
如果使用的是 Windows,请在 PowerShell 中使用此命令。
PS> 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"
3、如果我们查看容器的日志,我们应该会看到一条消息,表明它正在使用 mysql 数据库。
$ docker logs <container-id>
4、在浏览器中打开应用程序,然后将一些项目添加到的待办事项列表中。
5、连接 mysql 数据库并证明项目正在写入数据库。记住,密码是加密的。
$ docker exec -it <mysql-container-id> mysql -p todos
在 mysql shell 中,运行以下命令:
mysql> select * from todo_items;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YOMZkUlH-1659600598560)(https://raw.githubusercontent.com/yuyun-21/uplod-images/hyh/images/Flowable/image-20220620114323914.png)]
如果快速查看 Docker 仪表板,会发现我们有两个应用程序容器正在运行。但是,没有真正的迹象表明它们在一个应用程序中组合在一起。