Docker 容器编排:Docker Compose 从入门到实战完整指南

Docker Compose(容器编排)

什么是Docker Compose

docker-compose是Docker官方的开源项目,使用python编写,实现上调用了Docker服务的API进行容器管理及编排,其官方定义为定义和运行多个Docker容器的应用。

docker-compose中两个重要概念:

  • 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义,整个docker-compose.yml定义一个项目。
  • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。

Compose的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。通过compose可以方便的管理多个服务。

为什么要Docker Compose

  • Docker是一个轻量化的应用程序,Docker官方推荐每个Docker容器中只运行一个进程。
  • 如果一个应用需要涉及到MySQL、nginx等环境,那么需要分别为应用、数据库和nginx创建单独的docker容器,然后分别启动容器。
  • 每次启动应用,都至少需要docker run三次或者一些脚本来实现,这样会比较繁琐。
  • 另外,这些docker容器都是分散独立的,也不方便镜像管理

Docker Compose的安装

安装docker的时候, 默认已经装了docker-compose,安装的组件名称为docker-compose-plugin。

# 检查安装是否成功
root@139-159-150-152:/data/myworkdir/compose# docker compose version
Docker Compose version v2.16.0

Docker Compose的功能

  1. 使用步骤

    • 使用docker-compose.yml定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
    • 最后,执行docker compose up命令来启动并运行整个应用程序。
  2. 核心功能
    Compose具有管理应用程序整个生命周期的命令:

    • 启动,停止和重建服务
    • 查看正在运行的服务的状态
    • 流式传输运行服务的日志输出
    • 在服务上运行一次性命令

Docker Compose使用场景

  • 单主机部署:快速搭建一个单节点开发者或者测试环境,方便使用。
  • 不同环境隔离:通过指定project来运行不同的环境,实现隔离的目的。

Docker Compose文件 (docker-compose.yml)

文件语法版本

目前官方支持三个大版本,即Version 1、Version 2及Version 3,其中Version 1已经被废弃掉了。
当前最新的版本是3.8,它支持的Docker Engine版本不得低于19.03.0。这里主要基于3.8版本的Compose file语法进行讲解,其他版本介绍参见官方文档。

Compose file formatDocker Engine release
3.819.03.0+
3.718.06.0+
3.618.02.0+
3.517.12.0+
3.417.09.0+
3.317.06.0+
3.217.04.0+
3.11.13.1+
3.01.13.0+
2.417.06.0+
2.317.06.0+

文件基本结构及常见指令

version: "3.8" # 定义版本,表示当前使用的docker-compose语法的版本

services: # 服务,可以存在多个
  servicename: # 服务名字,它也是内部bridge网络可以使用的 DNS name,如果不是集群模式相当于docker run 的时候指定的一个名称
    # 集群(swarm)模式下是多个容器的逻辑抽象
    command: # 可选,如果设置了,则会覆盖默认镜像里的CMD命令
    image: # 必选,镜像的名字,I则会根据镜像里的
    environment: # 可选,等价于 docker container run里的 --env 选项 设置环境变量
    volumes: # 可选,等价于 docker container run里的 -v 选项 绑定数据卷
    networks: # 可选,等价于 docker container run里的 --network 选项 指定网络
    ports: # 可选,等价于 docker container run里的 -p 选项指定端口映射
    expose: # 可选,指定容器暴露的端口
    build: # 构建目录,指定dockerfile的端口
    depends_on: # 服务的依赖配置
    env_file: # 环境变量文件

  service2:
    image:
    command:
    networks:
    ports:

  service3:
    ...

volumes: # 可选,等价于 docker volume create
networks: # 可选,等价于 docker network create

常见字段格式语法

image

指定容器运行的镜像。以下格式都可以:

image: redis
image: redis:5
image: ha256:0ed5d5928d4737458944eb604cc8509e245c3e19d02ad83935398bc4b991aac7
image: library/redis
image: docker.io/library/redis
image: my.private.registry:5000/redis
command

覆盖容器启动的默认命令。

command: ["bundle", "exec", "thin", "-p", "3000"]
command: bundle exec thin -p 3000
entrypoint

覆盖容器默认的entrypoint。

entrypoint: /code/entrypoint.sh

也可以是以下格式:

entrypoint:
  - php
  - -d
  - zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
  - -d
  - memory_limit=-1
  - vendor/bin/phpunit
environment

添加环境变量。可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保YML解析器不会将其转换为True或False。

  • map语法
environment:
  SHOW: 'true'
  USER_INPUT: development
  RACK_ENV: development
  • 数组语法
environment:
  - RACK_ENV=development
  - SHOW=true
  - USER_INPUT
networks

指定容器运行的网络:

  • 配置容器网络
services:
  frontend:
    image: awesome/webapp
    networks:
      - front-tier
      - back-tier

  monitoring:
    image: awesome/monitoring
    networks:
      - admin

  backend:
    image: awesome/backend
    networks:
      back-tier:
        aliases:
          - database
      admin:
        aliases:
          - mysql

networks:
  front-tier:
  back-tier:
  admin:
  • 配置网络驱动和子网信息
services:
  frontend:
    image: awesome/webapp
    networks:
      front-tier:
        ipv4_address: 172.16.238.10

networks:
  front-tier:
    ipam:
      driver: default
      config:
        - subnet: "172.16.238.0/24"
volumes

将主机的数据卷或者文件挂载到容器里。

  • 短语法:
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"
  • 完整语法:
services:
  backend:
    image: awesome/backend
    volumes:
      - type: volume
        source: dbdata
        target: /data
        volume:
          nocopy: true
      - type: bind
        source: ./var/run/postgres/postgres.sock
        target: /var/run/postgres/postgres.sock

volumes:
  dbdata:
ports

指定端口映射。以下格式都可以:

  • 短语法:
ports:
  - "3000"
  - "8979:80"
  - "127.0.0.1:8080:80"
  • 长语法:
ports:
  - target: 80
    published: 8080
    protocol: tcp
    mode: host
  - target: 8000-9000
    published: 8000-9000
    protocol: tcp
    mode: host
  • 端口语法:
ports:
  - "3000-3005"
  - "8000:8000"
  - "9090-9091:8080-8081"
  - "49100:22"
  - "127.0.0.1:8001:8001"
  - "127.0.0.1:5000-5010:5000-5010"
  - "6060:6060/udp"
expose

暴露端口,但不映射到宿主机,只被连接的服务访问。
仅可以指定内部端口为参数:

expose:
  - "3000"
  - "8000"
build

指定为构建镜像上下文路径:
例如webapp服务,指定为从上下文路径./dir/Dockerfile所构建的镜像。

version: "3.7"
services:
  webapp:
    build: ./dir

或者,作为具有在上下文指定的路径的对象,以及可选的Dockerfile和args:

version: "3.7"
services:
  webapp:
    build:
      context: ./dir
      dockerfile: Dockerfile-alternate
      args:
        buildno: 1
      labels:
        - "com.example.description=Accounting webapp"
        - "com.example.department=Finance"
        - "com.example.label-with-empty-value"
  • context:上下文路径,镜像的Dockerfile文件所在的文件夹
  • dockerfile:指定构建镜像的Dockerfile的文件名
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
depends_on

设置依赖关系:
docker compose up:以依赖性顺序启动服务。在示例中,先启动db和redis,才会启动web。
docker compose up SERVICE:自动包含SERVICE的依赖项。在以下示例中,docker compose up web也会创建并启动db和redis。
docker compose stop:按依赖关系顺序停止服务。在以下示例中,web在db和redis之前停止。

version: "3.7"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres

可以指定条件,方便的配置健康检查来完成:

services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
  redis:
    image: redis
  db:
    image: postgres
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

healthcheck样例:

services:
  web:
    image: nginx:1.24.0
    environment:
      TEST: 1
    ports:
      - 8979:80
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: "bit@123"
    volumes:
      - /data/maxhou/mysqldata/varlib/:/var/lib/mysql
    healthcheck:
      test: mysql -user=root --password='bit@123' -e "SELECT 1;"
      interval: 10s
      timeout: 5s
      retries: 10
  redis:
    image: redis:7
    healthcheck:
      test: redis-cli ping
      interval: 10s
      timeout: 5s
      retries: 10
env_file

从文件添加环境变量。可以是单个值或列表的多个值。

env_file: .env

也可以是列表格式:

env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env

Docker Compose命令

命令功能
docker compose build构建服务
docker compose config验证并查看compose文件配置
docker compose cp在本地和服务容器之间拷贝文件
docker compose create创建服务的容器
docker compose down停止并删除容器、网络、卷、镜像
docker compose events从服务器接收实时事件
docker compose exec在运行的容器中执行命令
docker compose images列出所有容器使用的镜像
docker compose kill强制停止服务的容器
docker compose logs显示日志
docker compose ls显示所有项目
docker compose pause暂停服务
docker compose port列出所有的端口映射
docker compose ps该命令可以列出项目中目前的所有容器
docker compose pull拉取服务镜像
docker compose push推送服务镜像
docker compose restart重启或者重启某个服务
docker compose rm删除服务停止的容器
docker compose run在指定服务器上执行相关的命令
docker compose start启动当前停止的某个容器
docker compose stop停止当前运行的某个容器
docker compose top显示运行的进程
docker compose unpause恢复服务
docker compose upup命令会构建,(重新)创建,启动,链接一个服务相关的容器。情况如下如果容器已经存在,将会停止并尝试重新创建他们。并使用之前挂载的卷。–no-recreate参数可以让容器不被停止或者重新创建,-d表示后台运行
docker compose version查看版本

命令格式

对于Compose来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或者容器。如果没有特别的说明,命令对象将是项目,这意味着项目中所有的服务都会受到命令影响。

docker-compose命令的基本的使用格式为

docker compose [OPTIONS] COMMAND [ARGS...]

常见选项说明

  • -f, --file 指定使用的Compose模板文件,默认为docker-compose.yml,可以多次指定
  • -p, --project-name 指定项目名称,默认将使用所在目录名称作为项目名

常见命令说明

up

该命令的作用十分强大,它会尝试自动完成包括构建镜像、(重新)创建服务、启动服务并关联服务相关容器的一系列操作,可以直接通过该命令来启动一个项目。

docker compose up [options] [SERVICE...]
  • -d 在后台运行服务容器,推荐在生产环境下使用该选项
  • --force-recreate 强制重新创建容器,不能与--no-recreate同时使用
  • --no-recreate 如果容器已经存在了,则不重新创建,不能与--force-recreate同时使用
down

停止所有容器,并删除容器和网络

docker compose down [options] [SERVICE...]
  • -v, --volumes 删除容器同时删除目录映射
run

该命令可以在指定服务器上执行相关的命令 (注意这里启动的是yml文件中配置好的服务,而不是镜像)

docker compose run [options] SERVICE [COMMAND] [ARGS...]
  • -d 后台运行容器
  • --name NAME 为容器指定一个名字
  • --entrypoint CMD 覆盖默认的容器启动指令
  • -e KEY=VAL 设置环境变量值,可多次使用选项来设置多个环境变量
  • -u, --user="" 指定运行容器的用户名或者uid
  • --rm 运行命令后自动删除容器
  • -p, --publish=[] 映射容器端口到本地主机
# 例如:启动一个 ubuntu 服务器容器,并执行 ping docker.com 命令
docker compose run ubuntu ping docker.com

操作案例

Docker Compose基本操作

  1. 创建compose目录
mkdir -p /data/myworkdir/compose/base
cd /data/myworkdir/compose/base
  1. 进入base目录,创建docker-compose.yml文件
cd /data/myworkdir/compose/base/
vi docker-compose.yml
  1. 编写为以下内容:
version: 3.8
services:
  web:
    image: nginx:1.24.0
    environment:
      TEST: 1
    ports:
      - 8979:80
    networks:
      - mytestnet
    volumes:
      - ./mynginxhome:/usr/share/nginx/html
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: "bit@123"
    networks:
      - mytestnet
    volumes:
      - /data/maxhou/mysqldata/varlib/:/var/lib/mysql
    healthcheck:
      test: mysql -user=root --password='bit@123' -e "SELECT 1;"
      interval: 10s
      timeout: 5s
      retries: 10
  redis:
    image: redis:7
    networks:
      - mytestnet
    healthcheck:
      test: redis-cli ping
      interval: 10s
      timeout: 5s
      retries: 10
networks:
  mytestnet:
  1. 输入docker config会做检查
root@139-159-150-152:/data/myworkdir/compose/base# docker compose config
version must be a string
  1. 修改错误信息,将版本转为字符串,再次检查
services:
  web:
    image: nginx:1.24.0
    environment:
      TEST: 1
    ports:
      - 8979:80
    networks:
      - mytestnet
    volumes:
      - ./mynginxhome:/usr/share/nginx/html
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: "bit@123"
    networks:
      - mytestnet
    volumes:
      - /data/maxhou/mysqldata/varlib/:/var/lib/mysql
    healthcheck:
      test: mysql -user=root --password='bit@123' -e "SELECT 1;"
      interval: 10s
      timeout: 5s
      retries: 10
  redis:
    image: redis:7
    networks:
      - mytestnet
    healthcheck:
      test: redis-cli ping
      interval: 10s
      timeout: 5s
      retries: 10
networks:
  mytestnet:
root@139-159-150-152:/data/myworkdir/compose/base# docker compose config
name: base
services:
  mysql:
    environment:
      MYSQL_ROOT_PASSWORD: bit@123
    healthcheck:
      test:
        - CMD-SHELL
        - mysql -user=root --password='bit@123' -e "SELECT 1;"
      timeout: 5s
      interval: 10s
      retries: 10
    image: mysql:5.7
    networks:
      mytestnet: null
    volumes:
      - type: bind
        source: /data/maxhou/mysqldata/varlib/
        target: /var/lib/mysql
        bind:
          create_host_path: true
  redis:
    healthcheck:
      test:
        - CMD-SHELL
        - redis-cli ping
      timeout: 5s
      interval: 10s
      retries: 10
    image: redis:7
    networks:
      mytestnet: null
  web:
    depends_on:
      mysql:
        condition: service_healthy
      redis:
        condition: service_healthy
    environment:
      TEST: "1"
    image: nginx:1.24.0
    networks:
      mytestnet: null
    ports:
      - target: 80
        published: 8979
        protocol: tcp
        mode: ingress
    volumes:
      - type: bind
        source: /data/myworkdir/compose/base/mynginxhome
        target: /usr/share/nginx/html
        bind:
          create_host_path: true
networks:
  mytestnet:
    name: base_mytestnet
  1. 创建首页目录,编辑首页内容
root@139-159-150-152:/data/myworkdir/compose/base# mkdir -p mynginxhome
root@139-159-150-152:/data/myworkdir/compose/base/mynginxhome#
echo "Hello bit" > index.html
  1. 启动服务
root@139-159-150-152:/data/myworkdir/compose/base# docker compose up -d
[+] Running 4/4
 ✔ Network base_mytestnet  Created
 ✔ Container base-mysql-1  Healthy
 ✔ Container base-redis-1  Healthy
 ✔ Container base-web-1    Started
  1. 通过页面访问 http://139.159.150.152:8979
Hello bit
  1. 停止服务
root@139-159-150-152:/data/myworkdir/compose/base# docker compose stop
[+] Running 3/3
 ✔ Container base-web-1    Stopped
 ✔ Container base-mysql-1  Stopped
 ✔ Container base-redis-1  Stopped
  1. 启动服务
root@139-159-150-152:/data/myworkdir/compose/base# docker compose start
[+] Running 3/3
 ✔ Container base-redis-1  Healthy
 ✔ Container base-mysql-1  Healthy
 ✔ Container base-web-1    Started
  1. 删除服务
root@139-159-150-152:/data/myworkdir/compose/base# docker compose down
[+] Running 4/4
 ✔ Container base-web-1    Removed
 ✔ Container base-redis-1  Removed
 ✔ Container base-mysql-1  Removed
 ✔ Network base_mytestnet  Removed

综合案例

Docker Compose部署WordPress

WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站。也可以把WordPress当作一个内容管理系统(CMS)来使用。

部署WordPress

  1. 编写Docker Compose
#指定 docker-compose.yml 文件的版本
version: '3.8'

# 定义所有的 service 信息, services 下面的第一级别的 key 既是一个 service 的名称
services:
  db:
    image: mysql:5.7
    volumes:
      - ./db_data:/var/lib/mysql
    # 定义容器重启策略
    restart: always
    # 设置环境变量, environment 的值可以覆盖 env_file 的值
    environment:
      MYSQL_ROOT_PASSWORD: mywordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    healthcheck:
      test: mysql --user=root --password='mywordpress' -e "SELECT 1;"
      interval: 10s
      timeout: 5s
      retries: 10

  wordpress:
    #docker compose up 以依赖顺序启动服务,先启动db
    depends_on:
      db:
        condition: service_healthy
    image: wordpress:latest
    # 建立宿主机和容器之间的端口映射关系,容器的 80 端口和宿主机的 8000 端口建立映射关系
    ports:
      - "8000:80"
    restart: always
    volumes:
      - ./wordpress:/var/www/html
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
  1. 运行站点
docker compose up -d
  1. 访问web页面,配置参数,点击安装,登录:
    在这里插入图片描述

  2. 删除,释放空间

root@139-159-150-152:/data/myworkdir/compose# docker compose down
[+] Running 3/2
 ✔ Container compose-wordpress-1  Removed
3.3s
 ✔ Container compose-db-1         Removed
1.9s
 ✔ Network compose_default        Removed

常见问题

  1. up、run和start之间有什么区别
    通常,你想要docker compose up。用于up启动或重新启动docker-compose.yml.在默认的"附加"模式下,会看到来自所有容器的所有日志。在"分离"模式(-d)中,启动容器后Compose退出,但容器继续在后台运行。
    docker compose run命令用于运行"一次性"或"临时"任务。它需要您要运行的服务名称,并且只为正在运行的服务所依赖的服务启动容器。用于run运行测试或执行管理任务,例如从数据卷容器中删除或添加数据。该run命令的作用类似于docker run -ti它打开容器的交互式终端并返回与容器中进程的退出状态匹配的退出状态。
    docker compose start命令仅对重新启动先前创建但已停止的容器有用。它从不创建新容器。

  2. 如何在同一主机上运行Compose文件的多个副本
    Compose使用项目名称为项目的所有容器和其他资源创建唯一标识符。要运行项目的多个副本,使用 -p命令行选项或COMPOSE_PROJECT_NAME环境变量 设置自定义项目名称。

  3. 如何控制服务启动顺序?
    可以控制启动顺序,通过依赖指定,并且可以配合healthcheck等健康检查成功以后再启动。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值