BHOL304 - 使用docker-compose进行容器编排

本实验中,我们将使用docker-compose工具对docker脚本提供配置管理能力。Docker 使用起来虽然方便,但是如果全部通过脚本运行仍然不可靠,因为脚本本身无法有效的配置化,比如:对脚本中某个参数的变更会造成整个脚本的变更,这对于我们管理环境变更非常不方便。

Docker Compose就是为了解决这个问题而出现,它通过将docker脚本转换成yaml格式的配置文件,将所有命令参数进行配置化管理,并可以与代码一起保存,为我们提供了docker的 Iac (Infrastructure as Code) 能力支持。

01 - 为 docker-demo 添加后台数据库

使用vscode打开我们在 BHOL03 中使用的 docker-demo 代码库

BHOL304 - 使用docker-compose进行容器编排 - 图1

使用以下代码更新其中的 index.js

  1. var express = require('express');
  2. var app = express();
  3. var mysql = require("mysql");
  4. var con = mysql.createConnection(
  5. {
  6. host: process.env.MYSQL_HOST,
  7. user: process.env.MYSQL_USER,
  8. password: process.env.MYSQL_PASSWORD,
  9. database: process.env.MYSQL_DATABASE
  10. });
  11. // mysql code
  12. con.connect(function(err){
  13. if(err){
  14. console.log('Error connecting to db: ', err);
  15. return;
  16. }
  17. console.log('Connection to db established');
  18. con.query('CREATE TABLE IF NOT EXISTS visits (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, ts BIGINT)',function(err) {
  19. if(err) throw err;
  20. });
  21. });
  22. // Request handling
  23. app.get('/', function (req, res) {
  24. // create table if not exist
  25. con.query('INSERT INTO visits (ts) values (?)', Date.now(),function(err, dbRes) {
  26. if(err) throw err;
  27. res.send('Hello Boathouse! You are visitor number '+dbRes.insertId);
  28. });
  29. });
  30. // server
  31. var server = app.listen(3000, function () {
  32. var host = server.address().address;
  33. var port = server.address().port;
  34. console.log('Example app listening at http://%s:%s', host, port);
  35. console.log('process.env.MYSQL_HOST:',process.env.MYSQL_HOST);
  36. });

以上代码中增加了访问mysql数据库的逻辑

  • 在应用启动的时候创建一个visit表
  • 每次用户请求都会在这个表中写入一条数据,同时输出当前的请求数量

现在我们必须有一个mysql数据库才能启动这个应用。

02 - 使用docker运行mysql容器

运行以下脚本启动一个mysql容器

  1. # 启动mysql容器
  2. docker run --name docker-demo-db -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=myapp -e MYSQL_USER=myapp -e MYSQL_PASSWORD=password -p 3306:3306 -d mysql:5.7
  3. # 检查容器正常运行中
  4. docker ps
  5. # 检查 bridge 网络,并获取 docker-demo-db 的内网IP地址
  6. docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-demo-db
  7. {docker-demo-db 内网IP地址}

运行效果如下

BHOL304 - 使用docker-compose进行容器编排 - 图2

我们现在就有一个可以连接的mysql服务器,并且在其中创建了叫做myapp的数据库。

03 - 重新打包docker-demo并连接到mysql数据库

我们现在需要对docker-demo重新编译打包,并且在启动容器的时候按照代码中的要求添加环境变量,以便新的docker-demo容器可以连接到mysql服务器。

  1. # 执行以下命令完成编译打包,同时tag新镜像为 docker-demo:v2-mysql
  2. docker build -t docker-demo:v2-mysql .
  3. # 添加环境变量运行 v2-mysql 容器
  4. docker run --name docker-demo-web -e MYSQL_DATABASE=myapp -e MYSQL_USER=myapp -e MYSQL_PASSWORD=password -e MYSQL_HOST={docker-demo-db 内网IP地址} -itd -p 3000:3000 docker-demo:v2-mysql

打开浏览器导航到 http://192.168.99.102:3000

BHOL304 - 使用docker-compose进行容器编排 - 图3

04 - 使用一个 docker-compose 配置文件完成以上操作

使用vscode在docker-demo目录中创建 docker-compose.yml 文件,并添加以下内容

  1. version: "2.1"
  2. services:
  3. web:
  4. build: .
  5. ports:
  6. - "3000:3000"
  7. links:
  8. - db
  9. environment:
  10. MYSQL_DATABASE: myapp
  11. MYSQL_USER: myapp
  12. MYSQL_PASSWORD: password
  13. MYSQL_HOST: db
  14. depends_on:
  15. db:
  16. condition: service_healthy
  17. db:
  18. image: mysql:5.7
  19. ports:
  20. - "3306:3306"
  21. environment:
  22. MYSQL_DATABASE: myapp
  23. MYSQL_USER: myapp
  24. MYSQL_PASSWORD: password
  25. MYSQL_ROOT_PASSWORD: password
  26. healthcheck:
  27. test: ["CMD", 'mysqladmin', 'ping', '-h', 'localhost', '-u', 'root', '-p$$MYSQL_ROOT_PASSWORD' ]
  28. timeout: 5s
  29. retries: 3

清理镜像并使用docker-compose启动应用

  1. ## 清理正在运行的容器
  2. docker rm -f $(docker ps -qa)
  3. ## 一键启动
  4. docker-compose up

你会看到terminal中所输出的容器日志,等待日志输出 Example app listening at http://:::3000 以后,在主机上打开浏览器导航到

http://192.168.99.102:3000

即可看到如下应用

BHOL304 - 使用docker-compose进行容器编排 - 图4

清理环境

  1. ## 按Ctrl-C停止docker-compose运行
  2. ## 清理docker-compose应用
  3. docker-compose down

小结

docker-compose实在单机docker环境中进行多容器编排的非常有效的工具,可以把复杂纷乱的命令行参数转换成容易管理的yaml格式,便于我们与代码一同存储,同时也方便我们对环境配置变更进行审核。确保环境部署的可靠性。