前言
前面我们回顾了docker的一些基本概念即运维操作命令,包括容器的启动原理,镜像,仓库,仓库注册,命令行启动一个容器实例,dockfile文件定义一个独立应用容器,那当我们启动多个容器,甚至想简化多个应用容器的管理,减少命令行的复杂参数,那又该如何管理和操作呢?其实,docker作为成熟的软件,已经给我们提供了这些解决方案,下面让我们看下Docker Compose、Docker Machine、Docker Swarm 集群管理是如何进行的。
一、Docker Compose(早期的容器编排)
Docker-compose 是一个用于定义和运行多容器 Docker 应用程序的开源工具。使用 docker-compose,就可以使用 YAML 文件(compose使用的结构化文件)来自由配置我们应用程序的服务,并一键从这个配置中创建并启动所有服务。Compose 文件( Compose file format)是用于定义组成应用程序的一个或多个容器的配置方式。一旦你有了一个 Compose 文件,就可以使用一个命令来创建和启动你的应用程序:docker compose up。
docker-compose 适用于所有环境:生产、登台、开发、测试以及 CI 工作流程,使用它来管理一组相关联的的应用容器。目前,Docker Compose V2 是 Docker Compose 的主要版本升级版本。它已经用 Golang 从头开始完全重写(V1 是用 Python 编写的)。v2版本中,docker-compose不在是一个独立的二进制文件,且它的安装脚本可视情况编辑适配调整,提供了更大的自由度。当然,官方也提供了v1到v2的二进制文件转化,可参考 compose-switch,Compose Switch 是 Compose V1 docker-compose (python) 可执行文件的替代品。它将命令行转换为 Compose V2 docker compose,然后运行v2;
官方项目地址:https://github.com/docker/compose
官方文档:https://docs.docker.com/compose/
1)概念
2)安装
#ubuntu
sudo apt install docker-compose
docker-compose --version
#centos
wget https://github.com/docker/compose/releases/download/v2.11.1/docker-compose-linux-x86_64
wget https://github.com/docker/compose/archive/refs/tags/v2.11.1.tar.gz #源码包
mv/tmp/docker-compose-Linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
#启动docker
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": [
"https://hub-mirror.c.163.com",
"https://mirror.ccs.tencentyun.com",
"https://reg-mirror.qiniu.co"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3)docker-compose.yml示例:
docker-compose默认的模板文件名称为 docker-compose.yml;注意这里定义的每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像。如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD, EXPOSE, VOLUME, ENV 等) 将会自动被获取,无需在 docker-compose.yml 中重复设置。
version: "3.9" # optional since v1.27.0
services:
web:
build: . #指定为构建镜像的上下文路径,以当前目录所有文件进行镜像构建,读取./Dockerfile文件
ports:
- "5000:5000"
volumes:
- .:/tomcat
- logvolume01:/var/log
links:
- redis
redis:
image: redis
volumes:
logvolume01: {}
确认无误后,执行docker-compose up -d启动;
示例2:
version: '3' #指定本 yml 依从的 compose 哪个版本制定的
services:
elasticsearch:
image: elasticsearch:6.8.5
container_name: elasticsearch
restart: always
volumes: #将主机的数据卷或着文件挂载到容器里,用:分隔
- "/app/skywalking/elasticsearch/data:/usr/share/elasticsearch/data:rw"
- /app/skywalking/elasticsearch/conf/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- /app/skywalking/elasticsearch/conf/jvm.options:/usr/share/elasticsearch/config/jvm.options
- /app/skywalking/elasticsearch/logs:/usr/share/elasticsearch/logs:rw
environment:
- TZ=Asia/Shanghai
- xpack.monitoring.enabled=false
- xpack.watcher.enabled=false
ports:
- "9200:9200"
- "9300:9300"
ulimits:
nproc: 65535
nofile:
soft: 20000
hard: 40000
environment:
- SW_STORAGE= elasticsearch
- SW_STORAGE_ES_CLUSTER_NODES=elasticsearch:9200
示例3:
version: '3.3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.8.5
container_name: elasticsearch
restart: always
ports:
- 9200:9200
- 9300:9300
environment:
discovery.type: single-node
ulimits:
memlock:
soft: -1
hard: -1
oap:
image: skywalking/oap
container_name: oap
depends_on:
- elasticsearch
links:
- elasticsearch
restart: always
ports:
- 11800:11800
- 12800:12800
environment:
SW_STORAGE: elasticsearch
SW_STORAGE_ES_CLUSTER_NODES: elasticsearch:9200
ui:
image: skywalking/ui
container_name: ui #指定自定义容器名称,而非生成的默认名称
depends_on: #设置依赖关系
- oap
links:
- oap
restart: always
ports:
- 8080:8080
environment:
SW_OAP_ADDRESS: oap:12800
完成后,执行docker-compose -f /app/skywalking.yml up -d,然后浏览器访问8080验证
示例4:
version: "3.7"
services:
webapp:
build:
context: ./dir //上下文路径,构建时采用./dir/dockerfile文件里的规则
dockerfile: Dockerfile-alternate //指定构建镜像的 Dockerfile 文件名
args:
buildno: 1 //加构建参数,是只能在构建过程中访问的环境变量
labels: //设置构建镜像的标签
- "com.example.description=Accounting webapp"
- "com.example.department=Finance"
- "com.example.label-with-empty-value"
target: prod //多层构建,可以指定构建哪一层
示例5:
version: "3.7"
services:
redis:
image: redis:alpine
deploy: #指定与服务的部署和运行有关的配置。只在 swarm 模式下才会有用
mode:replicated #指定服务提供的模式;其中,replicated:复制指定服务到集群的机器上;global:全局服务,服务将部署至集群的每个节点
replicas: 6 #当mode为replicated 时,需使用此参数配置具体运行的节点数量
endpoint_mode: dnsrr
labels: #在服务上设置标签。可以用容器上的 labels(跟 deploy 同级的配置) 覆盖 deploy 下(服务)的labels
description: "This redis service label"
extra_hosts: #添加主机名映射,容器创建后会在此服务的内部容器中 /etc/hosts 创建一个具有 ip 地址和主机名的映射关系:
- "somehost:162.242.195.82"
- "otherhost:50.31.209.229"
resources: #配置服务器资源使用的限制
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
sysctls: #置容器中的内核参数,可以使用数组或字典格式
- net.core.somaxconn=1024
- net.ipv4.tcp_syncookies=0
ulimits: #覆盖容器默认的 ulimit
nproc: 65535
nofile:
soft: 20000
hard: 40000
restart_policy: #配置如何在退出容器时重新启动容器
condition: on-failure #可选 none,on-failure 或者 any(默认值:any)
delay: 5s #设置多久之后重启(默认值:0)
max_attempts: 3 #尝试重新启动容器的次数,超出次数,则不再尝试(默认值:一直重试)
window: 120s #设置容器重启超时时间(默认值:0)
healthcheck: #检测 docker 服务是否健康运行
test: ["CMD", "curl", "-f", "http://localhost"] # 设置检测程序
interval: 1m30s # 设置检测间隔
timeout: 10s # 设置检测超时时间
retries: 3 # 设置重试次数
start_period: 40s # 启动后,多少秒开始启动检测程序
4)docker compose使用
参数:
示例:
eg1:docker-compose -f web.yml config //此命令不会执行真正的操作,而是显示 docker-compose 程序解析到的配置文件内容
eg2:docker-compose -f web.yml images //列出 Compose 文件中包含的镜像
eg3:docker-compose -f web.yml ps //列出项目中目前的所有容器
eg4:docker-compose -f web.yml build //类似于docker build,构建(重新构建)项目中的服务容器
eg5:docker-compose -f skywalking.yml up //自动完成包括构建镜像,(重新)创建服务,启动服务,并关联服务相关容器的一系列操作;默认情况,docker-compose up 启动的容器都在前台,控制台将会同时打印所有容器的输出信息,一般多用于调试,生产加-d参数可指定运行后台;如果服务容器已经存在,docker-compose up 将会尝试停止容器,然后重新创建(保持使用 volumes-from 挂载的卷),以保证新启动的服务匹配 docker-compose.yml 文件的最新内容。如果用户不希望容器被停止并重新创建,可以使用 docker-compose up --no-recreate,这样将只会启动处于停止状态的容器,而忽略已经运行的服务。如果用户只想重新部署某个服务,可以使用 docker-compose up --no-deps -d <SERVICE_NAME> 来重新创建服务并后台停止旧服务,启动新服务,并不会影响到其所依赖的服务。其中,--no-color表不使用颜色来区分不同的服务的控制台输出;--no-deps表不启动服务所链接的容器;--force-recreate指定强制重新创建容器,不能与 --no-recreate 同时使用;--no-recreate 如果容器已经存在了,则不重新创建,不能与 --force-recreate 同时使用;--no-build 不自动构建缺失的服务镜像;-t(--timeout)指定停止容器时候的超时(默认为 10 秒)
eg6:docker-compose -f web.yml down //停止用up命令所启动的容器并移除网络
eg7:docker-compose -f web.yml stop Nginx //停止已经处于运行状态的容器,但不删除它。通过 docker-compose start 可以再次启动这些容器,如果不指定service则默认停止所有的容器,还可以使用-t, --timeout TIMEOUT 停止容器时候的超时(默认为 10 秒)
eg8:docker-compose -f web.yml start Nginx //启动已经存在的服务容器,同样适用于restart
eg9:docker-compose -f web.yml logs //查看整体的日志
eg10:docker-compose -f web.yml logs Nginx //查看某一指定容器的日志
注意:
5) Docker Compose构建三步骤
6)dockerfile其他配置项
endpoint_mode: vip # Docker 集群服务一个对外的虚拟 ip。所有的请求都会通过这个虚拟 ip 到达集群服务内部的机器。
endpoint_mode: dnsrr # DNS 轮询(DNSRR)。所有的请求会自动轮询获取到集群 ip 列表中的一个 ip 地址
二、Docker Machine:虚拟宿主机管理
Docker Machine 是一个简化 Docker 安装的命令行工具,通过一个简单的命令行即可在相应的平台上安装 Docker,比如 VirtualBox、 Digital Ocean、Microsoft Azure。它使用go语言编写,可使用不同引擎在多种平台上快速的安装Docker环境,允许我们在虚拟宿主机上安装Docker,并使用docker-machine命令管理这些宿主机,也可以启动、审查、停止、重启托管的docker ,升级Docker客户端和守护程序并配置docker客户端和宿主机通信,即完成更多任务的编排管理。
应用场景:
项目地址:https://github.com/docker/machine
官方文档:https://docs.docker.com/desktop/
Docker Machine允许我们在虚拟宿主机上安装Docker Engine引擎,并使用docker-machine命令管理宿主机(这里实际也是虚拟的,我们也叫虚拟主机)。可以使用本地的Mac、Linux,或Windows上创建和使用Docker宿主机。它可通过创建一个安装好的docker虚拟机并设置对应的环境变量,使本地docker工具获得透明远程操作虚拟机的能力,从而使本身不支持docker的windows和mac能够直接使用docker命令。Docker Desktop 易于安装,适用于 Mac、Linux 或 Windows 环境,可很方便就实现构建和共享容器化应用程序和微服务。如下所示,远程管理docker实例:
再来回顾下,我们说的Docker实际上指的就是Docker Engine(引擎),它是一个CS应用,由Docker守护进程、REST API指定与守护进程交互的接口、CLI命令行接口与守护进程通信(通过封装REST API),Docker Engine从CLI中接收docker命令。如下所示:
1)Docker Machine与Docker的关系
Docker Machine主要用于配置和管理Docker Engine宿主机,通常在维护人员本地OS上安装。Docker Machine有自己的CLI命令行客户端工具docker-machine和Docker Engine客户端工具docker。可以使用Docker Machine在一个或多个虚拟系统/主机上安装Docker Engine,比如:快速的给 100 台服务器安装上 docker。这些虚拟系统可以是本地也可以是远程的,比如:云供应商,如阿里云,腾讯云,AWS,或 DigitalOcean上的云主机。Dockerized宿主机本身可以认为是被管理的machine。
2)软件安装
注意:安装 Docker Machine 之前需要先安装 Docker。
#Linux
$ curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/tmp/docker-machine && //-L下载到本地
chmod +x /tmp/docker-machine &&
sudo cp /tmp/docker-machine /usr/local/bin/docker-machine
#安装自动补全功能
yum -y install bash-completion
scripts=( docker-machine-prompt.bash docker-machine-wrapper.bash docker-machine.bash ); for i in "${scripts[@]}"; do wget https://raw.githubusercontent.com/docker/machine/v0.16.2/contrib/completion/bash/${i} -P /etc/bash_completion.d; done
vim ~/.bashrc //确保有如下
source /etc/bash_completion.d/docker-machine-wrapper.bash
source /etc/bash_completion.d/docker-machine-prompt.bash
source /etc/bash_completion.d/docker-machine.bash
PS1='[\u@\h \W$(__docker_machine_ps1)]\$ '
#完成后生效
source ~/.bashrc
#客户端主机,即docker-machine的安装主机,配置ssh免密登录
ssh-keygen
#将上述生成keys拷贝到创建的虚拟host里
ssh-copy-id root@vhost_ip
#完成后,验证是否可以免密登录
ssh root@vhost_ip
#windows中需使用一个git bash工具
curl -L https://objects.githubusercontent.com/github-production-release-asset-2e65be/23216272/2c9b0433-013d-483f-8c1c-256e88ec86f3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIWNJYAX4CSVEH53A%2F20220924%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20220924T061211Z&X-Amz-Expires=300&X-Amz-Signature=3f7e092d389d75ce0b47a756e218c3aae47e1e4329da02e0dcf8bb2dcd673683&X-Amz-SignedHeaders=host&actor_id=0&key_id=0&repo_id=23216272&response-content-disposition=attachment%3B%20filename%3DGit-2.37.3-64-bit.exe
if [[ ! -d "$HOME/bin" ]]; then mkdir -p "$HOME/bin"; fi && \
curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-Windows-x86_64.exe > "$HOME/bin/docker-machine.exe" && \
chmod +x "$HOME/bin/docker-machine.exe"
#Mac OS
$ curl -L https://github.com/docker/machine/releases/download/v0.16.2/docker-machine-`uname -s`-`uname -m` >/usr/local/bin/docker-machine && \
chmod +x /usr/local/bin/docker-machine
#验证
docker-machine version
3)命令使用
注:对于docker machine来将,术语Machine就是运行docker daemon的主机,创建machine就是在host上安装docker引擎;
docker-machine ls //列出可用的机器
#创建一台虚拟宿主机
docker-machine create --driver virtualbox test //--driver:指定用来创建机器的驱动类型,这里是 virtualbox;该命令执行后会创建一台虚拟主机,并在其上安装好docker引擎,配置好ssh远程登录等
docker-machine ls //验证,查看列出可用的机器里这时已经有上一步创建的机器,active列显示 * 表激活,-表未激活;对于未被激活的,发布全局变量
export DOCKER_HOST="tcp://192.168.1.11:80"
docker-machine env test //验证
docker-machine active
docker-machine create --driver generic --generic-ip-address=192.168.1.12 docker12 //创建vhost时还可指定ip地址,同时配置vhost的主机名也未docker12;输出类似如下:
Running pre-create checks...
Creating machine...
(docker12) No SSH key specified. Assuming an existing key at the default location.
Waiting for machine to be running, this may take a few minutes...
Detecting operating system of created instance...
Waiting for SSH to be available...
Detecting the provisioner...
Provisioning with centos...
Copying certs to the local machine directory...
Copying certs to the remote machine...
Setting Docker configuration on the remote daemon...
Checking connection to Docker...
Docker is up and running!
To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env docker12
docker-machine ip test //查看虚拟主机test的ip地址,这里的test为虚拟主机的名称
docker-machine stop test //关停虚拟主机
docker-machine start test
docker-machine ssh test //连入虚拟主机
docker-machine active //查看当前激活状态的虚拟主机,会显示虚拟主机的名称
echo $DOCKER_HOST //查看被激活虚拟主机的url(tcp连接)
docker-machine status default //查看docker宿主机的状态
docker-machine kill default
docker-machine ls //指定地址后创建的vhost
NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS
docker12 - generic Running tcp://192.168.1.12:2376 v18.06.1-ce
#登录docker12主机查看:
ssh root@192.168.1.12
cat /etc/systemd/system/docker.service.d/10-machine.conf //输出如下
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H unix:///var/run/docker.sock --storage-driver devicemapper --tlsverify --tlscacert /etc/docker/ca.pem --tlscert /etc/docker/server.pem --tlskey /etc/docker/server-key.pem --label provider=generic
Environment=
//其中,-H tcp://0.0.0.0:2376 使docker daemon接受远程连接;--tls*对远程连接启用安全认证和加密
//查看docker12的环境变量
docker-machine env docker12 //输出如下
export DOCKER_TLS_VERIFY="1"
export DOCKER_HOST="tcp://192.168.1.12:2376"
export DOCKER_CERT_PATH="/root/.docker/machine/machines/docker12"
export DOCKER_MACHINE_NAME="docker12"
# Run this command to configure your shell:
# eval $(docker-machine env docker188)
eval $(docker-machine env docker12) //配置vhost的shell环境;执行后,可以看到,命令提示符变成了docker12,这是因为之前在/root/.bashrc里面配置了 PS1='[\u@\h \W$(__docker_machine_ps1)]\$ ',用于显示当前的docker host;如果我们输入eval $(docker-machine env docker12)没有显示出docker12的命令提示符,可以重新输入一遍 PS1='[\u@\h \W$(__docker_machine_ps1)]\$ ';这样的话,我们就无需ssh到vhost上,在此状态下执行的docker命令就相当于在docker12上执行了
~[docker188]]# docker ps //验证,查看当前是否有运行docker实例
//配置链接vhost docker12的ssl:
docker-machine config docker12
--tlsverify
--tlscacert="/root/.docker/machine/machines/docker12/ca.pem"
--tlscert="/root/.docker/machine/machines/docker12/cert.pem"
--tlskey="/root/.docker/machine/machines/docker12/key.pem"
-H=tcp://192.168.1.12:2376
docker-machine inspect docker12 //查看docker宿主机的更新信息
docker-machine regenerate-certs default //为docker宿主机重新生成TLS认证信息
其他选项:
config:查看当前激活状态 Docker 主机的连接信息。
env:显示连接到某个主机需要的环境变量
inspect: 以 json 格式输出指定Docker的详细信息
kill: 直接杀死指定的 Docker 主机
provision: 重新配置指定主机
regenerate-certs: 为某个主机重新生成 TLS 信息
rm: 删除某台 Docker 主机,对应的虚拟机也会被删除
scp: 在 Docker 主机之间以及 Docker 主机和本地主机之间通过 scp 远程复制数据
mount: 使用 SSHFS 从计算机装载或卸载目录
status: 获取指定 Docker 主机的状态(包括:Running、Paused、Saved、Stopped、Stopping、Starting、Error)等
upgrade: 将一个指定主机的 Docker 版本更新为最新
url: 获取指定 Docker 主机的监听 URL
version: 显示 Docker Machine 的版本或者主机 Docker 版本
help: 显示帮助信息
--engine-insecure-registry option 以键值对格式指定所创建Docker引擎允许访问的不支持认证的注册仓库服务;
--engine-registry-mirror option 指定使用注册仓库镜像;
--engine-label option 为所创建的Docker引擎添加标签;
--engine-storage-driver 存储后端驱动类型;
--engine-env option 指定环境变量;
--swarm 指定使用Swarm;
--swarm-image"swarm:latest" 使用Swarm时候采用的镜像;
--swarm-master 配置机器作为Swarm集群的master节点;
--swarm-discovery Swarm集群的服务发现机制参数;
--swarm-strategy"spread" Swarm默认调度策略;
--swarm-opt option 任意传递给Swarm的参数;
--swarm-host"tcp://0.0.0.0:3376" 指定地址将监听 Swarm master节点请求;
--swarm-addr 从指定地址发送广播加入Swarm集群服务。
eg1:
docker-machine create -d virtualbox \
--engine-storage-driver overlay \
--engine-label name=test1 \
--engine-label year=2022 \
--engine-opt dns=8.8.8.8 \
--engine-env HTTP_PROXY=http://proxy.com:3128 \
--engine-insecure-registry registry.private.com \
vHost1
4)docker-machine创建虚拟主机受支持的平台及驱动引擎
三、Docker Swarm 集群管理
Docker Swarm 是 Docker 的集群管理工具。它将 Docker 主机池转变为单个虚拟 Docker 主机。 swarm 集群由管理节点(manager)和工作节点(work node)构成。
更多,参看《微服务之Docker swarm集群管理》;
四、场景案例
五、Docker Desktop
Docker Desktop是一个面向开发人员的生产力工具和本地 Kubernetes 环境。Docker Desktop 是适用于 MacOS 和 Windows 机器,可用于在他们之间构建和共享容器化应用程序。访问 Docker Desktop只需按照引导在几分钟内就可构建一个容器化应用程序。它提供了一个简单的界面,使我们能够直接从本地机器管理我们的容器、应用程序和精心,而无需使用 CLI 来执行一些核心操作,它还可以访问 Docker Hub 中大量经过认证的mages和模板库,很方便我们再docker容器平台上快速搭建一套应用环境;Docker Desktop 对小型企业(少于 250 名员工和年收入低于 1000 万美元)和免费供个人使用、教育和非商业开源项目使用,对大企业收费(注意:付费订阅是 Docker,而不是 Docker Desktop。);官方解释说:Docker Desktop 是开源和闭源软件的混合体,它是 Docker Desktop 许可变更适用的闭源位。这意味着所有二进制文件(Docker Engine、Docker Daemon、Docker CLI、Docker Compose、BuildKit、库等)和任何开源代码都将继续免费。
官网: https://www.docker.com/products/docker-desktop/
1)Docker Desktop vs Docker Engine
2)安装
参考1:Linux环境安装,参考Linux环境安装文档,安装条件:
参考2:windows环境安装文档;另外,需要window环境WSL 2支持,Windows Subsystem for Linux(简称WSL)是一个在Windows 10\11上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层,它是一些组件的集合,允许原生的Linux ELF64二进制文件跑在Windows上。它同时包括了用户态和内核态组件,旨在实现使纯正的Ubuntu、Debian等映像能下载和解压到用户的本地计算机,并且映像内的工具和实用工具能在此子系统上原生运行。另外,它需要64位win10以上OS、支持硬件虚拟化和4G内存;要运行 Windows 容器,您需要 Windows 10 或 Windows 11 专业版或企业版。 Windows 家庭版或教育版仅允许您运行 Linux 容器。
wget https://desktop.docker.com/win/main/amd64/Docker%20Desktop%20Installer.exe
六、Docker参考
Docker 国内镜像: