Bootstrap

Docker Compose 编排技术

Docker Compose

Compose 编排基础

Docker Compose 非常适合组合使用多个容器部署

架构

以前

使用 docker run 等命令来完成容器的管理,一旦参数过多,就比较费时费力,容易出错

Docker Compose 将所有容器参数通过精简的配置文件(Compose 文件)来定义,通过命令 docker-compose 命令管理配置文件,完成容器的部署,从而解决复杂应用程序的问题

三个层次

管理的对象从上到下依次:

  • 项目(Project):又称为工程,代表实现的一个应用程序,由一组关联的容器组成一个完整的业务单元,可以包含一个或者多个服务
  • 服务(Service):代表着需要实现的一个子应用程序,以容器形式来完成任务,一个服务运行一个镜像
  • 容器(Container):每个服务又以多个容器实列的形式运行,多个容器实例指的是服务的副本,可以通过修改副本数量来扩展服务

docker-py 是一个使用 python 语言开发并调用 DockerAPI 的软件包,不管前面如何,最终都会落实到 docker 引擎对容器的管理与部署上

在这里插入图片描述

使用步骤
  1. Dockerfile 定义应用程序环境
  2. docker-compose.yml 文件定义组成应用程序的各个服务(默认配置文件,一个文件作为一个单独的项目,会创建一个独立的网络,让其中的若干容器在隔离的环境中一起运行)
  3. 启动整个应用程序:docker-compose up
特性
  1. 单主机上建立多个隔离环境,它会使用项目名称来隔离彼此的环境,默认项目名称是项目目录的基本名称,也可以使用命令行 -p 或者环境变量 COMPOSE_PROJECT_NAME 来设置自定义的项目名称
  2. 创建容器的时候保留卷数据,它会保留服务所使用的所有卷
  3. 仅重建已更改的容器
  4. 不同环境定制编排
场景
  • 开发环境
  • 自动化测试环境
  • 单主机部署
安装
  • 依赖 docker 引擎才能正常工作,所以需要先安装 docker 引擎

官方安装参考地址:安装 Compose 独立版 |Docker 文档

### 插件方式安装的查看方式
docker compose version

在这里插入图片描述

示例
  1. 创建项目目录:mkdir project-demo ; cd project-demo
  2. 创建源码文件
cat >app.py <<EOF
import time

import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
    retries = 5
    while True:
        try:
            return cache.incr('hits')
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)

@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I have been seen {} times.\n'.format(count)
EOF

  1. 创建依赖文件
cat >requirements.txt <<EOF
flask
redis
EOF

  1. 创建 Dockerfile 文件
cat >Dockerfile <<EOF
FROM python:3.7-alpine
WORKDIR /code
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0
RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt
EXPOSE 5000
COPY . .
CMD ["flask", "run"]
EOF

  1. 定义 docker-compose.yml 文件
cat >docker-compose.yml <<EOF
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"
EOF

  1. 使用 docker compose up 构建并运行应用
docker compose up

过程

在这里插入图片描述

  1. 命令行访问8000验证程序

在这里插入图片描述

在这里插入图片描述

Compose 文件详解

Compose 文件是 Docker Compose 项目的主配置文件,又称 Compose 模板文件

  • 定义整个应用程序:服务、网络、卷
  • 文本文件或者 YAML 格式,后缀可以是 .yml 或者 .yaml
  • 默认文件名:docker-compose.yml
文件格式版本

三个版本

传统格式

版本2.x:文件的首部来表示(version: ‘2’)

版本3.x:文件的首部来表示(version: '3)

  • 现在多用 3.x 版本,要求docker 1.13.0 以上
  • 差异性表现:可用配置项、docker 引擎最低版本、网络有关的行为
文件结构

标准文件的4个顶级部分

  • version:定义版本号,没有下级字段
  • services:定义服务,由下级字段定义
  • networks:定义网络,由下级字段定义
  • volumes:定义存储和卷,由下级字段定义

示例文件

version: '3'			## 定义版本号
services:				## 定义服务的部分
  web:					## 定义第一个服务名称
    build: .			## 定义服务构建方法
    ports:				## 定义端口映射
      - "8000:5000"
  redis:				## 定义第二个服务名称
    image: "redis:alpine"	## 定义使用的镜像
networks:			## 定义网络
  frontend:
volumes:				## 定义存储
  logvolumes01: {}

简单格式说明

  • 缩进只能空格,不能 TAB
  • 冒号与后面的参数之间需要一个空格
services 定义
  • 定义若干服务,每个服务就是一个容器,容器是基于镜像运行的,所以必须使用 image 或者 build 字段来提供镜像,其他字段可选

image

指定用于启动容器的镜像,可以是镜像名称或者镜像ID,如果镜像本地不存在,就会根据镜像的信息从远程注册中心进行拉取

build

定义构建镜像的配置,可以定义包括构建上下文路径的字符,如果同时指定 image,那么就会根据 build 构建镜像并且构建出来的镜像命名为定义的 image 名称

build: ./dir

###
build:
  context: ./dir		### 定义构建上下文,可以是包含dockerfile的目录,或者访问仓库的URL
  dockerfile: xxxxx		### 定义 Dockerfile 文件
  args:					### 指定构建参数,构建阶段访问的环境变量
    name: whale

command

覆盖容器启动后默认执行的命令

depends_on

定义服务之间的依赖,解决容器的依赖、启动的先后顺序问题

services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: mysql

docker compose up 会按照依赖顺序启动服务

docker compose up web 启动web,会一同启动依赖

docker compose stop 先停止web,后停止依赖

entrypoint

覆盖容器的默认入口设置,清除镜像上的任何默认命令,也包括 CMD

env_file

从文件中加载环境变量

env_file: .env

###
env_file:
  - ./xxx.env
  - ./yyy.env
  - ./zzz.env

environment

添加环境变量,数组或者字典形式,布尔值或者逻辑值需要使用引号

environment:
    name: whale
    age: 18
    
###
environment:
  - name=whale
  - age=18

expose

定义用于暴露没有发布到主机的端口,只允许被连接的服务访问,仅可以指定内部端口

expose:
  - "9090"

external_links

用来连接未在 docker-compose.yml 文件中定义,甚至非compose管理的容器

external_links:
  - redis
  - mysql
  - db2

network_mode

指定网络模式,与–network 选项类似

network_mode: "bridage"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

networks

指定要加入的网络(networks 部分定义的网络)

networks:
  - mynet

ports

指定要暴露的端口

ports:
  - "9090"
  - "9090:22"
  
  ### 多个字段定义端口
  ports:
    - target: 80
      published: 8080
      protocol: tcp
      mode: host

volumes

与 volumes 部分定义卷存储不同的是,这个地方是用来定义挂载的主机路径或命名卷

  • 挂载主机路径作为单个服务定义的一部分,不用再后续的部分中定义这个卷
  • 如果多个服务之间重用一个卷,后续的部分中要定义这个卷,然后再这里引用
version: "3"
services:
  web:
    image: myweb
    volumes:
      - type: volume
        source: mydata
        targetL /data
        volume:
          nocopy: "true"
      - type: bind
        source: /static
        target: /opt/static
  db:
    image: mysql
    volumes:
      - "/data/mysql:/var/lib/mysql"
volumes:
  mydata

restart

定义容器重启策略,默认设置是 no,任何情况不会重启容器

  • akways:总是重新启动
  • no-failure:退出代码指示故障错误,将重启容器
volumes 定义

不同于 services 下面的 volumes,这里是单独创建命名卷,能在多个服务之间重用

### 条目可以为空,就会使用 Docker 配置的默认存储驱动
volumes:
  mydata:
  
### 也可以进行字段配置
driver: local			### 定义卷的卷驱动,多数情况下 local 本地
driver_opts:			### 传递给卷的驱动,取决于卷驱动的本身
  foo:
  baz:

### 外部创建,如果为true,docker compose 不会去尝试创建它,如果不存在就会报错
volumes:
  data:
    external: true
networks 定义

1.0 版本不支持网络配置,只有 2.0以上才支持

默认网络配置

root@VM-16-4-ubuntu:~/project-demo# cat docker-compose.yml
services:
  web:
    build: .
    ports:
      - "8000:5000"
  redis:
    image: "redis:alpine"

在这里插入图片描述

  • 创建为名 目录名_default 的网络
  • 创建使用 web 的容器,并加入在 web 名下的【目录名_default】网络
  • 创建使用 redis的容器,并加入在 redis名下的【目录名_default】网络

更改默认网络的配置

networks:
  default:
    driver: xxxxx  ### 使用自定义驱动

指定自定义网络

  • 可以创建更复杂的拓扑
  • 自定义网络驱动和选项
  • 将服务连接到不由 compose 管理的外部创建的网络中
services:
  web:
    build: .
    ports:
      - "8000:5000"
    networks:
      - frontend
networks:
  frontend:
    driver: xxxxxxxxx

使用现有网络

networks:
  default:
    external:
      name: xxxxxxxxx

在这里插入图片描述

Compose 命令行

命令行格式
docker compose [-f <arg>...] [options] [conmand] [args...]
  • -f 指定多个文件,会按照顺序组合到一个单一的配置中,后面的 compose 文件将覆盖和追加到前面的 compose 文件中(感觉不太好用,比喜欢用)

  • 其他选项

    • -p :指定项目名称,默认当前目录作为项目名称
    • –verbose:输出更多调试信息
    • –log-level:设置日志级别
    • -v:显示版本信息
    • -h:帮助
    • –project-directory:指定项目名称,默认是Compose文件所在路径

    在这里插入图片描述

常见命令

dockers compose build

构建或重新构建服务并设置标签,(不太习惯这种使用方法)

  • –no-cache:不使用缓存
  • –pull 总是拉取最新版本镜像
  • –build-arg key=value 构建时的变量

docker compose start

启动运行指定服务的已存在的容器

docker compose stop

停止指定服务的所有容器

docker compose pause

暂停指定服务的容器

docker compose unpause

恢复指定服务已处于暂停状态的容器

docker compose kill

通过发送SIGKILL信号来强制终止正在运行的容器,也可以 -s SIGINT 发送其他信号

docker compose up

最常用,用于构建、创建、启动和连接指定的服务容器,所有连接的服务都会启动,除非他们已经运行

  • -d:后台运行,输出容器名称
  • –quiet-pull:拉取镜像不会输出进程信息
  • –no-start:创建服务后不启动他们
  • –build:启动容器之间构建镜像

docker compose run

为服务运行一次性的命令

docker compose ps

查看服务中当前运行的容器,如果不指定 -p ,会以当前目录作为项目名称去查询

docker compose down

停止容器并删除由它创建的容器、网络、卷和镜像

docker compose rm

删除所有处于停止状态的服务容器,可以使用 -f 进行强制删除

docker compose config

验证和查看 Compose 文件

Compose 环境变量

多种使用方法
  1. 替换文件中的环境变量:shell 环境中的变量会被找到并替换
  2. 设置容器中的环境变量:environment 字段
  3. shell 环境变量也可传递给容器,不赋值即可将 shell 中的环境变量传递给服务的容器
  4. env_file 字段传递
  5. docker compose run -e 设置
环境变量优先级
  1. 优先级最高:compose 文件中定义
  2. 当前 shell 中的环境变量值(可使用 export 定义)
  3. 环境文件
  4. Dockerfile

Compose 编排示例

负载均衡示例

示例由4个容器组成,1个haproxy容器充当负载均衡服务,另外3个nginx充当web页面

cd /opt/software
mkdir test ; cd test
mkdir haproxy web1 web2 web3
### haproxy.cfg
cat >./haproxy/haproxy.cfg <<EOF
global
  log 127.0.0.1 local0
  log 127.0.0.1 local1 notice
defaults
  log global
  mode http
  option httplog
  timeout connect 5000ms
  timeout client 50000ms
  timeout server 50000ms
  stats uri /status
frontend balancer
  bind 0.0.0.0:80
  default_backend web_backends
backend web_backends
  balance roundrobin
  server web1 web1:80 check
  server web2 web2:80 check
  server web3 web3:80 check
EOF

### web1的index.html
cat >./web1/index.html <<EOF
web1
EOF

### web2的index.html
cat >./web2/index.html <<EOF
web2
EOF
### web33的index.html
cat >./web3/index.html <<EOF
web3
EOF

定义 compose 文件

cat >docker-compose.yml <<EOF
version: "3.5"
services:
  web1:
    image: nginx
    expose:
      - "80"
    volumes:
      - ./web1/index.html:/usr/share/nginx/html/index.html
  web2:
    image: nginx
    expose:
      - "80"
    volumes:
      - ./web2/index.html:/usr/share/nginx/html/index.html
  web3:
    image: nginx
    expose:
      - "80"
    volumes:
      - ./web3/index.html:/usr/share/nginx/html/index.html
  haproxy:
    image: haproxy
    ports:
      - "80:80"
    volumes:
      - ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
networks:
  default:
    external:
      name: mynet
EOF

在这里插入图片描述

运行

在这里插入图片描述

验证

在这里插入图片描述

在这里插入图片描述

;