Docker(七)——多容器应用
如果我们想添加 MySQL 到我们的应用栈。下面产生了几个问题,MySQL在哪里运行?安装在同一个容器还是分开安装?总得来说,每个容器应该只做一件事情,并做好。原因如下:很可能需要扩展 APIs,但是前端和数据库不同。独立的容器使得能够控制版本,更新的版本是隔离的。当你为本地数据库使用一个容器,你可能会想在生产环境终端数据库使用一个管理服务。所以,你不想将你的数据库和应用一起发送。运行多个进程需要
如果我们想添加 MySQL 到我们的应用栈。下面产生了几个问题,MySQL在哪里运行?安装在同一个容器还是分开安装?总得来说,每个容器应该只做一件事情,并做好。
原因如下:
- 很可能需要扩展 APIs,但是前端和数据库不同。
- 独立的容器使得能够控制版本,更新的版本是隔离的。
- 当你为本地数据库使用一个容器,你可能会想在生产环境终端数据库使用一个管理服务。所以,你不想将你的数据库和应用一起发送。
- 运行多个进程需要一个进程管理器(容器只能启动一个进程),这增加了容器启动和关闭的复杂性。
因为这些原因,我们将会以下面的工作方式更新我们的应用:
容器联网
容器默认是独立工作的,不知道其他在机器中的进程和容器。我们可以使用网络去使一个容器可以和另一个容器通信。
如果两个容器在同一个网络,那么可以互相通信。否则不行。
启动 MySQL
这里有两种方式将一个容器放入一个网络。
- 在开始时分配它。
- 连接一个现存的容器
下面我们将先建立一个网络,再在启动 MySQL 容器时将其加入进去。
- 创建网络
docker network create todo-app
- 启动一个 MySQL 容器,并将其加入到网络中。我们也将定义一些环境变量,使数据库可以用来初始化。
docker run -d --network todo-app --network-alias mysql -v todo-mysql-data:/var/lib/my
sql -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=todos mysql:5.7
你可能会注意到,我们正使用一个 todo-mysql-data
volume,然后将其挂载到 /var/lib/mysql
,MySQL在这存储数据。但是,我们没有运行 docker volume create
命令。Docker 推测我们想使用一个 named volume
然后自动给我们创建了一个。
- 为了确定我们安装了数据库并且运行了,连接数据库并验证它的连接。
docker exec -it <mysql-container-id> mysql -u root -p
当密码提示出现时,键入密码。在 MySQL shell
列出数据库,你可以看到 todos
数据库。
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| todos |
+--------------------+
5 rows in set (0.00 sec)
连接 MySQL
现在我们知道 MySQL 已经被安装和运行了。现在的问题是,如果我们在相同的网络内运行另一个容器,我们将如何找到这个容器?
为了解决这个问题,我们将要使用 nicolaka/netshoot
容器,这个容器有许多用于检测和调试网络问题的工具。
- 首先,使用
nicolaka/netshoot
镜像启动一个新容器。确保连接在同一个网络内。
docker run -it --network todo-app nicolaka/netshoot
- 在容器内部,我们将使用
dig
命令,一个有用的域名解析工具。我们将查找主机名为mysql
的 IP 地址。
dig mysql
输出如下:
; <<>> DiG 9.16.22 <<>> mysql
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 24223
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;mysql. IN A
;; ANSWER SECTION:
mysql. 600 IN A 172.18.0.2
;; Query time: 2 msec
;; SERVER: 127.0.0.11#53(127.0.0.11)
;; WHEN: Fri Mar 04 09:31:59 UTC 2022
;; MSG SIZE rcvd: 44
在 ANSWER SECTION
,你会看到一个 A
记录给 mysql
,这将解析为 172.18.0.2
。虽然 mysql
不是一个标准的合法主机名,Docker也能够将其解析为有着网络别名容器的 IP 地址。
所以,我们的应用只要连接到主机名为 mysql
,就可以和数据库通信。
使用 MySQL 运行应用
todo 应用支持设置一些环境变量去设置 MySQL 的连接设置。
MYSQL_HOST
- 运行 MySQL 服务器的主机名MYSQL_USER
- 连接使用的用户名MYSQL_PASSWORD
- 连接使用的密码MYSQL_DB
- 连接时使用的数据库
下面,我们开启设备准备容器
- 对于 MySQL8.0 以及更高版本,在
mysql
中运行下面的命令
mysql> ALTER USER 'root' IDENTIFIED WITH mysql_native_password BY 'secret';
mysql> flush privileges;
- 明确环境变量,同时将容器连接至我们的应用网络
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
数据库的信息。
yarn install v1.22.17
[1/4] Resolving packages...
warning Resolution field "ansi-regex@5.0.1" is incompatible with requested version "ansi-regex@^2.0.0"
warning Resolution field "ansi-regex@5.0.1" is incompatible with requested version "ansi-regex@^3.0.0"
success Already up-to-date.
Done in 0.44s.
yarn run v1.22.17
$ nodemon src/index.js
[nodemon] 2.0.13
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node src/index.js`
Waiting for mysql:3306.
Connected!
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 |
+--------------------------------------+-------+-----------+
| a6a1d6df-73d1-4277-9d0d-cc7d7f4df0de | 1321 | 0 |
| 84e1989c-b1ec-4329-b7b9-32943f3b75fa | 21312 | 0 |
| e9c22587-f676-4fca-b9b3-f2503d5160c5 | 321 | 0 |
+--------------------------------------+-------+-----------+
3 rows in set (0.00 sec)
你可以看到添加的项,被加入到 MySQL 数据库中。
如果你此时打开 Dashboard,会发现有两个容器在运行。
更多推荐
所有评论(0)