@longj
2018-06-07T12:42:36.000000Z
字数 5255
阅读 3421
Author Johnny Law
注:本博客不涉及对 nginx, flask, mysql 或者 redis 过多的介绍,并假定读者已经有了一定的 Docker 入门基础。本博客重点介绍如何使用 docker-compose 把它们连接起来。
对 nginx, flask, mysql, redis 不熟悉并不影响阅读。 另可参考docker 的简单介绍
本博客所介绍的 docker-compose.yml 文件的标签只是基础的,更加丰富的使用的方法请参考官方文档。
Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速的部署分布式应用。

Compose 定位是 「定义和运行多个 Docker 容器的应用(Defining and running multi-container Docker applications)」,其前身是开源项目 Fig。Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理。因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理。
通过之前对于 docker 的简单介绍,我们知道使用一个 Dockerfile 模板文件,可以让用户很方便的定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。

本篇博客将对上图所描述 web 后台结构实现 docker-compose 一键部署
按照官网给出的指导进行安装即可。
下面是在 Linux 下安装流程
下载最新版本的 docker-compose(于2018.06.03, 最新版本以官网为准)
sudo curl -L https://github.com/docker/compose/releases/download/1.21.2/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
给可执行文件赋予运行权限
sudo chmod +x /usr/local/bin/docker-compose
测试安装结果,查看 docker-compose 的版本
$ docker-compose --versiondocker-compose version 1.21.2, build 1719ceb
如果可以看到对应的 docker-compose 的版本号,则显示安装成功。
Docker Compose 允许你在项目根目录下的一个陈述性语言 yaml 文件 docker-compose.yml 中定义你这个项目所要用到的所有容器,网络,或者挂载的信息。然后运行一个简单的命令 docker-compose up 即可以进行一键部署。
项目的文件目录组织情况因人而异,我个人比较喜欢的是把每个容器的需要东西都放在一个独立的文件夹中,然后由 docker-compose 进行统一的调用。下面是我们小组课程项目的文件结构目录:
.├── app│ ├── app.py│ ├── data│ │ ├── menu_database.json│ │ └── resturant_database.json│ ├── data_importer.py│ ├── db_insert.py│ ├── dbOperators.py│ ├── Dockerfile│ ├── requirements.txt│ ├── tools.py│ └── wait-for-it.sh├── db│ ├── 01-my-script.sh│ ├── Dockerfile│ ├── README.md│ └── TinyHippo.sql├── docker-compose.yml├── LICENSE├── nginx│ └── conf.d│ └── web.conf└── README.md
下面是我的项目中 docker-compose.yml 的例子:
version: '3'services:db:restart: alwaysbuild: db/.environment:MYSQL_ROOT_PASSWORD: tiny-hippoMYSQL_DATABASE: TINYHIPPOMYSQL_USER: tinyMYSQL_PASSWORD: tiny-hippoports:- "3306:3306"networks:- db_nwweb:restart: alwaysbuild: app/.volumes:- ./app:/code/appworking_dir: /code/appcommand: bash -c "/code/app/run-after-db-init.sh"depends_on:- db- redisnetworks:- db_nw- web_nw- redis_nwstdin_open: truetty: trueredis:image: "redis:alpine"networks:- redis_nwnginx:image: nginx:latestrestart: alwaysports:- "8080:80"volumes:- ./nginx/conf.d:/etc/nginx/conf.ddepends_on:- webnetworks:- web_nwnetworks:db_nw:driver: bridgeweb_nw:driver: bridgeredis_nw:driver: bridge
我们需要在 services 标签下指定各个容器的名字和基本属性。
buildimageimage 标签来指定使用的镜像。(需要 build 的镜像在它们各自的 Dockerfile 中指定了初始的镜像)ports3306:3306 只是为了暴露 mysql 的接口方便本地进行调试,实际部署到生产环境的时候可以去掉。restartrestart: always ,当容器意外退出的时候可以一直重启,保证容器跑的进程不会 exit,方便调试。networksnetworks 标签中指定。
environment:MYSQL_ROOT_PASSWORD: tiny-hippoMYSQL_DATABASE: TINYHIPPOMYSQL_USER: tinyMYSQL_PASSWORD: tiny-hippo
上述命令是用来指定 MySQL db 容器的环境变量,使得 mysql 的容器一启动起来就可以按照设置的环境变量进行初始化
volumesdocker-compose up 运行了整个服务后,修改本地代码文件即可以直接反映在对应的容器中,而不需要重启 docker-compose, 方便调试。depends_oncommandrun-after-db-init.sh, web 会先一直向 db 的 3306 发送请求,直至成功连接后才启动服务 python app.py ,防止web 在 db 启动后, 初始化未完成时就尝试连接数据库导致连接失败的情况。stdin_open, tty对于 redis 和 nginx, 并没有特别需要设置的,所用到的设置也已经在前面介绍过,不再赘述。
在 networks 标签下指定各个网络的名字和连接方式。常用的连接方式是桥接 bridge.
docker-compose 会在宿主机 (host) 的内部构建一个虚拟的网络环境,并且为各个容器分配了一个 ip 地址,services 中的各个容器的名字,eg. web, db, nginx 将会被加载进 docker-compose 提供的 DNS 系统里面。这意味着我们可以在程序中直接使用 services 的名字作为 host 来实现连接。

eg. 在我们的项目中, 用 python3 写的持久化层可以直接与 db 建立连接:
db = pymysql.connect(host='db',user='root',password='tiny-hippo',database='TINYHIPPO',charset='utf8')
这样我们就可以非常方便地在 docker-compose 中添加我们想要的服务容器,并实现相互沟通。
在 Nginx 的容器中,我们挂载一个简单的配置文件
server {listen 80;server_name localhost;location / {proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;proxy_set_header Host $http_host;proxy_pass http://web:5000;}}
注意这里的 proxy_pass 的设置中 hostnane 直接就设置成 docker-compose.yml 中设置的容器的名字 web, 这是因为 Docker 内部的 DNS 可以处理拿到正确的 ip 地址。
定义好了各个容器的构建方式,还有总体的 docker-compose 模板文件 docker-compose.yml 后,就可以很轻松地使用 docker-compose 进行一键部署了!
在项目根目录下运行下面命令:
docker-compose up
实验结果截图

后台已经成功部署并开始监听。
访问 http:localhost:8080/ 获取 json 数据:

访问 http:localhost:8080/testRedis 并进行几次刷新,对后台进行测试。
其中的数字会更新,说明 redis 缓冲可以正常工作
访问 http:localhost:8080/insert_fake_data1 插入假数据

查看后台记录:
nginx 运行正常
docker-compose up -d 让 docker-compose 在后台运行docker-compose downdocker-compose build webdocker-compose up -d --scale web=3 可以方便地多开几 (3) 个 web 容器,提高业务处理的性能。文中所用的代码参考仓库rookies-sysu/Order-System-Backend