Docker Compose

如果Docker中的一个服务需要依赖多个应用进程(比如一个web服务由java、tomcat、mysql、nginx等多个应用进程组成),需要在Docker中运行多个容器,容器之间有交互和关联,docker run提供--link选项来建立容器间的依赖关联。

但是容器的依赖必须保证被依赖的容器正在运行,如果一个服务中容器的依赖关系比较复杂、繁琐,还可能容易出现差错。Docker提供了Docker Compose来解决此问题。

Docker Compose是Docker官方提供的容器编排工具,它使用YAML格式模板文件定义容器的依赖关系,这些容器会根据配置模板中的“--link”等参数,对启动的优先级自动排序,简单执行一条“docker-compose up”,就可以把同一个服务中的多个容器依次创建、启动。

1.安装Docker Compose

官方指引:https://docs.docker.com/compose/install/#install-compose

Step 1:下载最新版Docker Compose

$ sudo curl -L https://github.com/docker/compose/releases/download/1.18.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   617    0   617    0     0    541      0 --:--:--  0:00:01 --:--:--   541
100 8280k  100 8280k    0     0   101k      0  0:01:21  0:01:21 --:--:--  106k

Step 2:添加可执行权限

$ chmod +x /usr/local/bin/docker-compose

Step 3:测试是否安装成功

$ docker-compose --version
docker-compose version 1.18.0, build 8dd22a9

2.使用Docker Compose创建、启动、停止容器

这里使用之前提到的WordPress的例子来做演示

Step 1:查询原来WordPress应用启动的容器

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
26a266da188a        wordpress           "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       0.0.0.0:8080->80/tcp   MyWordPress
05305331681f        mariadb             "docker-entrypoint.s…"   11 minutes ago      Up 11 minutes       3306/tcp               db

Step 2:停止这两个容器

[root@localhost ~]# docker stop MyWordPress && docker stop db
MyWordPress
db

Step 3:创建docker-compose配置文件~/wordpress/docker-compose.yml

[root@localhost ~]# cat << EOF > ~/wordpress/docker-compose.yml
> wordpress:  
>  image: wordpress  
>  links:    
>   - db:mysql  
>  ports:    
>   - 8080:80
> db:  
>  image: mariadb  
>  environment:    
>   MYSQL_ROOT_PASSWORD: example
> EOF

Step 4:进入配置文件所在目录,使用docker-compose以后台方式创建并启动容器

[root@localhost ~]# cd ~/wordpress/ && docker-compose up -d
Creating wordpress_db_1        ... done
Creating wordpress_db_1        ... 
Creating wordpress_wordpress_1 ... done

Step 5:容器启动成功后再次查看运行中的容器,使用了新的CONTAINER ID创建了新的容器,并且已自动命名

[root@localhost wordpress]# docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                  NAMES
06a518aaae16        wordpress           "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        0.0.0.0:8080->80/tcp   wordpress_wordpress_1
e429a99ad973        mariadb             "docker-entrypoint.s…"   2 minutes ago       Up 2 minutes        3306/tcp               wordpress_db_1

3.Docker Compose相关命令

3.1 创建并启动一组容器
# 当前所在目录为默认配置文件docker-compose.yml所在目录
docker-compose up -d
# 使用指定配置文件作为Docker Compose配置文件
docker-compose -f xxx.yml up -d
3.2 停止一组容器
docker-compose -f xxx.yml stop
3.3 启动一组容器
docker-compose -f xxx.yml start
3.4 查看指定项目的所有容器状态
docker-compose -f xxx.yml ps
3.5 删除项目
docker-compose -f xxx.yml down

4.Docker Compose配置文件

Docker Compose默认使用docker-compose.yml作为配置文件,执行docker-compose命令时,当前所在目录需要与docker-compose.yml所在目录一致;
如果自定义配置文件,则不需要在配置文件所在目录下执行docker-compose命令,但是需要使用-f xxx.yml指定配置文件。

Docker Compose配置文件使用YMAL语法定义了一组关联的应用容器,详细的参数和属性与运行docker run命令时的选项和参数基本一致,只是以不同的形式描述而已。

5.Docker Compose实现水平扩展和负载均衡

这里以一个简单的flask应用为例,请求/将返回当前运行flask应用的容器的hostname。

1.使用Pipenv创建虚拟环境,并创建一个最简单的flask应用。

app.py

from flask import Flask
import socket

app = Flask(__name__)


@app.route('/')
def hello():
    return 'Hello, my hostname is {}\n'.format(socket.gethostname())


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=80, debug=False)

2.编写构建应用镜像的Dockerfile

FROM python:3.7
ADD flask-demo /app/flask-demo
WORKDIR /app/flask-demo/
ENV FLASK_APP="app.py"
RUN pip install pipenv
RUN pipenv install
EXPOSE 80
CMD pipenv run python app.py

3.编写docker-compose配置文件,其中lb为haproxy,用于处理请求转发

docker-compose.yml

version: "3"
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile

  lb:
    image: dockercloud/haproxy
    links:
      - web
    ports:
      - 9090:80
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

4.使用docker-compose启动应用

docker-compose up -d

使用curl访问http://localhost:80,返回结果如下

$ curl http://localhost:9090
Hello, my hostname is c4374b73e405

5.使用docker-compose的--scale选项指定容器的数量

$ docker-compose up --scale web=3 -d
Starting docker-compose-scale_web_1 ... done
Creating docker-compose-scale_web_2 ... done
Creating docker-compose-scale_web_3 ... done
docker-compose-scale_lb_1 is up-to-date

多次请求将被转发轮询到各个应用容器中

$ curl http://localhost:9090
Hello, my hostname is c4374b73e405
$ curl http://localhost:9090
Hello, my hostname is e9b3416512f3
$ curl http://localhost:9090
Hello, my hostname is 130939b91e36

并且后续可以继续通过--scale增减应用的容器数量实现扩容或缩容。