• 循序渐进Docker Compose


    1.概述

    1.1 Docker Compose 定义

    Docker Compose是Docker官方的开源项目,负责实现对Docker容器集群的快速编排。Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器

    1.2 Docker Compose背景

    我们使用 Docker 的时候,定义 Dockerfile 文件,然后使用 docker build、docker run 等命令操作容器。然而微服务架构的应用系统一般包含若干个微服务,每个微服务一般都会部署多个实例,如果每个微服务都要手动启停,那么效率之低,维护量之大可想而知。
    Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。.Docker Compose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器,Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。
    注意,为变量输入数据时,必须遵循标准 YAML 规则。 对于包含特殊字符的密码,需要正确转义它们($ 是转义字符)或正确引用变量。 如果不知道如何执行此操作或不愿意研究,最好的做法是仅使用字母数字字符。

    1.3 Docker Compose核心概念

    Docker Compose将所管理的容器分为三层,分别是:

    • 项目(project)
    • 服务(service)
    • 容器(containner)
      我们将通过后续的章节理解这三层的意思或用途

    2.安装

    2.1 Official Repos

    从版本 2 开始,Docker 开始将 docker compose 发布为基于 Go 的 Docker 插件(而不是基于 Python 的独立二进制文件)。并且为多个架构发布了这个插件,而 v1.x 版本的二进制文件仅适用于 x86_64 架构。
    按照此处描述从官方仓库安装 Docker,确保在此过程中安装 docker-compose-plugin 软件包。

    2.2 Manual Installation

    通过以下命令手动安装 docker compose:

    mkdir -p "$HOME/.docker/cli-plugins" 
    curl -sL "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o "$HOME/.docker/cli-plugins/docker-compose" 
    chmod +x $HOME/.docker/cli-plugins/docker-compose
    
    • 1
    • 2
    • 3

    在系统范围内安装,可以使用 /usr/local/lib/docker/cli-plugins 而不是 $HOME/.docker/cli-plugins
    如果已经安装了 docker(或至少安装了 docker-cli),最好是从官仓 安装compose,运行 docker compose version 将显示 compose 版本。

    ./docker-compose version
    Docker Compose version v2.27.0
    
    • 1
    • 2

    2.3 v1.x 兼容性

    由于 v2 作为插件运行而不是独立的二进制文件,它通过 docker compose args 而不是 docker-compose args调用。
    Docker 在推出 v2 作为插件运行后,为了帮助用户更顺利地从 v1 迁移到 v2,提供了一个新的适用于 x86_64 和 aarch64 平台的docker-compose 二进制文件以兼容原有的命令调用方式。例如:

    • 以插件方式运行comose:
    docker compose version
    Docker Compose version v2.27.0
    
    • 1
    • 2
    • 兼容命令方式:
    /home/docker/.docker/cli-plugins/docker-compose version
    Docker Compose version v2.27.0
    
    • 1
    • 2

    3. YAML 配置说明

    简而言之,Docker Compose 通过应用在单个 docker-compose.yml 配置文件中声明的许多规则来工作。
    几乎每个规则都替换了特定的 Docker 命令,因此最终只需要运行:

    docker-compose up
    
    • 1

    使用 Docker Compose 可以应用大量的配置,而这些配置是由 Compose 在后台处理的, 这省去用 Bash 或其他东西编写脚本的麻烦。

    在此文件中,我们需要指定至少一项服务以及可选的卷和网络:

    version: "3.7"
    services:
      ...
    volumes:
      ...
    networks:
      ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.1 Services

    首先,服务指的是容器的配置.
    例如,以一个由前端、后端和数据库组成的 Docker 化 Web 应用程序为例。 可能会将这些组件拆分为三个映像,并在配置中将它们定义为三个不同的服务:

    services:
      frontend:
        image: my-vue-app
        ...
      backend:
        image: my-springboot-app
        ...
      db:
        image: postgres
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.2 Volumes & Networks

    卷是主机和容器之间甚至容器之间共享的磁盘空间的物理区域。 换句话说,卷是主机中的共享目录,对某些或所有容器可见。
    同样,网络定义了容器之间以及容器与主机之间的通信规则。 Common network zones(公共网络区域)将使容器的服务可以相互发现,而private zones(私有区域)将它们隔离在虚拟沙箱中。

    4. 解析 Service

    现在让我们开始检查服务的主要设置。

    4.1 Pulling一个Image

    有时,Service所需的镜像已经(由我们或其他人)发布在 Docker Hub 或另一个 Docker Registry中。
    可以通过来使用 image 属性引用它,在属性中指定镜像名称和标签

    services: 
      my-service:
        image: ubuntu:latest
        ...
    
    • 1
    • 2
    • 3
    • 4

    4.2 Building一个Image

    或者使用dockerfile建置,需要通过读取 Dockerfile构建镜像。
    这里使用 build 关键字,将 Dockerfile 的路径作为值传递:

    services: 
      my-custom-app:
        build: /path/to/dockerfile/
        ...
    
    • 1
    • 2
    • 3
    • 4

    使用 URL 代替路径:

    services: 
      my-custom-app:
        build: https://github.com/my-company/my-project.git
    
    • 1
    • 2
    • 3

    还可以与 build 属性一起指定image名称,该属性将在创建后命名image,后续可供其他服务使用:

    services: 
      my-custom-app:
        build: https://github.com/my-company/my-project.git
        image: my-project-image
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    4.3 Configuring the Networking

    Docker 容器之间,通过 Docker Compose 隐式创建或通过配置创建的网络进行通信。一个服务可以通过容器名称和端口(例如 network-example-service:80)直接引用同一网络上的另一个服务进行通信,前提是已经通过expose关键字公开端口:

    services:
      network-example-service:
        image: karthequian/helloworld:latest
        expose:
          - "80"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但是,要从主机访问容器,端口必须通过ports关键字进行映射,映射的format如下:
    host_port:container_port

    services:
      network-example-service:
        image: karthequian/helloworld:latest
        ports:
          - "80:80"
        ...
      my-custom-app:
        image: myapp:latest
        ports:
          - "8080:3000"
        ...
      my-custom-app-replica:
        image: myapp:latest
        ports:
          - "8081:3000"
        ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    端口 80 现在将在主机上可见,而其他两个容器的 3000 端口将分别在主机的 8080 和 8081 端口上可用

    进一步定义额外的虚拟网络来隔离容器:

    services:
      network-example-service:
        image: karthequian/helloworld:latest
        networks: 
          - my-shared-network
        ...
      another-service-in-the-same-network:
        image: alpine:latest
        networks: 
          - my-shared-network
        ...
      another-service-in-its-own-network:
        image: alpine:latest
        networks: 
          - my-private-network
        ...
    networks:
      my-shared-network: {}
      my-private-network: {}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    “another-service-in-the-same-network“将能够ping并访问“network-example-service”的端口80,而“another-service-in-its-own-network”则不行。

    4.4 设置卷

    卷分为三种类型:

    • anonymous(匿名卷)
    • named(命名卷)
    • host(主机卷)
      Docker 管理着匿名卷和命名卷,并自动将它们挂载到主机上自行生成的目录中。虽然在旧版本的 Docker(1.9 之前)中,匿名卷很有用,但现在推荐使用命名卷。主机卷还允许我们指定主机上的一个现有文件夹。。
      我们可以在service级别配置主机卷,并在配置的外层级别配置命名卷,以便后者对其他容器可见,而不仅仅是它们所属的容器可见:
    services:
      volumes-example-service:
        image: alpine:latest
        volumes: 
          - my-named-global-volume:/my-volumes/named-global-volume                     --引用命名卷
          - /tmp:/my-volumes/host-volume                                               --主机卷
          - /home:/my-volumes/readonly-host-volume:ro                                  --主机卷
        ...
      another-volumes-example-service:
        image: alpine:latest                        
        volumes:
          - my-named-global-volume:/another-path/the-same-named-global-volume           --引用命名卷
        ...
    volumes:
      my-named-global-volume:  --定义命名卷
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    这里,两个容器都将对 my-named-global-volume 共享文件夹具有读/写访问权限,无论它们将其映射到哪个路径。 相反,这两个主机卷将仅可用于volumes-example-service。

    主机文件系统的 /tmp 文件夹映射到容器的 /my-volumes/host-volume 文件夹。 文件系统的这一部分是可写的,这意味着容器可以读取也可以写入(和删除)主机中的文件。
    通过在规则中附加 :ro 以只读模式挂载卷,就像 /home 文件夹(因为有时候不希望 Docker 容器错误地删除用戶的home目录)。

    4.5 声明依赖关系

    通常,如果需要在服务之间创建依赖链,以便某些服务在其他服务之前加载(并在之后卸载)。 则通过depends_on关键字来实现这个结果:

    services:
      kafka:
        image: wurstmeister/kafka:2.11-0.11.0.3
        depends_on:
          - zookeeper
        ...
      zookeeper:
        image: wurstmeister/zookeeper
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    不过要注意,Compose 不会等待 Zookeeper 服务加载完成才启动 kafka 服务; 它只是简单的等待它start。 如果我们需要在启动另一个服务之前完全加载一个服务,需要在 Compose 中更深入地控制启动和关闭顺序

    5. 管理环境变量

    在 Compose 中使用环境变量非常简单。我们可以定义静态环境变量,也可以使用 ${} 标记来定义动态变量。

    services:
      database: 
        image: "postgres:${POSTGRES_VERSION}"
        environment:
          DB: mydb
          USER: "${USER}"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    有不同的方法可以向 Compose 提供这些值:
    例如,一种方法是将它们设置在同一目录中的 .env 文件中,其结构类似于 .properties 文件,key=value:

    POSTGRES_VERSION=alpine
    USER=foo
    
    • 1
    • 2

    否则,在调用命令之前在操作系统中设置变量:

    export POSTGRES_VERSION=alpine
    export USER=foo
    docker-compose up
    
    • 1
    • 2
    • 3

    也可以在 shell 中使用简单的一行代码:

    POSTGRES_VERSION=alpine USER=foo docker-compose up
    
    • 1

    可以混合使用这些方法,但请记住,Compose 使用以下优先级顺序,用较高优先级覆盖不太重要的内容:

    • 1.Compose file
    • 2.Shell environment variables
    • 3.Environment file
    • 4.Dockerfile
    • 5.Variable not defined

    6. Scaling & Replicas

    在较旧的 Compose 版本中,可以通过 docker-compose scale 命令来扩展容器实例。较新的版本废弃了这个命令,并用 --scale 选项取而代之。
    利用 Docker Swarm(一个 Docker 引擎的集群),并通过 deploy 部分的 replicas 属性声明性地自动扩展容器。

    services:
      worker:
        image: dockersamples/examplevotingapp_worker
        networks:
          - frontend
          - backend
        deploy:
          mode: replicated
          replicas: 6
          resources:
            limits:
              cpus: '0.50'
              memory: 50M
            reservations:
              cpus: '0.25'
              memory: 20M
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    在 deploy 部分,还可以指定许多其他选项,例如资源阈值。然而,Compose 仅在部署到 Swarm 时才考虑整个 deploy 部分,否则会忽略它。

    7. 生命周期管理

    Docker Compose 的语法:

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

    有许多可用的选项和命令,但至少需要知道正确active和deactive整个系统的选项和命令。

    7.1. Startup

    可以使用 up 命令来创建和启动配置中定义的容器、网络和卷。

    docker-compose up
    
    • 1

    在第一次之后,可以简单地使用 start 命令来启动服务

    docker-compose start
    
    • 1

    如果文件的名称与默认文件名 (docker-compose.yml) 不同,可以利用 -f 和 ––file 标志来指定备用文件名:

    docker-compose -f custom-compose-file.yml start
    
    • 1

    使用 -d 选项启动时,Compose 还可以作为守护进程在后台运行:

    docker-compose up -d
    
    • 1

    7.2. Shutdown

    为了安全地停止活动服务,可以使用 stop,它将保留容器、卷和网络,以及对它们所做的每项修改:

    docker-compose stop
    
    • 1

    要重置项目的状态,可以运行 down 命令。运行 down 命令会删除由 docker-compose.yml 文件定义的所有服务、网络和容器,但会保留外部卷(如果有的话)

    docker-compose down
    
    • 1

    8. Docker compose示例

    8.1 Single service

    以下是使用 docker compose 部署 single service的基本示例:

    services:
      heimdall:
        image: linuxserver/heimdall
        container_name: heimdall
        volumes:
          - /home/user/appdata/heimdall:/config
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Europe/London
        ports:
          - 10080:80
          - 10443:443
        restart: unless-stopped
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    如果将上述代码片段保存在名为 compose.yml 的文件中,则只需从同一文件夹中运行 docker compose up -d 即可自动拉取 heimdall 映像,并创建并启动一个容器。 up 表示创建并启动服务,-d 表示在后台执行。
    如果从不同的文件夹执行操作,或者 yaml 文件命名为其他名字,例如 heimdall.yml,那么需要在命令中使用 -f 选项:

    docker compose -f /path/to/single_service.yml up -d。
    
    • 1

    docker compose ls将列出running状态的服务,如果要列出包含“非running状态”,需要搭配-a 选项

    docker compose ls
    NAME                STATUS              CONFIG FILES
    docker              running(1)          /home/docker/single_service.yaml
    
    
    • 1
    • 2
    • 3
    • 4

    8.2 Multiple Service

    以下是使用 docker compose 部署 multiple service的基本示例:
    可以通过一个单一的 compose yaml 文件来管理多个服务。将以下内容复制.yml 文件中,然后使用 docker-compose up/down 命令就可以同时对所有服务进行操作。

    services:
      heimdall:
        image: linuxserver/heimdall
        container_name: heimdall
        volumes:
          - /home/user/appdata/heimdall:/config
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Europe/London
        ports:
          - 80:80
          - 443:443
        restart: unless-stopped
    
      nginx:
        image: linuxserver/nginx
        container_name: nginx
        environment:
          - PUID=1000
          - PGID=1000
          - TZ=Europe/London
        volumes:
          - /home/user/appdata/nginx:/config
        ports:
          - 81:80
          - 444:443
        restart: unless-stopped
    
      mariadb:
        image: linuxserver/mariadb
        container_name: mariadb
        environment:
          - PUID=1000
          - PGID=1000
          - MYSQL_ROOT_PASSWORD=ROOT_ACCESS_PASSWORD
          - TZ=Europe/London
        volumes:
          - /home/user/appdata/mariadb:/config
        ports:
          - 3306:3306
        restart: unless-stopped
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    启动yaml档:

    docker compose -f /home/docker/multi_service.yaml up -d
    [+] Running 3/3
     ✔ Container nginx     Running                                                                                                                                                                                 0.0s
     ✔ Container heimdall  Running                                                                                                                                                                                 0.0s
     ✔ Container mariadb   Started 
    
    • 1
    • 2
    • 3
    • 4
    • 5

    查看compose项目运行状况

    docker@anzfam:~$ docker compose ls -a
    NAME                STATUS              CONFIG FILES
    docker              running(3)          /home/docker/multi_service.yaml
    
    • 1
    • 2
    • 3

    查看compose包含的服务

    docker@anzfam:~$ docker compose config --services
    heimdall
    mariadb
    nginx
    
    
    • 1
    • 2
    • 3
    • 4
    • 5

    查看compose所拥有的容器

    docker container ls -a
    CONTAINER ID   IMAGE                  COMMAND   CREATED          STATUS              PORTS                                                                                NAMES
    dcbf3af2c44e   linuxserver/heimdall   "/init"   19 minutes ago   Up 19 minutes       0.0.0.0:10080->80/tcp, :::10080->80/tcp, 0.0.0.0:10443->443/tcp, :::10443->443/tcp   heimdall
    a3939bcca133   linuxserver/nginx      "/init"   19 minutes ago   Up 19 minutes       0.0.0.0:10081->80/tcp, :::10081->80/tcp, 0.0.0.0:10444->443/tcp, :::10444->443/tcp   nginx
    59b322021f3a   linuxserver/mariadb    "/init"   19 minutes ago   Up About a minute   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp                                            mariadb
    
    • 1
    • 2
    • 3
    • 4
    • 5

    从上述输出结果来看,已经定义了 3 个服务:heimdall、nginx 和 mariadb,并与之对应有三个container运行,当执行 docker compose up -d 时,它将首先下载所有三个容器的映像(如果它们不存在)(如果存在,则不会更新),然后它将创建所有三个容器并启动它们。 docker compose down 将关闭所有三个服务并销毁容器(持久数据将保留)。

    8.3 启动多个compose project

    前面讲到docker compose将整个结构分为project、service以及container三层,如果想要在同一台主机上启动多个yaml档项目,需要指定-p选项来指定project name,否则docker将默认project name为docker,如此当分别启动上述两个示例时,可能会产生冲突

    启动single_service.yaml,并命名为single-service-example

     docker compose -f ./single_service.yaml -p single-service-example up -d
    [+] Running 2/2
     ✔ Network single-service-example_default  Created                                                                                                                                                                                      0.1s
     ✔ Container heimdall01                    Started 
    
    • 1
    • 2
    • 3
    • 4

    启动multi_service.yaml,并命名为multi-service-example

    docker compose -f ./multi_service.yaml -p multi-service-example up -d
    [+] Running 4/4
     ✔ Network multi-service-example_default  Created                                                                                                                                                                                       0.1s
     ✔ Container nginx                        Started                                                                                                                                                                                       1.9s
     ✔ Container mariadb                      Started                                                                                                                                                                                       1.5s
     ✔ Container heimdall02                   Started 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    查看结果显示这里已经有两个不同yaml档建立的project

    docker@anzfam:~$ docker compose ls -a
    NAME                     STATUS              CONFIG FILES
    multi-service-example    running(3)          /home/docker/multi_service.yaml
    single-service-example   running(1)          /home/docker/single_service.yaml
    
    • 1
    • 2
    • 3
    • 4
  • 相关阅读:
    上周热点回顾(4.18-4.24)
    对于JSP原理以及源码的深入剖析与理解心得
    【Java|golang】791. 自定义字符串排序---使用桶排序
    风光储一体化园区 | 图扑新能源可视化
    如何与Excel聊天?
    淘宝产品ID在哪儿查询?
    生产环境TiDB集群缩容TiKV操作步骤
    C++ Opencv 图片运算和处理
    基于stm32单片机的LCD1602计时器可调时钟显示Proteus仿真
    图论与宽搜——图中点的层次
  • 原文地址:https://blog.csdn.net/weixin_43230594/article/details/138955513