一、概述
到目前为止,你一直在使用单个容器应用。但是,现在您将 MySQL 添加到 应用程序堆栈。经常会出现以下问题 - “MySQL将在哪里运行?将其安装在同一个 容器还是单独运行?一般来说,每个容器都应该做一件事,并且把它做好。以下是单独运行容器的几个原因:
- 很有可能你必须以与数据库不同的方式扩展 API 和前端。
- 通过单独的容器,可以单独对版本进行版本控制和更新。
- 虽然您可以在本地使用数据库的容器,但您可能希望使用托管服务 用于生产中的数据库。然后,你不希望将数据库引擎与应用一起提供。
- 运行多个进程将需要一个进程管理器(容器只启动一个进程),这增加了容器启动/关闭的复杂性。
还有更多原因。因此,如下图所示,最好在多个容器中运行应用。
二、容器网络
请记住,默认情况下,容器是孤立运行的,对其他进程一无所知 或同一台机器上的容器。那么,如何允许一个容器与另一个容器通信呢?答案是 联网。如果将两个容器放在同一个网络上,它们可以相互通信。
三、启动 MySQL
有两种方法可以将容器放在网络上:
- 启动容器时分配网络。
- 将已运行的容器连接到网络。
在以下步骤中,你将首先创建网络,然后在启动时附加 MySQL 容器。
-
创建网络。
<span style="background-color:#ffffff"><code class="language-console"><span style="color:#8f5902">$</span> docker network create todo-app </code></span>
-
启动 MySQL 容器并将其附加到网络。您还将定义一些环境变量,这些变量 database 将用于初始化数据库
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:8.0
在上一个命令中,您可以看到--network alias标志。在后面的部分中,您将了解有关此标志的更多信息。
提示
在上面的命令中,您会注意到一个名为todo-mysql-data的卷,它安装在/var/lib/mysql中,mysql就是在这里存储数据的。但是,您从未运行过docker volume create命令。Docker识别出您想要使用一个命名卷,并自动为您创建一个。 - 若要确认数据库已启动并运行,请连接到数据库并验证其是否已连接。
docker exec -it <mysql-container-id> mysql -u root -p
当出现密码提示时,键入secret。在MySQL外壳中,列出数据库并验证是否看到todos数据库。
mysql> SHOW DATABASES;
您应该看到如下输出:
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | todos | +--------------------+ 5 rows in set (0.00 sec)
4. 退出MySQL shell以返回到您机器上的shell。
mysql> exit
现在您有了一个todos数据库,可以使用了。
四、连接到MySQL
既然你知道MySQL已经启动并运行了,你就可以使用它了。但是,你该如何使用它呢?如果在同一网络上运行另一个容器,如何找到该容器?请记住,每个容器都有自己的IP地址。
为了回答上述问题并更好地理解容器网络,您将使用nicolaka/netshoot容器,该容器附带了许多工具,这些工具对解决或调试网络问题非常有用。
- 使用nicolaka/netshoot映像启动一个新容器。请确保将其连接到同一网络。
2. 在容器中,您将使用dig命令,这是一个有用的DNS工具。您将查找主机名mysql的IP地址。docker run -it --network todo-app nicolaka/netshoot
dig mysql
您应该得到如下输出。
; <<>> DiG 9.18.8 <<>> mysql ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 32162 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;mysql. IN A ;; ANSWER SECTION: mysql. 600 IN A 172.23.0.2 ;; Query time: 0 msec ;; SERVER: 127.0.0.11#53(127.0.0.11) ;; WHEN: Tue Oct 01 23:47:24 UTC 2019 ;; MSG SIZE rcvd: 44
在“应答部分”中,您将看到mysql的一条A记录,解析为172.23.0.2(您的IP地址很可能有不同的值)。虽然mysql通常不是一个有效的主机名,但Docker能够将其解析为具有该网络别名的容器的IP地址。请记住,您之前使用了--network别名。
这意味着你的应用程序只需要连接到一个名为mysql的主机,它就会与数据库对话。
五、使用 MySQL 运行应用使用 MySQL 运行应用
todo 应用程序支持设置一些环境变量来指定 MySQL 连接设置。他们是:
MYSQL_HOST
- 正在运行的MySQL服务器的主机名MYSQL_USER
- 用于连接的用户名MYSQL_PASSWORD
- 用于连接的密码MYSQL_DB
- 连接后要使用的数据库
现在,您可以启动您的开发就绪容器:
- 指定以前的每个环境变量,并将容器连接到应用程序网络。运行此命令时,请确保您位于“入门”应用程序目录中。
docker run -dp 127.0.0.1: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:18-alpine \
sh -c "yarn install && yarn run dev"
- 如果您查看容器的日志(docker-logs-f<containerid>),您应该会看到类似于下面的消息,这表明它正在使用mysql数据库。
nodemon src/index.js
[nodemon] 2.0.20
[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
- 在浏览器中打开应用程序,并将一些项目添加到待办事项列表中。
- 连接到mysql数据库,并证明项目正在写入数据库。记住,密码是秘密的。
docker exec -it <mysql-container-id> mysql -p todos
在mysql shell中,运行以下命令:
mysql> select * from todo_items; +--------------------------------------+--------------------+-----------+ | id | name | completed | +--------------------------------------+--------------------+-----------+ | c906ff08-60e6-44e6-8f49-ed56a0853e85 | Do amazing things! | 0 | | 2912a79e-8486-4bc3-a4c5-460793a575ab | Be awesome! | 0 | +--------------------------------------+--------------------+-----------+
您的表看起来会有所不同,因为它有您的项目。但是,你应该看到它们被存放在那里。