在使用 docker run 命令启动 Docker 容器时, 如果需要进行端口映射, 目录挂载, 网络信息等配置, 整条命令将变得非常长, 并且由于是一条 shell 命令, 修改和复用也不方便. 我们在大规模部署容器的时候不可能手动去输入众多的命令, 所以需要一些工具来辅助我们实现 docker run 命令的编写, 同时实现简单快捷的大规模部署.
docker-compose 部署
docker-compose 是一个读取特定格式的 YAML 文件并将其转换为 docker run 命令的工具, 它有效的规避了上述的问题, 并且它也是 docker swarm,docker stack 等技术的基石. docker-compose 需要一份 YAML 格式的脚本, 如果在使用命令时不想指定具体的脚本名称, 那就需要将脚本命名为 docker-compose.YAML. 下面是一份启动 MySQL 容器的 docker-compose 脚本.
- version: "3"
- services:
- MySQL:
- container_name: login_db
- image: MySQL:5.7
- ports:
- - "3306:3306"
- environment:
- - MYSQL_ROOT_PASSWORD=123456
- volumes:
- - "mysql-data:/var/lib/mysql"
- networks:
- - my-bridge
- volumes:
- MySQL-data:
- networks:
- my-bridge:
- driver: bridge
全局配置
version 指定的是 docker-compose 的版本, 由于 v2 和 v3 在语法上存在一些不同, 所以需要明确告诉 docker-compose 当前脚本所使用的语法版本是多少.
services 表示服务定义. 一份脚本中可以定义多个服务, docker-compose 会一并启动.
volumes 下的名称列表就是服务启动时要创建的所有数据卷的名称, 只有先创建了数据卷才能在下面的服务定义中的 volumes 配置中进行挂载使用. 注意区分全局的 volumes 和服务定义下的 volumes 配置.
networks 下配置的是服务启动时要创建的网络及其驱动类型. 这里创建了一个驱动为 bridge, 名称为 my-bridge 的桥接网络. 只有先创建了网络才能在下面的服务定义中的 networks 配置中进行注册使用. 注意区分全局的 networks 和服务定义下的 networks 配置.
服务配置
MySQL 表示定义一个名叫 MySQL 的服务.
container_name 表示服务要启动的容器的名称, 如果这个服务要动态扩展多个容器, 则不可以指定容器名称, 否则由于容器名称冲突将导致无法扩展.
image 表示服务要使用的镜像.
ports 表示容器与宿主机的端口映射关系. 凡是指定了端口映射关系的服务都不能动态扩展容器数量, 因为会导致端口冲突.
environment 表示要设置到容器中的环境变量. 这里设置的环境变量将被放置到容器的全局环境变量中, 你可以在容器中读取并操作.
volumes 表示要挂载的目录或者数据卷. 这里和 docker run 命令中的 -v 参数作用是一致的, 即可以挂载数据卷, 也可以挂载目录. 这里使用到的数据卷必须在全局配置中先指定, 如果是挂载目录则需要先手动创建.
networks 表示这个服务要注册到哪些网络上去, 这里使用到的网络必须在全局配置中先指定. 注册到同一个网络上的容器之间可以使用服务名进行通信.
使用 docker-compose
通过 docker-compose 可以对服务进行启动, 停止, 删除, 扩容等操作. docker-compose 的操作必须依赖脚本, 如果脚本存在于当前目录下且名为 docker-compose.YAML 则不需要额外指定, 否则需要使用 -f 参数进行指定.
启动服务
启动服务使用命令 docker-compose -f /path/to/script.YAML up -d,up 表示启动服务,-d 表示后台运行. 这个命令会读取脚本文件并首先创建申明的数据卷和网络, 然后再启动服务.
停止服务
停止服务使用命令 docker-compose -f /path/to/script.YAML stop. 这个命令会将脚本中的所有服务的所有容器都停止, 但不会删除容器.
删除服务
删除服务使用命令 docker-compose -f /path/to/script.YAML rm. 这个命令会要求二次确认删除, 并且无法删除未停止的服务. 删除服务时不会关联删除服务启动时创建的网络和数据卷.
强行删除服务
强行删除服务使用命令 docker-compose -f /path/to/script.YAML down. 这个命令会将所有服务的所有容器都停止并删除, 同时删除服务启动时创建的网络, 但不会删除数据卷.
扩容服务
随着业务量的上升, 我们可能需要将服务从一个容器扩展到多个容器以提高服务能力, 这时候就可以使用 docker-compose 来直接扩容服务.
docker-compose -f /path/to/script.YAML up --scale orderService=3 -d
这个命令表示将名为 orderService 的服务扩容至三个容器并后台启动. 如果原本的容器数量大于 3 个, 那么这个命令就是缩减容器数量操作. 需要注意的是, 支持服务扩容的要求是非常苛刻的, 需要满足以下三点要求:
不能够指定 container_name, 即容器名;
不能够指定端口映射关系;
不能够指定挂载数据卷或目录.
如果在脚本中指定了要挂在的目录或者数据卷, 那么扩容后多个容器将共用一个数据卷和目录, 这样就会导致数据出现混乱. 解决方法是不指定任何数据卷和目录进行挂载, 由 Docker 自行创建随机名称的数据卷.
Docker Swarm 部署
上文讲到的 docker-compose 部署方式还停留在单机部署上, 但在实际生产环境中不同系统的 Docker 容器都是垮宿主机部署, 这时候就需要将这些宿主机形成集群统一管理, Docker Swarm 就是 Docker 原生提供的一种集群管理模式. 除了 Docker Swarm 外, 还有 Mesos,Kubernates 等不同的集群管理模式.
在 Docker Swarm 集群模式下, 当多个宿主机形成集群后, 我们就可以在管理节点 (Manager Node) 上通过管理命令将不同服务的容器部署到集群内不同的宿主机上, 同一个服务的多个容器也可以分布到集群内不同的宿主机上以实现负载均衡.
创建 Swarm 集群
创建集群之前需要先规划好集群内的节点角色, 选择其中一台宿主机作为管理节点开始创建集群, 执行如下命令:
docker swarm init --advertise-addr = 本机 IP
--advertise-addr 用于指定管理节点所在宿主机的 eth0 网卡的 IP 地址, 如果存在多个网卡, 这个参数一定要指定, 否则可能造成管理节点和工作节点之间无法通信. 命令执行完毕后会输出如下的提示信息:
- Swarm initialized: current node (gmdscjfdlubanwl7i75z5cc85) is now a manager.
- To add a worker to this swarm, run the following command:
- docker swarm join \
- --token SWMTKN-1-6djatxtetutac68xd1u8v1icnyv6t0pcplhaph2irqqxqo1m2b-8w6lq2kpw6j1chqpu4vlf2cx3 \
管理节点 IP:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
根据输出提示, 我们需要在其他宿主机上执行 docker swarm join ... 操作以使其加入到集群作为工作节点. 集群节点加入完成后在管理节点执行 docker node ls 可以看到所有的节点状态信息.
- ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS
- gmdscjfdlubanwl7i75z5cc85 * docker-1 Ready Active Leader
- xna7a0h6a0xhct95kh7v6p9pl docker-3 Ready Active
使用标签标记节点
- ID NAME IMAGE NODE ESIRED STATE CURRENT STATE ERROR PORTS
- 0m5erytxi6sa MySQL.1 MySQL:5.7 docker-1 Running Running 3 minutes ago
- ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
- 0m5erytxi6sa MySQL.1 MySQL:5.7 docker-1 Running Running 13 minutes ago
- idgvqymekwam MySQL.2 MySQL:5.7 docker-3 Running Running 3 minutes ago
- fldlrega7p40 MySQL.3 MySQL:5.7 docker-3 Running Running 3 minutes ago
- version: '3'
- services:
- WordPress:
- image: WordPress
- ports:
- - 80:80
- environment:
- - WORDPRESS_DB_HOST=MySQL
- - WORDPRESS_DB_PASSWORD=123456
- networks:
- - my-network
- depends_on:
- - MySQL
- deploy:
- mode: replicated
- replicas: 3
- restart_policy:
- condition: on-failure
- delay: 5s
- max_attempts: 3
- update_config:
- parallelism: 1
- delay: 10s
- MySQL:
- image: MySQL:5.7
- environment:
- - MYSQL_ROOT_PASSWORD=123456
- - MYSQL_DATABASE=WordPress
- volumes:
- - MySQL-data:/var/lib/MySQL
- networks:
- - my-network
- deploy:
- mode: global
- placement:
- constraints: [node.labels.mytag == db]
- volumes:
- MySQL-data:
- networks:
- my-network:
- driver: overlay
- networks:
- my-network:
- external: true
来源: https://juejin.im/post/5c6f524e6fb9a049f23d5ebe