多容器应用
预计阅读时间:9分钟
到目前为止,我们一直在使用单个容器应用程序。但是,我们现在想将MySQL添加到应用程序堆栈中。通常会出现以下问题-“ MySQL将在哪里运行?将它安装在同一个容器中还是单独运行?” 通常,每个容器都应该做一件事情并且做好事。原因如下:
- 您很有可能必须以与数据库不同的方式扩展API和前端
- 单独的容器使您可以单独进行版本控制和更新版本
- 尽管您可能在本地使用数据库的容器,但可能要在生产环境中使用数据库的托管服务。然后,您不希望随应用程序一起提供数据库引擎。
- 运行多个进程将需要一个进程管理器(容器仅启动一个进程),这增加了容器启动/关闭的复杂性
还有更多原因。因此,我们将更新我们的应用程序使其工作如下:
容器网络
请记住,默认情况下,容器是独立运行的,并且对同一台计算机上的其他进程或容器一无所知。那么,我们如何允许一个容器与另一个容器对话?答案是 网络。现在,您不必成为网络工程师(万岁!)。只要记住这个规则...
笔记
如果两个容器在同一网络上,则它们可以相互通信。如果不是,他们就不会。
启动MySQL
有两种将容器放置在网络上的方法:1)在开始时分配它,或2)连接现有的容器。现在,我们将首先创建网络,并在启动时附加MySQL容器。
-
创建网络。
docker network create todo-app
-
启动一个MySQL容器并将其附加到网络。我们还将定义一些数据库将用于初始化数据库的环境变量(请参阅MySQL Docker Hub清单中的“环境变量”部分)。
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
您还将看到我们指定了
--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 Shell中,列出数据库并确认您看到该
todos
数据库。mysql> SHOW DATABASES;
您应该看到如下所示的输出:
+--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | sys | | todos | +--------------------+ 5 rows in set (0.00 sec)
万岁!我们有我们的
todos
数据库,可以随时使用!
连接到MySQL
现在我们知道MySQL已启动并正在运行,让我们使用它吧!但是,问题是...如何?如果我们在同一网络上运行另一个容器,我们如何找到该容器(记住每个容器都有自己的IP地址)?
为了弄清楚,我们将使用nicolaka / netshoot容器,该容器附带了许多工具,这些工具可用于故障排除或调试网络问题。
-
使用nicolaka / netshoot映像启动一个新容器。确保将其连接到同一网络。
docker run -it --network todo-app nicolaka/netshoot
-
在容器内部,我们将使用
dig
命令,这是一个有用的DNS工具。我们将查找主机名的IP地址mysql
。dig mysql
然后您将得到这样的输出...
; <<>> DiG 9.14.1 <<>> 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
在“答复部分”中,您将看到解决该问题的
A
记录 (您的IP地址很可能具有不同的值)。虽然通常不是有效的主机名,但Docker能够将其解析为具有该网络别名的容器的IP地址(还记得我们之前使用的 标志吗?)。mysql
172.23.0.2
mysql
--network-alias
这意味着...我们的应用程序仅需要连接到名为的主机
mysql
,它将与数据库对话!没有比这更简单的了!
使用MySQL运行您的应用
todo应用程序支持一些环境变量的设置,以指定MySQL连接设置。他们是:
MYSQL_HOST
-正在运行的MySQL服务器的主机名MYSQL_USER
-用于连接的用户名MYSQL_PASSWORD
-用于连接的密码MYSQL_DB
-连接后要使用的数据库
通过Env Vars设置连接设置
虽然通常可以使用env vars设置连接设置来进行开发,但是 在生产环境中运行应用程序时,强烈建议不要使用它。Docker的前安全主管Diogo Monica 写了一篇很棒的博客文章, 解释了为什么。
一种更安全的机制是使用容器编排框架提供的秘密支持。在大多数情况下,这些机密会作为文件安装在正在运行的容器中。您会看到许多应用程序(包括MySQL映像和todo应用程序)也支持带有
_FILE
后缀的env var,以指向包含变量的文件。例如,设置
MYSQL_PASSWORD_FILE
var将使应用程序将引用文件的内容用作连接密码。Docker并没有做任何支持这些环境变量的事情。您的应用将需要知道寻找变量并获取文件内容。
在解释了所有这些内容之后,让我们开始开发就绪容器!
-
我们将指定上面的每个环境变量,并将容器连接到我们的应用程序网络。
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"
-
如果我们查看容器(
docker logs <container-id>
)的日志,则应该看到一条消息,表明它正在使用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
-
在浏览器中打开应用程序,然后向待办事项列表中添加一些项目。
-
连接到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 | +--------------------------------------+--------------------+-----------+
显然,您的表看起来会有所不同,因为它包含您的项目。但是,您应该看到它们存储在这里!
如果快速浏览Docker Dashboard,您会看到我们有两个正在运行的应用程序容器。但是,没有真正的迹象表明它们在单个应用程序中组合在一起。我们很快就会看到如何使它变得更好!
回顾
至此,我们有了一个应用程序,该应用程序现在将其数据存储在运行在单独容器中的外部数据库中。我们了解了一些有关容器网络的知识,并了解了如何使用DNS执行服务发现。
但是,很有可能您会对启动该应用程序所需做的一切感到有点不知所措。我们必须创建一个网络,启动容器,指定所有环境变量,公开端口等等!这要记住很多,这肯定会使事情很难传递给其他人。
在下一节中,我们将讨论Docker Compose。借助Docker Compose,我们可以以更简单的方式共享我们的应用程序堆栈,并允许其他人使用一个(简单的)命令将它们旋转起来!
入门,设置,方向,快速启动,简介,概念,容器,码头