「docker」学习笔记 | 容器编排之Docker Compose

why docker-compose?

为什么需要用到编排工具?

当我们的业务越来越复杂时,需要多个容器相互配合,甚至需要多个主机组成容器集群才能满足我们的业务需求,这个时候就需要用到容器的编排工具了。Docker三种常用的编排工具:Docker Compose、Docker Swarm和Kubernetes。了解这些编排工具,可以让你在不同的环境中选择最优的编排框架。

容器编排工具的优点

  1. 批量地创建、调度和管理容器,帮助我们解决容器的部署问题。

Docker Compose 的前世今生

WechatIMG379(已去底)

Docker Compose 项目是Docker官方的开源项目,负责实现对 Docker 容器集群的快速编排。

Docker Compose 的前身是 Orchard 公司开发的 Fig,2014 年 Docker 收购了 Orchard 公司,然后将 Fig 重命名为 Docker Compose。现阶段 Docker Compose 是 Docker 官方的单机多容器管理系统,它本质是一个 Python 脚本,它通过解析用户编写的 yaml 文件,调用 Docker API 实现动态的创建和管理多个容器。

Linux系统下安装Docker Compose

macOS 系统下通常以Docker桌面版本的形式安装 docker,桌面版安装之后就默认已安装了docker compose。下面介绍其他 Linux 系统下的安装流程:

  1. 使用 curl 命令(一种发送 http 请求的命令行工具)下载 Docker Compose 的安装包:

    sudo curl -L "https://github.com/docker/compose/releases/download/1.27.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
    
  2. 修改 Docker Compose 执行权限:

    sudo chmod +x /usr/local/bin/docker-compose
    
  3. 检查 Docker Compose 是否安装成功:

    docker-compose --version # docker-compose version 1.27.3, build 4092ae5d
    

Docker Compose 模板文件的介绍

在使用 Docker Compose 之前,我们首先需要先编写 Docker Compose 模板文件,因为 Docker Compose 运行的时候是根据 Docker Compose 模板文件中的定义来运行的。

在使用 Docker Compose 启动容器时, Docker Compose 会默认使用docker-compose.yml 文件, docker-compose.yml 文件的格式为 yaml(类似于 json,一种标记语言)。

Docker Compose 文件主要分为三部分: services(服务)、networks(网络) 和 volumes(数据卷)。

  • services(服务):服务定义了容器启动的各项配置,就像我们执行docker run命令时传递的容器启动的参数一样,指定了容器应该如何启动,例如容器的启动参数,容器的镜像和环境变量等。
  • networks(网络):网络定义了容器的网络配置,就像我们执行docker network create命令创建网络配置一样。
  • volumes(数据卷):数据卷定义了容器的卷配置,就像我们执行docker volume create命令创建数据卷一样。

docker-compose.yaml/各个参数之间的层级关系图-By Billie/

1. version

Docker Compose 模板文件一共有三个版本: v1、v2 和 v3。目前最新的版本为 v3,也是功能最全面的一个版本。

2. services

services下,首先需要定义服务名称,例如nginx服务,便可以命名为nginx,格式如下

version: "3"
services:
	nginx:
		...
  • images - 指定容器镜像的地址

  • volumes - 不仅可以挂载主机数据卷到容器中,也可以直接挂载主机的目录到容器中,使用方式类似于使用docker run启动容器时添加-v参数

  • networks - 这是服务要使用的网络名称,对应顶级的networks中的配置

  • build - 用于构建docker镜像,类似于docker build命令,build可以指定Dockerfile文件路径,然后根据Dockerfile命令来构建文件

  • cap_add \ cap_drop - 指定容器可以使用到哪些内核能力(capabilities)

  • command - 用于覆盖容器默认的启动命令,和Dockerfile中的CMD用法类似

  • container_name - 用于指定容器启动时容器的名称

  • depends_on - 用于指定服务间的依赖关系,这样可以先启动被依赖的服务,例如,我们的服务依赖数据库服务 db,可以指定 depends_on 为 db

  • devices - 挂载主机的设备到容器中

  • dns - 自定义容器中的dns配置

  • dns_search - 配置dns的搜索域

  • entrypoint - 覆盖容器的entrypoint命令

  • env_file - 指定容器的 环境变量文件,启动时会把文件中的环境变量值注入容器中

  • environment - 指定容器启动时的环境变量

  • pid - 共享主机的进程命名空间,像在主机上的直接启动进程一样,可以看到主机的进程信息

  • ports - 暴露端口信息,使用格式为HOST:CONTAINER,前面填写要映射到主机上的端口,后面填写对应的容器内的端口

3. volumes

如果你想在多个容器间共享数据卷,则需要在外部声明数据卷,然后在容器里声明使用数据卷。例如我想在两个服务间共享日志目录,则使用以下配置:

version: "3"

services:
  my-service1:
    image: service:v1
    volumes:
      - type: volume
        source: logdata
        target: /var/log/mylog
  my-service2:
    image: service:v2
    volumes:
      - type: volume
        source: logdata
        target: /var/log/mylog

volumes:
  logdata:

4. netwoks

Docker Compose 文件顶级声明的 networks 允许你创建自定义的网络,类似于docker network create命令。

例如你想声明一个自定义 bridge 网络配置,并且在服务中使用它,使用格式如下:

version: "3"

services:
  web:
    networks:
      mybridge: 
        ipv4_address: 172.16.1.11

networks:
  mybridge:
    driver: bridge
    ipam: 
      driver: default
      config:
        subnet: 172.16.1.0/24

编写 Docker Compose 模板文件

1. command指令

方式1: /bin/bash -c 字符串方式

command: /bin/bash -c "uwsgi --ini ./web_flask/uwsgi.ini && python3 run.py"

在这个示例中,sh -c允许您在一个命令中执行多个命令。&&符号表示仅在第一个命令成功执行后才执行第二个命令。

多条命令之间使用&&符号连接,并且此方式为串行运行,后一条命令需等前一条命令结束之后才会执行。

方式2: /bin/bash -c 配置文件方式

  • 串行

    command:
        - sh
        - -c 
        - 
            cmd1
            cmd2
            cmd3
    

    如上配置会按顺序执行cmd1,之后再执行cmd2,之后cmd3。对于可以串行的命令,这样即可。

  • 并行

    有时候想配置几个常驻脚本在docker,希望这几个 脚本一起跑起来(并行运行)

    command:
        - sh
        - -c 
        - 
            cmd1 &
            cmd2 &
            cmd3
    

    上面cmd 都是要求常驻的,没有顺序要求,那么在命令中,前面的几个都加上&,最后一个命令不加,也就是前面几个扔后台运行,最后一个直接运行,使得docker 和最后一个cmd 一样“生命周期”,这样就做到几个cmd 并行运行了。

    如果每条命令结尾都加上&,其实是不正确的,docker 运行起来,就马上结束了。猜测是像程序开发的开多线程一样,“主线程开了线程,不等线程,自己就退出了,由于主线程退出,进程也跟着退出了,导致一个线程都没有跑起来”。

2. restart指令

代码示例:

version: '3'
services: 
  redis-server:
    image: 'redis'
  node-app:
    restart: unless-stopped
    build: .
    ports: 
      - "4001:8081"
  • - restart: 'no',这意味着如果容器停止或崩溃,永远不要尝试重新启动容器。记得给单引号'no'因为在 yaml 文件中,如果我们给no不带引号,它会被视为 false。
  • 总是 - restart: always,如果我们的容器因任何原因停止,请始终尝试重新启动停止的容器。
  • 故障 - restart: on-failure,仅当容器因错误代码停止时才重新启动。
  • 除非停止 - restart: unless-stopped ,除非开发人员强行停止该过程,否则始终重新启动。

docker-compose 操作命令

使用docker-compose -h命令用于查看 docker-compose 的用法,docker-compose 的基本使用格式如下:

docker-compose [-f <arg>...] [options] [--] [COMMAND] [ARGS...]

其中 options 是 docker-compose 的参数,支持的参数和功能说明如下:

-f, –file FILE 指定 docker-compose 文件,默认为 docker-compose.yml
-p, –project-name NAME 指定项目名称,默认使用当前目录名称作为项目名称
–verbose 输出调试信息
–log-level LEVEL 日志级别 (DEBUG, INFO, WARNING, ERROR, CRITICAL)
-v, –version 输出当前版本并退出
-H, –host HOST 指定要连接的 Docker 地址
–tls 启用 TLS 认证
–tlscacert CA_PATH TLS CA 证书路径
–tlscert CLIENT_CERT_PATH TLS 公钥证书问价
–tlskey TLS_KEY_PATH TLS 私钥证书文件
–tlsverify 使用 TLS 校验对端
–skip-hostname-check 不校验主机名
–project-directory PATH 指定工作目录,默认是 Compose 文件所在路径。

COMMAND 为 docker-compose 支持的命令。支持的命令如下:

build 构建服务
config 校验和查看 Compose 文件
create 创建服务
down 停止服务,并且删除相关资源
events 实时监控容器的时间信息
exec 在一个运行的容器中运行指定命令
help 获取帮助
images 列出镜像
kill 杀死容器
logs 查看容器输出
pause 暂停容器
port 打印容器端口所映射出的公共端口
ps 列出项目中的容器列表
pull 拉取服务中的所有镜像
push 推送服务中的所有镜像
restart 重启服务
rm 删除项目中已经停止的容器
run 在指定服务上运行一个命令
scale 设置服务运行的容器个数
start 启动服务
stop 停止服务
top 限制服务中正在运行中的进程信息
unpause 恢复暂停的容器
up 创建并且启动服务
version 打印版本信息并退出

编程

1. 在结束时执行指定任务

为了确保在容器停止时生成的静态文件是最新的,您可以使用trap命令在脚本中捕获SIGTERM信号。当Docker容器收到SIGTERM信号时,它将优雅地关闭并执行清理任务。

请按照以下步骤操作:

  1. 在您的项目目录中创建一个名为start.sh的脚本,并添加以下内容:
bashCopy code
#!/bin/sh

# 定义一个函数来处理SIGTERM信号
shutdown_handler() {
  echo "SIGTERM received, generating static files and stopping the server..."
  hugo -D
  pkill hugo
}

# 设置一个信号捕获器来监听SIGTERM信号
trap shutdown_handler SIGTERM

# 运行Hugo服务器
hugo server --bind 0.0.0.0 -w

# 等待所有子进程完成
wait
  1. start.sh脚本添加可执行权限。在项目目录中执行以下命令:
bashCopy code
chmod +x start.sh
  1. 修改您的docker-compose.yaml文件,以引用新创建的start.sh脚本。假设您的服务名称是your_service,则docker-compose.yaml文件应如下所示:
yamlCopy code
version: '3.8'
services:
  your_service:
    build: .
    ports:
      - "本地端口:容器端口"
    command: ./start.sh

现在,当您通过docker-compose down或类似命令停止容器时,shutdown_handler函数将捕获SIGTERM信号,生成静态文件,然后停止Hugo服务器。

结语

Docker Compose 是一个用来定义复杂应用的单机编排工具,通常用于服务依赖关系复杂的开发和测试环境,如果你还在为配置复杂的开发环境而烦恼,Docker Compose 可以轻松帮你搞定复杂的开发环境。你只需要把复杂的开发环境使用 Docker Compose 模板文件描述出来,之后无论你在哪里可以轻松的一键启动开发和测试环境,极大地提高了我们的开发效率,同时也避免了污染我们开发机器的配置。

推荐阅读

项目实践案例请参考:


3637 字