Docker Compose

  • Docker Compose

    简介

    https://docs.docker.com/get-started/08_using_compose/

    是一个定义和运行多个容器的工具,使用YAML配置文件。Compose是Docker官方的开源项目,需要我们自己安装使用。服务、应用是一个个容器,Compose将关联容器组成一个Project来运行。

    Docker-Compose将所管理的容器分为三层:

    • 工程(project):由一组关联的应用容器组成的一个完成业务单元,在docker-compose.yml中定义。即是 Compose的一个配置文件可以解析为一个项目,Compose通过分析指定配置文件,得出配置文件所需完成的所 有容器管理与部署操作。
    • 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。每个服务都有自己的名 字、使用的镜像、挂载的数据卷、所属的网络、依赖哪些其他服务等等,即以容器为粒度,用户需要Compose 所完成的任务。
    • 容器(container)

    一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像,参数,依赖。一个服务当中可包括多个容器实例。

    Compose 使用的三个步骤:

    • 使用 Dockerfile 定义应用程序的环境。
    • 使用 docker-compose.yml 定义构成应用程序的服务,这样它们可以在隔离环境中一起运行。
    • 最后,执行 docker-compose up 命令来启动并运行整个应用程序。

    安装

    1. 下载

      1
      curl -L "https://get.daocloud.io/docker/compose/releases/download/v2.6.1/docker-compose-$(uname -s)-$(uname -m)"  -o /usr/local/bin/docker-compose
    2. 授权

      1
      2
      3
      [root@io bin]# chmod +x docker-compose 
      [root@io bin]# docker-compose version
      Docker Compose version v2.6.1
    3. 体验

      • 准备

        创建一个测试目录:

        1
        2
        $ mkdir composetest
        $ cd composetest

        在测试目录中创建一个名为 app.py 的文件,并复制粘贴以下内容:

        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
        import time

        import redis
        from flask import Flask

        app = Flask(__name__)
        #host 域名
        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)

        在此示例中,redis 是应用程序网络上的 redis 容器的主机名,该主机使用的端口为 6379。

        在 composetest 目录中创建另一个名为 requirements.txt 的文件,内容如下:

        1
        2
        flask
        redis
      • 创建Dockerfile文件

        在 composetest 目录中,创建一个名为 Dockerfile 的文件,内容如下:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        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
        COPY . .
        CMD ["flask", "run"]

        Dockerfile 内容解释:

        • FROM python:3.7-alpine: 从 Python 3.7 映像开始构建镜像。

        • WORKDIR /code: 将工作目录设置为 /code。

        • ENV FLASK_APP app.py
          ENV FLASK_RUN_HOST 0.0.0.0
          
          1
          2
          3
          4
          5
          6
          7
          8

          设置 flask 命令使用的环境变量。

          - **RUN apk add --no-cache gcc musl-dev linux-headers**: 安装 gcc,以便诸如 MarkupSafe 和 SQLAlchemy 之类的 Python 包可以编译加速。

          - ```
          COPY requirements.txt requirements.txt
          RUN pip install -r requirements.txt
          复制 requirements.txt 并安装 Python 依赖项。
        • COPY . .: 将 . 项目中的当前目录复制到 . 镜像中的工作目录。

        • CMD [“flask”, “run”]: 容器提供默认的执行命令为:flask run。

      • 创建 docker-compose.yml

        1
        2
        3
        4
        5
        6
        7
        8
        9
        # yaml 配置
        version: '3'
        services:
        web:
        build: .
        ports:
        - "5000:5000"
        redis:
        image: "redis:alpine"

        该 Compose 文件定义了两个服务:web 和 redis。

        • web:该 web 服务使用从 Dockerfile 当前目录中构建的镜像。然后,它将容器和主机绑定到暴露的端口 5000。此示例服务使用 Flask Web 服务器的默认端口 5000 。
        • redis:该 redis 服务使用 Docker Hub 的公共 Redis 映像。
      • 使用 Compose 命令构建和运行您的应用

        在测试目录中,执行以下命令来启动应用程序:

        1
        docker-compose up

        如果你想在后台执行该服务可以加上 -d 参数:

        1
        docker-compose up -d

        查看结果

        1
        2
        [root@io yio]# curl localhost:5000
        Hello World! I have been seen 13 times.

        关闭服务

        1
        docker compose down
      • 查看一下网络

        1
        docker network inspect composetest_default

        image-20220719212835052

    YAML规则

    菜鸟教程yyds

    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
    # 3层

    version: '' #版本
    service: #服务
    service_name1: #服务名

    build: #指定为构建镜像上下文路径:例如 webapp 服务,指定为从上下文 #路径 ./dir/Dockerfile 所构建的镜像
    #或者,作为具有在上下文指定的路径context的对象,以及可选的 #Dockerfile ;添加构建参数,这是只能在构建过程中访问的环境 #变量args;labels:设置构建镜像的标签
    #target:多层构建,可以指定构建哪一层
    images: #镜像
    depends on:
    - service_name2 # 先启动
    - service_name3
    volumes: #挂载
    network: #网络
    configs:
    deploy: #部署
    replicas: 6 #副本
    ·····
    environment:
    MYSQL_HOST: mysql
    MYSQL_USER: root
    MYSQL_PASSWORD: secret
    MYSQL_DB: todos
    expose:
    - '8080'
    - '3000'

    service_name2: #服务名

    service_name3: #服务名

    service_name4: #服务名

    volumes: #项目挂载

    多看多想,看官网,开源项目

    一键部署WP博客

    https://docs.docker.com/samples/wordpress/

    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
    version: '3'

    services:
    db:
    # We use a mariadb image which supports both amd64 & arm64 architecture
    image: mariadb:latest
    # If you really want to use MySQL, uncomment the following line
    #image: mysql:8.0.27
    command: '--default-authentication-plugin=mysql_native_password'
    volumes:
    - db_data:/var/lib/mysql
    restart: always
    environment:
    - MYSQL_ROOT_PASSWORD=123456
    - MYSQL_DATABASE=wordpress
    - MYSQL_USER=wordpress
    - MYSQL_PASSWORD=123
    expose:
    - 3306
    - 33060
    wordpress:
    depends_on:
    - db
    image: wordpress:latest
    ports:
    - 80:80
    restart: always
    environment:
    - WORDPRESS_DB_HOST=db
    - WORDPRESS_DB_USER=wordpress
    - WORDPRESS_DB_PASSWORD=123
    - WORDPRESS_DB_NAME=wordpress
    volumes:
    db_data:

    ##Docker Swarm

    Docker Swarm

    简介

    image-20220719225931176

    如下图所示,swarm 集群由管理节点(manager)和工作节点(work node)构成,A given Docker host can be a manager, a worker, or perform both roles,如果一个Worker挂掉了,这个Worker中的task就会被交给其他的Worker执行,每个task都不是以一个独立的容器运行的。

    • swarm mananger:负责整个集群的管理工作包括集群配置、服务管理等所有跟集群有关的工作,manage node也可以执行服务,但是可以自己配置它只运行管理工作。
    • worker node:即图中的 available node,主要负责运行相应的服务来执行任务(task)。

    img

    一些优点:Swarm支持我们自定义服务的配置,并且自动生效。集群中的node仍然可以运行一个独立的容器,Swarm中的容器会被Swarm Manager管理控制,这是与独立的容器之间的区别。

    ###Raft一致性协议

    Raft协议是一种基于日志复制的一致性算法,通过选举领袖的方式来实现的。

    论文

    基本概念:

    • 复制状态机(Replicated state machines)

      将集群中的每个服务器看做一个状态机, 它们接收外部的指令, 进行状态的改变。只要初始状态和接收到的指令是确定的, 那么它任意时刻的状态也是确定的, 这样以来, 所谓保持分布式一致性即是保证集群中所有状态机的状态一致性

    • 领导人(leader)、跟随者(follower) 和 候选人(candidate)

      raft 将所有服务器结点划分为 3 个互不相交的子集, 任何一个结点都隶属于某一个集合, 其中地位最高的结点称为领导人(leader), 它负责接收来自客户端的调用, 组织日志复制给其它结点, 统筹管理整个计算机集群, raft 保证集群中在任意时刻至多有一个领导人, 跟随者(follower)接收来自领导人(leader)的复制日志, 按照领导人(leader)的要求进行相应的动作。领导人(leader)持续地向集群中的所有其它结点发送心跳包, 以此宣告“你们的皇帝还活着”。一旦跟随者(follower)在给定的时间内没有收到来自领导人(follower)的心跳包, 它便认为领导人出了故障, 于是转变自己的身份为候选人(candidate)进行领导人的竞选。

    • 任期(term)

      raft 将系统时间划分为一个个逻辑段, 每个逻辑段的时间长度是不一致的, 可以是任意长度, 每一个逻辑段称为一个任期(term), raft 对每一个任期都设置一个整型编号, 称为任期号(类似皇帝的年号或者说最后的庙号), 每一个任期可以进一步划分为两个子段, 其中第一个子段是选举期, 第二个子段是任职期, 选举期将竞选产生集群的领导人, 若领导人选举成功, 则进入了任职期, 在任职期内只要领导人持续保持健康状态(即持续不间断地向其他跟随者发送心跳包), 则这个时期可以无限期地持续, 当然在 raft 中选举不一定都是成功的, 可能存在某个 term 中的选举期没有任何候选人胜出, 这样 raft 会进行下一个 term, 重新进行选举, 直到有新的领导人胜出, 从而进入任职期, raft 采用了特别的机制来尽可能地避免一个 term 中没有任何候选人竞选成功的情形出现。

    • 日志(log)与日志复制(log replication)

      raft 将集群中的所有服务器看做若干个状态机, 状态机接收指令进行状态的变更, 在 raft 协议中, 指令是以日志的形式的传递的, 虽然集群中有N个结点, 但只有一个结点(领导人)接收客户端的请求, 其它所有结点接收来自领导人的复制日志(Replicated log), 进行解析、和执行, 从而进行状态的变更, 所有服务器结点按序执行相同的日志(指令), 从而保持状态一致性。(Hadoop的集群)

    • 日志提交(commit)

      领导人在接收到客户端请求之后, 会产生一个相应的日志项(log entry), 日志项中包含了指令, 领导人不会立即执行这个指令, 它首先会进行日志项复制, 当日志项被成功地复制到集群中的大多数结点(超多半数,一半以上不包括一半)后, 领导人会提交(commit)这个日志项, 并执行其中的指令(即将该日志应用(apply)到状态机中)

    使用

    1. Docker Machine 创建Docker主机

      • 安装:

        1
        2
        $ sudo curl -L https://github.com/docker/machine/releases/download/v0.13.0/docker-machine-`uname -s`-`uname -m` > /usr/local/bin/docker-machine
        $ sudo chmod +x /usr/local/bin/docker-machine
      • 创建四个主机

        1
        2
        3
        4
        docker-machine create -d virtualbox manager1 && 
        docker-machine create -d virtualbox manager2 &&
        docker-machine create -d virtualbox worker1 &&
        docker-machine create -d virtualbox worker2
      • 查看主机信息

        1
        docker-machine ls
    2. Docker Swarm 配置集群节点

      • 创建管理节点(初始化)

        1
        2
        #在manager1主机上,创建一个 Docker Swarm 管理节点(初始化集群的时候,会自动把当前节点设置为管理节点)
        docker-machine ssh manager1 "docker swarm init --advertise-addr 192.168.99.100"
      • 创建工作节点并加入到集群

        1
        2
        3
        4
        5
        6
        #1
        docker-machine ssh worker1 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
        This node joined a swarm as a worker.
        #2
        docker-machine ssh worker2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-envtxo4dl6df2ar3qldcccfdg 192.168.99.100:2377"
        This node joined a swarm as a worker.
      • 另一个管理节点

        1
        2
        3
        4
        5
        6
        7
        #先在manager1主机上,获取管理节点对应的token,然后再配置为管理节点
        [user]docker-machine ssh manager1 "docker swarm join-token manager"
        +To add a manager to this swarm, run the +following command:
        +
        + docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377

        [user] docker-machine ssh manager2 "docker swarm join --token SWMTKN-1-5uwpqibnvmho1png8zmhcw8274yanohee32jyrcjlait9djhsk-0koz1b98sco8r5cn3g61eahnu 192.168.99.100:2377"
      • 查看集群信息

        1
        2
        3
        4
        5
        6
        7
        8
        #进入manager1内
        [user]docker node ls
        ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
        n0ub7dpn90rxjq97dr0g8we0w * manager1 Ready Active Leader
        t4cy67qp0bf2spgabsutwxnzt manager2 Ready Active Reachable
        if0kmzp4ww3oy57y7cha7v36t worker1 Ready Active
        jgg61cujzaeb3du5796fm0x2g worker2 Ready Active
        #Leader表示领导者,Reachable表示候选人,头一挂掉它就顶上去了,可以不指定,会选举。
    3. Docker Service 部署单个集群服务

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      # --replicas 4  表示四个副本 实际上这个副本可以更多 每个容器中可以多跑几个服务来分配
      docker service create --replicas 4 -p 8088:80 --name nginx 192.168.99.1:5000/nginx:latest

      #此时四个docker任意一个ip都可以访问服务
      #也可以手动设置实例个数
      docker service scale nginx=4
      #
      #查看服务
      $ docker service ls
      ID NAME MODE REPLICAS IMAGE PORTS
      ap8h8srb8yh3 nginx replicated 4/4 192.168.99.1:5000/nginx:latest *:8080->8080/tcp

      $ docker service ps nginx
      ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
      l2rdrwzs5zog nginx.1 192.168.99.1:5000/nginx:latest manager1 Running Running about a minute ago
      vsfczzbwanx3 nginx.2 192.168.99.1:5000/nginx:latest manager2 Running Running about a minute ago
      qtbgw5h6dsi9 nginx.3 192.168.99.1:5000/nginx:latest worker Running Running about a minute ago
      za2ejnvb3n6z nginx.4 192.168.99.1:5000/nginx:latest worker2 Running Running about a minute ago
    4. Docker Stack 部署多个集群服务

      以后可以使用k8s了

      使用docker stack进行多服务编排部署,使用的同样是docker-compose.yml配置文件

      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
      version: "3"

      services:
      nginx:
      image: 192.168.99.1:5000/nginx:latest
      ports:
      - 8088:80
      deploy:
      mode: replicated
      replicas: 4

      visualizer:
      image: 192.168.99.1:5000/dockersamples/visualizer:latest
      ports:
      - "8080:8080"
      volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      deploy:
      replicas: 1
      placement:
      constraints: [node.role == manager]

      portainer:
      image: 192.168.99.1:5000/portainer/portainer:latest
      ports:
      - "9000:9000"
      volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
      deploy:
      replicas: 1
      placement:
      constraints: [node.role == manager]
      1
      2
      3
      4
      5
      6
      7
      8
      #部署
      docker stack deploy -c docker-compose.yml deploy-demo
      #查看
      docker stack ls
      #
      #去浏览器看
      http://192.168.99.100:8080/
      http://192.168.99.100:9000/
    5. 常用命令

    • docker-machine

      命令 说明
      docker-machine create 创建一个 Docker 主机(常用-d virtualbox
      docker-machine ls 查看所有的 Docker 主机
      docker-machine ssh SSH 到主机上执行命令
      docker-machine env 显示连接到某个主机需要的环境变量
      docker-machine inspect 输出主机更多信息
      docker-machine kill 停止某个主机
      docker-machine restart 重启某台主机
      docker-machine rm 删除某台主机
      docker-machine scp 在主机之间复制文件
      docker-machine start 启动一个主机
      docker-machine status 查看主机状态
      docker-machine stop 停止一个主机
    • docker swarm

      命令 说明
      docker swarm init 初始化集群
      docker swarm join-token worker 查看工作节点的 token
      docker swarm join-token manager 查看管理节点的 token
      docker swarm join 加入集群中
    • docker node

      命令 说明
      docker node ls 查看所有集群节点
      docker node rm 删除某个节点(-f强制删除)
      docker node inspect 查看节点详情
      docker node demote 节点降级,由管理节点降级为工作节点
      docker node promote 节点升级,由工作节点升级为管理节点
      docker node update 更新节点
      docker node ps 查看节点中的 Task 任务
    • docker service

      命令 说明
      docker service create 部署服务
      docker service inspect 查看服务详情
      docker service logs 查看某个服务日志
      docker service ls 查看所有服务详情
      docker service rm 删除某个服务(-f强制删除)
      docker service scale 设置某个服务个数
      docker service update 更新某个服务
    • docker stack

      命令 说明
      docker stack deploy 部署新的堆栈或更新现有堆栈
      docker stack ls 列出现有堆栈
      docker stack ps 列出堆栈中的任务
      docker stack rm 删除堆栈
      docker stack services 列出堆栈中的服务
      docker stack down 移除某个堆栈(不会删除数据)

    docker secret docker config·····

    作者: Meow Mii

    本文链接: https://blog.yiochin.top/p/c0e3b7e9.html

    版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议,转载请注明出处!


    📝 Comment