作者:变优秀的小白
Github:关注YX-XiaoBai
爱好:Americano More Ice !
QQ学习交流群(new): 811792998
目录
多容器应用
在此之前我们已经玩过了单容器应用了。但是我们现在想要加mysql
去我们的应用栈(application stack
)。
你可能会有一些疑问
mysql
会在哪里运行?- 下载是在同一个容器吗?运行是分离的吗?
通常情况中,每个容器应该做一件事且做的很好。以下是为什么他能do it well
- 首先你将
前端&后端
与数据库
区别开来是很好的 - 容器分离可以使你的版本和更新版本独立开来(
解耦
) - 当你可能为本地的数据库使用一个容器,你可能想要为生产环境用一个管理服务。你不想要将你的数据库引擎和你的应用一起发布
- 同时运行多个程序会需要一个程序管理器(
一个容器仅仅启动一个程序
),这样会增加了容器启动和关闭的复杂度
因此,我们更新我们的应用可能如图所示:
集装箱网络(Container networking)
我们需要时刻记得容器的重点
,容器默认上是以隔离模式运行,这也表明了即使多个容器和多个进程在同一个机器工作他们之间也完全不知道对方是啥、在干啥。
tips: 如果两个容器在同一个网路中,他们是可以互相交流的。否则不可以。
启动MySQL
有两种方式将容器放进网络中
- 在启动时表明它
- 连接一个存在容器
现在我们将先会创建网络和在MySql
容器创建时连接
- 创建网络
docker network create todo-app
ce6d03370cb350850c211ee7f223ea47bf72e7860db7ad3ae63027e229c3105b
- 启动一个
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
Tips: 你可能注意到我们使用的名称为
todo-mysql-data
的volume
装入/var/lib/mysql
(是mysql存储数据的地方)。然而,我们不用运行docker volume create
命令,因为docker
会自动识别和为我们自动创建。
- 为了确认我们有个数据库启动并运行了,我们连接下数据库并确定它连接成功
docker exec -it <mysql-container-id> mysql -p
当执行完上面的命令,你需要输入db的密码secret
,验证成功后你会看到todos
数据库
mysql> SHOW DATABASES;
搞定!现在我们的mysql
数据库已经启动成功了
连接Mysql
现在我们知道Mysql
已经启动且正在运行,让我们尝试去使用它吧~ 但是怎么去使用它呢? 如果我们运行的另一个容器在同一个网路中,我们怎么找到这个容器呢?(还记得每个容器拥有自己的IP地址吗
)
我们将充分利用nicolaka/netshoot->netshoot
包含了很多工具,它的主要用于排查和调试网络问题
- 用
nicolaka/netshoot
启动一个新容器,确保连接在同一个网路中
docker run -it --network todo-app nicolaka/netshoot
- 在容器中我们使用
dig
命令(一个有效的DNS工具
)。我们将查找hostname=mysql
的IP
地址
$ dig mysql
// output
; <<>> DiG 9.14.12 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 64017
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;mysql. IN A
;; ANSWER SECTION:
mysql. 600 IN A 172.22.0.2
;; Query time: 1 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Fri Jan 29 10:37:14 UTC 2021
;; MSG SIZE rcvd: 44
在ANSWER SECTION
中,你会看到一个mysql
的一个A
记录紧接着172.22.0.2
(可能与你的IP
地址不同)。虽然mysql
通常不是有效的主机名,但Docker
能够将其解析为具有该网络别名的容器的IP地址(还记得我们前面使用的--network alias
标志吗?)
我的意思就是,我们应用只要简单连接一个hostname
为mysql
即可与数据库交互。
使用mysql运行应用
我们的应用支持以下环境变量镇定mysql
连接设置
MYSQL_HOST
: 运行的Mysql
服务器的hostname
MYSQL_USER
: 用于连接Mysql
的用户名MYSQL_PASSWORD
: 用于连接Mysql
的密码MYSQL_DB
: 连接使用的数据库
- 指定上面提到的每个环境变量,并将容器连接到我们的应用网路中
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
数据库 -
打开
http://localhost:3000:3000
,添加一些数据
- 连接
mysql
数据库验证自己的数据被写入
docker exec -it <mysql-container-id> mysql -p todos
- 接着在
shell
中运行
tips: 此处可能存在延迟,数据库连接有一定时长
mysql> select * from todo_items;
+--------------------------------------+------------+-----------+
| id | name | completed |
+--------------------------------------+------------+-----------+
| dc967fb4-f030-42f6-a3ec-466284111a98 | YX-Xiaobai | 1 |
| 6508d432-fa16-492e-9521-a2cbabbf8400 | 666 | 0 |
| 88b7b280-b6dd-484e-834f-0904d50424c8 | 123 | 0 |
+--------------------------------------+------------+-----------+
3 rows in set (0.00 sec)
我们可以在Docker Dashboard
中看到我们这两个容器,但是不能看出来这两者是否连接在一起了,或者说不能知道这两者处于同一个网络当中
总结
到这里,我们已经有了一个将数据存储在单独容器(外部数据库
)的应用程序。我们必须创建一个网络,启动容器,指定所有环境变量,公开端口等等。
接下来的一篇,重头戏(方便我们旋转跳跃
) -->> Docker Compose
,可以让我们更金安达的共享我们的应用程序堆栈仅需使用一个命令