目录

Life in Flow

知不知,尚矣;不知知,病矣。
不知不知,殆矣。

X

Docker Compose多容器部署

多容器的APP的痛点

  • 要从Dockerfile build image或者Dockerhub拉取iage
  • 要创建多个container
  • 要管理这些container(启动停止删除)
  • 一个应用可能由多个容器之间相互配合完成,追个容器进行管理成本高,将多个容器定义为一个组,对组进行统一的管理。
  • 微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。

Docker Compose简介

Docker Compose批处理
 使用 Docker Compose 可以轻松、高效的管理容器,它是一个用于定义和运行多容器 Docker 的应用程序工具。

  • Docker Compose是一个工具。
  • 这个工具可以通过yml文件定义多容器的docker APP。
  • 通过一条命令就可以根据yml文件的定义去创建或管理多容器。

yml概念

yml概念

Services

  • 一个service代表一个container,这个container可以从dockerhub的image创建而来,或是从本地的Dockerfile build构建的image创建而来。
  • Service的启动类似docker run,我们可以给其指定network和volume,所以可以给service指定network和Volume的引用。

docker-compose.yml

version: '3'

services:

  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: mysql
      WORDPRESS_DB_PASSWORD: root
    networks:
      - my-bridge

  mysql:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: wordpress
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - my-bridge

volumes:
  mysql-data:

networks:
  my-bridge:
    driver: bridge

docker compose

linux下需要单独安装docker compose,windows和mac不需要。

curl -L https://github.com/docker/compose/releases/download/1.7.0/docker-compose-`uname -s `-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

常用命令

[root@localhost docker-compose]# pwd
/docker/docker-compose
[root@localhost docker-compose]# ls /docker/docker-compose/
docker-compose.yml
[root@localhost docker-compose]# docker-compose -f docker-compose.yml up
# 也可以缺省为:启动当前目录下docker-compose文件中定义的容器
[root@localhost docker-compose]# docker-compose up
# 后台执行:平时用的比较多
[root@localhost docker-compose]# docker-compose up -d 

# 查看当前目录下docker-compose文件中定义的容器运行状态
[root@localhost docker-compose]# docker-compose ps

# 停止容器组
[root@localhost docker-compose]# docker-compose stop

# 停止容器组,并删除容器、networks、volumes
[root@localhost docker-compose]# docker-compose down

# 列举出docker-compose.yml中所定义的container及它使用的image
[root@localhost docker-compose]# docker-compose images

# 进入容器后面跟着docker-compose.yml中定义的service
[root@localhost docker-compose]# docker-compose exec mysql bash
[root@localhost docker-compose]# docker-compose exec wordpress bash

docker-compose快速上手

编写一个最简单的docker-compose.yml

version: '3'
services:
  redis:
    image: mycentos:redis

compose相关操作
 操作docker-compose一定要在配置文件docker-compose.yml文件路径下操作。

# 后台启动容器
[root@master docker-compose]# docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_redis_1 ... done
[root@master docker-compose]# docker ps | grep redis
ed82c76ba738        mycentos:redis         "/bin/sh -c '/usr/lo…"   24 seconds ago      Up 23 seconds                                           docker-compose_redis_1

# 查看容器
[root@master docker-compose]# docker-compose ps
         Name                       Command               State   Ports
-----------------------------------------------------------------------
docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Up  

# 进入容器
[root@master docker-compose]# docker-compose exec redis bash
[root@ed82c76ba738 /]# 

# 停止容器
[root@master docker-compose]# docker-compose stop
Stopping docker-compose_redis_1 ... done
[root@master docker-compose]# docker-compose ps
         Name                       Command               State    Ports
------------------------------------------------------------------------
docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Exit 0   

# 启动容器
[root@master docker-compose]# docker-compose start
Starting redis ... done
[root@master docker-compose]# docker-compose ps
         Name                       Command               State   Ports
-----------------------------------------------------------------------
docker-compose_redis_1   /bin/sh -c /usr/local/redi ...   Up   

# 删除容器
[root@master docker-compose]# docker-compose down
Stopping docker-compose_redis_1 ... done
Removing docker-compose_redis_1 ... done
Removing network docker-compose_default

# 删除容器并且删除volumes
[root@master docker-compose]# docker-compose down --volumes

docker-compose参考案例

 docker-compose.yml分为三大部分:version、services、networks。通过编写docker-compose.yml文件可以设置网络模式、端口映射、文件共享、同时管理多个容器。
docker-compose.yml

version: '3'
services:
  nginx:
    image: mycentos:nginx
    network_mode: "host"
    volumes:
    - /docker/nginx/html:/usr/local/nginx/html
    - /docker/nginx/logs:/usr/local/nginx/logs
    command: /usr/local/nginx/sbin/nginx -g "daemon off;"
  redis:
    image: mycentos:redis
    ports:
    - "6380:6379"

启动

[root@master docker-compose]# docker-compose up -d
Creating network "docker-compose_default" with the default driver
Creating docker-compose_nginx_1 ... done
Creating docker-compose_redis_1 ... done

docker-compose搭建个人博客wordpress

docker-compose.yml

version: '3.3'
services:
   db:
     image: mysql:5.7
     volumes:
       - db_data:/var/lib/mysql  # 采用的是卷标的形式挂载(注意:- db_data是参数,可以变,自 定义,必须与下面对应)
     restart: always  # 自动重启,保证服务在线
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress # 数据库远程连接的密码
       MYSQL_DATABASE: wordpress  # 数据库名称
       MYSQL_USER: wordpress	# 用户名称
       MYSQL_PASSWORD: wordpress	# 用户密码

   wordpress:
     depends_on:	#只有容器db(mysql)成功启动之后,才可以运行wordpress容器,并且等同于 --link 的功能
       - db
     image: wordpress:latest
     ports:
       - "8000:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress
volumes:
    db_data: {}

如何查看容器自定义的volumes

# 查看所有卷
[root@master docker-compose]# docker volume ls

# 查看具体卷的信息
[root@master docker-compose]# docker volume inspect wordpress_db_data  | grep "Mountpoint"
此宿主机路径挂载至容器内/var/lib/mysql

使用docker compose构建flask app

访问:http://192.168.31.220:8080

# Dockerfile 
[root@localhost flask-redis]# cat Dockerfile 
FROM python:2.7
LABEL maintaner="xxx"
COPY . /app
WORKDIR /app
RUN pip install flask redis
 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
EXPOSE 5000

# docker-compose.yml 
[root@localhost flask-redis]# cat docker-compose.yml 
version: "3"
services:

  redis:
    image: redis

  web:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 8080:5000
    environment:
      REDIS_HOST: redis

# app.py 
[root@localhost flask-redis]# cat app.py 
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())

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

# 启动容器组
[root@localhost flask-redis]# docker-compose  up

水平扩展和负载均衡之Scale

Scale
 假设启动3个web(servbice)作为负载均衡

  • scale只能在单机对容器进行扩容/缩容,如果单机的资源有上限,需要将同一个容器扩容并运行在不同的Docker节点上,需要使用swarm。
[root@localhost lb-scale]# pwd
/docker/docker-compose/lb-scale

# docker-compose.yml 
[root@localhost lb-scale]# cat docker-compose.yml 
version: "3"

services:

  redis:
    image: redis

  web:
    build:
      context: .
      dockerfile: Dockerfile
    environment:
      REDIS_HOST: redis

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

# Dockerfile 
[root@localhost lb-scale]# cat Dockerfile 
FROM python:2.7
LABEL maintaner="xxx"
COPY . /app
WORKDIR /app
RUN pip install flask redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
EXPOSE 80

# app.py 
[root@localhost lb-scale]# cat app.py 
from flask import Flask
from redis import Redis
import os
import socket

app = Flask(__name__)
redis = Redis(host=os.environ.get('REDIS_HOST', '127.0.0.1'), port=6379)

@app.route('/')
def hello():
    redis.incr('hits')
    return 'Hello Container World! I have been seen %s times and my hostname is %s.\n' % (redis.get('hits'),socket.gethostname())

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

# 启动容器组
[root@localhost lb-scale]# docker-compose up

# 查看容器组中各容器状态
[root@localhost lb-scale]# docker-compose ps
      Name                    Command               State                    Ports                 
--------------------------------------------------------------------------------------
lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                               
lb-scale_web_1     python app.py                    Up      80/tcp   

# 访问发现此时 hostname是 9b57020bdd3c.
  是web的hostname
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 9 times and my hostname is 9b57020bdd3c.

# 验证hostname
[root@localhost lb-scale]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                     NAMES
0cae2375e720        dockercloud/haproxy   "/sbin/tini -- docke…"   3 minutes ago       Up 3 minutes        443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp   lb-scale_lb_1
f64a9093ba45        redis                 "docker-entrypoint.s…"   3 minutes ago       Up 3 minutes        6379/tcp                                  lb-scale_redis_1
9b57020bdd3c        lb-scale_web          "python app.py"          3 minutes ago       Up 3 minutes        80/tcp                                    lb-scale_web_1

# 使用scale做水平扩展:web 容器的数量。
[root@localhost lb-scale]# docker-compose up --scale web=5 -d 
Starting lb-scale_web_1 ... done
lb-scale_redis_1 is up-to-date
Creating lb-scale_web_2 ... done
Creating lb-scale_web_3 ... done
Creating lb-scale_web_4 ... done
Creating lb-scale_web_5 ... done
lb-scale_lb_1 is up-to-date

# 验证
[root@localhost lb-scale]# docker-compose ps
      Name                    Command               State                    Ports                 
--------------------------------------------------------------------------------------
lb-scale_lb_1      /sbin/tini -- dockercloud- ...   Up      1936/tcp, 443/tcp, 0.0.0.0:8080->80/tcp
lb-scale_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp                               
lb-scale_web_1     python app.py                    Up      80/tcp                                 
lb-scale_web_2     python app.py                    Up      80/tcp                                 
lb-scale_web_3     python app.py                    Up      80/tcp                                 
lb-scale_web_4     python app.py                    Up      80/tcp                                 
lb-scale_web_5     python app.py                    Up      80/tcp  

[root@localhost lb-scale]# docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED              STATUS              PORTS                                     NAMES
2d3206abc32e        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_3
08114069ebb6        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_2
2ad3c66ab1e3        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_5
3edd57819130        lb-scale_web          "python app.py"          About a minute ago   Up About a minute   80/tcp                                    lb-scale_web_4
0cae2375e720        dockercloud/haproxy   "/sbin/tini -- docke…"   9 minutes ago        Up 9 minutes        443/tcp, 1936/tcp, 0.0.0.0:8080->80/tcp   lb-scale_lb_1
f64a9093ba45        redis                 "docker-entrypoint.s…"   9 minutes ago        Up 9 minutes        6379/tcp                                  lb-scale_redis_1
9b57020bdd3c        lb-scale_web          "python app.py"          9 minutes ago        Up 9 minutes        80/tcp                                    lb-scale_web_1

# 再次访问,发现第六次6次访问的hostname和第一次的一致,可判断Haproxy访问web的方式为轮询。
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 10 times and my hostname is 9b57020bdd3c.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 11 times and my hostname is 08114069ebb6.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 12 times and my hostname is 2d3206abc32e.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 13 times and my hostname is 3edd57819130.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 14 times and my hostname is 2ad3c66ab1e3.
[root@localhost lb-scale]# curl 127.0.0.1:8080
Hello Container World! I have been seen 15 times and my hostname is 9b57020bdd3c.

# 服务缩容(修改容器名称后面的数量即可)
[root@localhost lb-scale]# docker-compose up --scale web=3 -d 

docker compose部署投票系统

投票系统架构图

  • Voting App采用python,接收前端用户投票输入操作,并写入redis。
  • Java worker采用java,读取redis中数据写入数据库。
  • Result App采用Node.js,实时从数据库中拉取数据展示给前端用户。

投票系统源码


作者:Soulboy