1. Docker-Compose企业生产环境实战

  • Docker Compose 是 Docker 官方编排(Orchestration)项目之一,负责快速在集群中部署分布式应用。Compose 定位是“defining and running complex applications with Docker”,前身是 Fig,兼容 Fig 的模板文件。

2. Docker-Compose概念剖析

  • 我们知道Dockerfile 可以让用户管理一个单独的应用容器,而今天即将学习的 Compose 则是允许用户在一个模板(YAML 格式)中定义一组相关联的应用容器(被称为一个 project,即项目),例如:一台Web 服务容器关联后端的数据库服务容器等。
  • Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器(container)。Docker-Compose运行目录下的所有文件(docker-compose.yml,extends文件或环境变量文件等)组成一个工程,若无特殊指定工程名即为当前目录名。一个工程当中可包含多个服务,每个服务中定义了容器运行的镜像、参数、依赖。
  • 一个服务当中可包括多个容器实例,Docker-Compose并没有解决负载均衡的问题,因此需要借助其它工具实现服务发现及负载均衡
  • Docker-Compose的配置文件默认为docker-compose.yml,可通过环境变量COMPOSE_FILE或-f参数自定义配置文件,其定义了多个有依赖关系的服务及每个服务运行的容器。
  • 使用Dockerfile模板文件,可以让用户很方便的定义一个单独的应用容器。在工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
  • Docker-Compose允许用户通过单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)
  • Docker-Compose项目由Python编写,调用Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。

3. Docker-Compose部署安装

  • 安装Docker Compose 之前,需要先安装 Docker引擎服务,此处使用 Compose镜像方式安装Compose项目,然后执行如下命令:
//下载Docker compose脚本
[root@localhost ~]# curl -SL https://github.com/docker/compose/releases/download/v2.17.2/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose

//添加脚本x权限
chmod +x /usr/local/bin/docker-compose

//查看版本信息
[root@localhost ~]# docker-compose --version
Docker Compose version v2.17.2

4. Docker-Compose命令实战

生产环境docker m集群 docker生产环境实践_Docker

5. Docker-Compose常见概念

  • 服务(service)
  1. 一个应用容器,实际上可以运行多个相同镜像的实例。
  • 项目(project)
  1. 由一组关联的应用容器组成的一个完整业务单元。
  2. 一个项目可以由多个服务(容器)关联而成,Compose是面向项目进行管理。

6. Docker-Compose语法详解

  • version:指定本 yml 依从的 compose 哪个版本制定的。
  • build:指定为构建镜像上下文路径:
  • 例如 webapp 服务,指定为从上下文路径 ./dir/Dockerfile 所构建的镜像:
version: "3"
services:
  webapp:
    build: ./dir
  • 或者,作为具有在上下文指定的路径的对象,以及可选的 Dockerfile 和 args:
version: "3"
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"
      target: prod
  • context:上下文路径。
  • dockerfile:指定构建镜像的 Dockerfile 文件名。
  • args:添加构建参数,这是只能在构建过程中访问的环境变量。
  • labels:设置构建镜像的标签。
  • target:多层构建,可以指定构建哪一层。
  • cap_add,cap_drop
  • 添加或删除容器拥有的宿主机的内核功能。
cap_add:
  - ALL # 开启全部权限
cap_drop:
  - SYS_PTRACE # 关闭 ptrace权限
  • cgroup_parent:为容器指定父 cgroup 组,意味着将继承该组的资源限制。
cgroup_parent: m-executor-abcd
  • command:覆盖容器启动的默认命令。
command: ["bundle", "exec", "thin", "-p", "3000"]
  • container_name:指定自定义容器名称,而不是生成的默认名称。
container_name: my-web-container
  • 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"
services:
  web:
    build: .
    depends_on:
      - db
      - redis
  redis:
    image: redis
  db:
    image: postgres
  • 注意:web 服务不会等待 redis db 完全启动 之后才启动。
  • deploy:指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用。
version: "3"
services:
  redis:
    image: redis:alpine
    deploy:
      mode:replicated
      replicas: 6
      endpoint_mode: dnsrr
      labels: 
        description: "This redis service label"
      resources:
        limits:
          cpus: '0.50'
          memory: 50M
        reservations:
          cpus: '0.25'
          memory: 20M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
  • 可以选参数:
  1. endpoint_mode:访问集群服务的方式。
endpoint_mode: vip
  • Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr
  • DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址。
  • labels:在服务上设置标签。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下的 labels。
  • mode:指定服务提供的模式
  • replicated:复制服务,复制指定服务到集群的机器上。
  • global:全局服务,服务将部署至集群的每个节点。
  • 图解:下图中黄色的方块是 replicated 模式的运行情况,灰色方块是 global 模式的运行情况。
  • replicas:mode 为 replicated 时,需要使用此参数配置具体运行的节点数量。
  • resources:配置服务器资源使用的限制,例如上例子,配置 redis 集群运行需要的 cpu 的百分比 和 内存的占用。避免占用资源过高出现异常。
  • restart_policy:配置如何在退出容器时重新启动容器。
  • condition:可选 none,on-failure 或者 any(默认值:any)。
  • delay:设置多久之后重启(默认值:0)。
  • max_attempts:尝试重新启动容器的次数,超出次数,则不再尝试(默认值:一直重试)。
  • window:设置容器重启超时时间(默认值:0)
  • rollback_config:配置在更新失败的情况下应如何回滚服务。
  • parallelism:一次要回滚的容器数。如果设置为0,则所有容器将同时回滚
  • delay:每个容器组回滚之间等待的时间(默认为0s)
  • failure_action:如果回滚失败,该怎么办。其中一个 continue 或者 pause(默认pause)
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)
  • max_failure_ratio:在回滚期间可以容忍的故障率(默认为0)
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认 stop-first )。
  • update_config:配置应如何更新服务,对于配置滚动更新很有用。
  • parallelism:一次更新的容器数
  • delay:在更新一组容器之间等待的时间。
  • failure_action:如果更新失败,该怎么办。其中一个 continue,rollback 或者pause (默认:pause)。
  • monitor:每个容器更新后,持续观察是否失败了的时间 (ns|us|ms|s|m|h)(默认为0s)。
  • max_failure_ratio:在更新过程中可以容忍的故障率。
  • order:回滚期间的操作顺序。其中一个 stop-first(串行回滚),或者 start-first(并行回滚)(默认stop-first)。
    注:仅支持 V3.4 及更高版本。
  • devices:指定设备映射列表
devices:
  - "/dev/ttyUSB0:/dev/ttyUSB0"
  • dns:自定义 DNS 服务器,可以是单个值或列表的多个值
dns: 8.8.8.8
dns:
  - 8.8.8.8
  - 9.9.9.9
  • dns_search:自定义 DNS 搜索域。可以是单个值或列表
dns_search: example.com
dns_search:
  - dc1.example.com
  - dc2.example.com
  • 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
  • env_file:从文件添加环境变量。可以是单个值或列表的多个值
env_file: .env
  • 也可以是列表格式:
env_file:
  - ./common.env
  - ./apps/web.env
  - /opt/secrets.env
  • environment:添加环境变量。您可以使用数组或字典、任何布尔值,布尔值需要用引号引起来,以确保 YML 解析器不会将其转换为 True 或 False。
environment:
  RACK_ENV: development
  SHOW: 'true'
  • expose:暴露端口,但不映射到宿主机,只被连接的服务访问
  • 仅可以指定内部端口为参数:
expose:
 - "3000"
 - "8000"
  • extra_hosts:添加主机名映射。类似 docker client --add-host
extra_hosts:
 - "somehost:162.242.195.82"
 - "otherhost:50.31.209.229"
  • 以上会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:
162.242.195.82  somehost
50.31.209.229   otherhost
  • healthcheck:用于检测 docker 服务是否健康运行
healthcheck:
  test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
  interval: 1m30s # 设置检测间隔
  timeout: 10s # 设置检测超时时间
  retries: 3 # 设置重试次数
  start_period: 40s # 启动后,多少秒开始启动检测程序
  • image:指定容器运行的镜像。以下格式都可以
image: redis
image: ubuntu:14.04
image: tutum/influxdb
image: example-registry.com:4000/postgresql
image: a4bc65fd # 镜像id
  • logging:服务的日志记录配置
  • driver:指定服务容器的日志记录驱动程序,默认值为json-file。有以下三个选项
driver: "json-file"
driver: "syslog"
driver: "none"
  • 仅在 json-file 驱动程序下,可以使用以下参数,限制日志得数量和大小
logging:
  driver: json-file
  options:
    max-size: "200k" # 单个文件大小为200k
    max-file: "10" # 最多10个文件
当达到文件限制上限,会自动删除旧得文件。
  • syslog: 驱动程序下,可以使用 syslog-address 指定日志接收地址
logging:
  driver: syslog
  options:
    syslog-address: "tcp://192.168.0.42:123"
  • network_mode:设置网络模式
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"
  • networks:配置容器连接的网络,引用顶级 networks 下的条目
services:
  some-service:
    networks:
      some-network:
        aliases:
         - alias1
      other-network:
        aliases:
         - alias2
networks:
  some-network:
    # Use a custom driver
    driver: custom-driver-1
  other-network:
    # Use a custom driver which takes special options
    driver: custom-driver-2
  • aliases :同一网络上的其他容器可以使用服务名称或此别名来连接到对应容器的服务。
  • restart: “no”:是默认的重启策略,在任何情况下都不会重启容器
  • always:容器总是重新启动
  • on-failure:在容器非正常退出时(退出状态非0),才会重启容器
  • unless-stopped:在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
estart: "no"
restart: always
restart: on-failure
restart: unless-stopped
注:swarm 集群模式,请改用 restart_policy。
secrets
存储敏感数据,例如密码:
version: "3.1"
services:
mysql:
  image: mysql
  environment:
    MYSQL_ROOT_PASSWORD_FILE: /run/secrets/my_secret
  secrets:
    - my_secret
secrets:
  my_secret:
    file: ./my_secret.txt
  • security_opt:修改容器默认的 schema 标签
security-opt:
  - label:user:USER   # 设置容器的用户标签
  - label:role:ROLE   # 设置容器的角色标签
  - label:type:TYPE   # 设置容器的安全策略标签
  - label:level:LEVEL  # 设置容器的安全等级标签
  • stop_grace_period:指定在容器无法处理 SIGTERM (或者任何 stop_signal 的信号),等待多久后发送 SIGKILL 信号关闭容器。
stop_grace_period: 1s # 等待 1 秒
stop_grace_period: 1m30s # 等待 1 分 30 秒 
默认的等待时间是 10 秒。
  • stop_signal:设置停止容器的替代信号。默认情况下使用 SIGTERM
  • 以下示例,使用 SIGUSR1 替代信号 SIGTERM 来停止容器
stop_signal: SIGUSR1
  • sysctls:设置容器中的内核参数,可以使用数组或字典格式
sysctls:
  net.core.somaxconn: 1024
  net.ipv4.tcp_syncookies: 0

sysctls:
  - net.core.somaxconn=1024
  - net.ipv4.tcp_syncookies=0
  • tmpfs:在容器内安装一个临时文件系统。可以是单个值或列表的多个值。
tmpfs: /run
tmpfs:
  - /run
  - /tmp
ulimits
覆盖容器默认的 ulimit。
ulimits:
  nproc: 65535
  nofile:
    soft: 20000
    hard: 40000
  • volumes:将主机的数据卷或着文件挂载到容器里
version: "3"
services:
  db:
    image: postgres:latest
    volumes:
      - "/localhost/postgres.sock:/var/run/postgres/postgres.sock"
      - "/localhost/data:/var/lib/postgresql/data"

7. Docker-Compose Nginx案例一

  • 基于docker-compose构建Nginx容器,并且实现发布目录映射,通过浏览器实现访问,操作步骤如下:

7.1. 编写docker-compose.yml文件,内容如下:

version: "3" 
services:
  nginx:
    container_name: www-nginx
    image: nginx:latest
    restart: always
    ports:
      - 80:80
    volumes:
    - /data/webapps/www/:/usr/share/nginx/html/

7.2. 创建发布目录:/data/webapps/www/,并且在发布目录新建index.html页面

mkdir -p /data/webapps/www/
echo "<h1>www.ys.com Nginx Test pages.</h1>" >>/data/webapps/www/index.html

7.3. 启动和运行docker-compose,启动Nginx容器

docker-compose up -d
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS         PORTS                               NAMES
cdfefbea8594   nginx:latest   "/docker-entrypoint.…"   2 minutes ago   Up 2 minutes   0.0.0.0:80->80/tcp, :::80->80/tcp   www-nginx

7.4. 通过浏览器访问宿主机80端口,即可访问Nginx容器

生产环境docker m集群 docker生产环境实践_docker_02

7.5. docker-compose.yml内容剖析

指令

解释

version

版本号,通常写2和3版本

service

Docker容器服务名称

container_name

容器的名称

restart

设置为always,容器在停止的情况下总是重启

image

docker官方镜像上找到最新版的镜像

ports

容器自己运行的端口号和需要暴露的端口号

volumes

数据卷。表示数据、配置文件等存放的位置。(- . 这个表示docker-compose.yml当前目录)

8. Docker-Compose Tomcat案例二

  • 基于docker-compose构建Nginx容器和Tomcat容器,并且实现Nginx和Tomcat发布目录映射,同时实现nginx均衡tomcat服务,通过浏览器访问Nginx 80端口即访问Tomcat的8080端口,操作步骤如下:

8.1. 编写docker-compose.yml文件

version: "3"
services:
  tomcat01:
    container_name: tomcat01
    image: tomcat:latest
    restart: always
    ports:
      - 8080
  tomcat02:
    container_name: tomcat02
    image: tomcat:latest
    restart: always
    ports:
      - 8080
  nginx:
    container_name: www-nginx
    image: nginx:latest
    restart: always
    ports:
        - 80:80
    volumes:
        - ./default.conf:/etc/nginx/conf.d/default.conf
    links:
        - tomcat01
        - tomcat02

8.2. 创建nginx默认配置文件:default.conf,内容如下:

vim /data/default.conf

upstream tomcat_web {
        server tomcat01:8080 max_fails=2 fail_timeout=15;
        server tomcat02:8080 max_fails=2 fail_timeout=15;
}
server {
    listen       80;
    server_name  localhost;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        proxy_pass http://tomcat_web;
        proxy_set_header host $host;
    }
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

8.3. 创建tomcat1和tomcat2网页文件

[root@localhost ~]# docker exec -it tomcat01 /bin/bash
root@58bcbf453d69:/usr/local/tomcat# mkdir webapps/ROOT
root@58bcbf453d69:/usr/local/tomcat# echo wo shi ys > webapps/ROOT/index.jsp

[root@localhost ~]# docker exec -it tomcat02 /bin/bash
root@c221423b1ded:/usr/local/tomcat# mkdir webapps/ROOT
root@c221423b1ded:/usr/local/tomcat# echo wo shi sxy > webapps/ROOT/index.jsp

8.4. 启动Docker-compose

[root@localhost ~]# docker-compose up -d
[+] Running 9/9
 ✔ tomcat02 7 layers [⣿⣿⣿⣿⣿⣿⣿]      0B/0B      Pulled                                                                         264.6s
   ✔ 74ac377868f8 Pull complete                                                                                                77.7s
   ✔ a182a611d05b Pull complete                                                                                                78.9s
   ✔ ad4fe29a3001 Pull complete                                                                                               228.3s
   ✔ 9d52462c5181 Pull complete                                                                                               228.3s
   ✔ ac04a5bb8dd2 Pull complete                                                                                               228.4s
   ✔ 9477858ddf22 Pull complete                                                                                               228.9s
   ✔ cc2062ac4c6a Pull complete                                                                                               229.0s
 ✔ tomcat01 Pulled                                                                                                            264.6s
WARN[0264] Found orphan containers ([mysql-db]) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
[+] Running 3/3
 ✔ Container tomcat02   Started                                                                                                 1.1s
 ✔ Container tomcat01   Started                                                                                                 1.0s
 ✔ Container www-nginx  Started

[root@localhost ~]# docker ps
CONTAINER ID   IMAGE           COMMAND                   CREATED          STATUS          PORTS                                                  NAMES
a6b585276f8c   nginx:latest    "/docker-entrypoint.…"   12 minutes ago   Up 12 minutes   0.0.0.0:81->80/tcp, :::81->80/tcp                      www-nginx
7d6037beb05a   tomcat:latest   "catalina.sh run"         12 minutes ago   Up 12 minutes   0.0.0.0:32769->8080/tcp, :::32769->8080/tcp            tomcat02
bb9aa0c16d9e   tomcat:latest   "catalina.sh run"         12 minutes ago   Up 12 minutes   0.0.0.0:32768->8080/tcp, :::32768->8080/tcp            tomcat01
9f0cf4b99612   mysql:latest    "docker-entrypoint.s…"   30 minutes ago   Up 30 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-db

8.5. 通过浏览器直接访问Nginx容器,默认访问宿主机的80端口即可,如图所示:

生产环境docker m集群 docker生产环境实践_生产环境docker m集群_03