docker高级
文章目录
- 1.Docker Compose
- 1.1 介绍
- 1.2 compose文件
- 1.3 常用命令
- 1.4 安装
- 1.5 项目说明和构建
- 1.5.1 手工启动
- 1.5.2 compose 编排启动
- 1.5.3 完善 compose.yml
- 1.5.4 加入前端容器
- 2.UI管理平台
- 2.1 portainer
- 3.镜像发布
- 3.1 阿里云
- 3.2 Docker Registry
- 3.2.1 介绍
- 3.2.2 安装
- 3.2.3 测试
- 3.2.4 https 问题
- 方法1.配置 Docker 客户端允许 HTTP 连接
- 方法2.使用 HTTPS 配置 Registry(推荐)
- 5.Docker Swarm
- 5.1 简介
- 5.1.1 节点
- 5.1.2 服务、任务、容器
- 1.2 swarm集群
- 5.3 节点维护
- 5.3.1 退群进群
- worker 节点
- manager 节点
- 5.3.2 更改角色 (升级降级)
- 5.3.3 节点标签
- 5.4.1 开启 autolock
- 5.4.2 状况模拟
- 5.5 创建服务
- 5.6 服务的负载均衡
- 1.7 扩容缩容与可用性
- 1.7.1 扩容缩容
- 5.7.2 availability 可用性
- 1.8 全局模式部署
1.Docker Compose
1.1 介绍
对于现在应用来说,大多都是通过很多的微服务互相协同组成的一个完整应用。
例如订单管理、用户管理、品类管理、缓存服务、数据库服务等,它们构成了一个电商平台的应用。
部署和管理大量的服务容器是一件非常繁琐的事情,而 Docker Compose 就是解决这类问题的。
Docker Compose 是一个需要在 Docker 主机上进行安装的 Docker 容器编排外部工具。
其并不是通过脚本或各种冗长的 Docker 命令来将应用组件组织起来的,而是通过一个声明式的配置文件描述整个应用,然后通过一条命令完成应用部署的。
部署成功后,还可通过一系列简单命令实现对其完整生命周期的管理。
1.2 compose文件
Docker Compose 使用 YAML 文件来定义服务,官方推荐的默认文件名为 compose.yml 但同时也支持 docker-compose.yml。
由于一个 compose 文件中定义的是一个项目的所有服务,所以一般为在创建 compose 文件之前先新建一个目录,目录名称一般为项目名称,然后再将项目所需的所有镜像、微服务的 Dockerfile放入该目录,并在该目录中新建 compose 文件。
compose 文件中包含6个顶级属性:version、services、networks、volumes、configs 与 secrets,它们下面还包含很多属性。
官方:https://docs.docker.com/reference/compose-file/
1.3 常用命令
官方:https://docs.docker.com/reference/cli/docker/compose/
-
docker-compose pull
拉取 compose 中服务依赖的全部镜像或指定镜像,通过在命令后添加服务名称来指定。
-
docker-compose config
检査 compose 文件是否正确,可添加选项-q,表示只有存在问题时才有输出。
-
docker-compose up
启动 compose 中的所有容器,-d 选项表示后台启动。
-
docker-compose down
停止并移除 compose 中的所有容器、网络
-
docker-compose logs
查看 comopse 中所有服务或指定服务的运行日志,通过在命令后添加服务名称来指定。
默认情况下,将对不同的服务日志使用不同的颜色来区分。 -
docker-compose ps
列出 compose 中所有服务或指定服务,通过在命令后添加服务名称来指定。
-
docker-compose top
列出 compose 中当前正在运行的所有服务或指定服务,通过在命令后添加服务名称来指定。
-
docker-compose images
列出 compose 中所有服务或指定服务对应的镜像,通过在命令后添加服务名称来指定。 -
docker-compose port
列出指定服务容器的指定端口所映射的宿主机端口。
-
docker-compose run
用于在已经运行的服务中启动一个新的容器。与 docker-compose up 命令不同,docker-compose run 命令可以单独启动一个容器,而不是启动所有定义的服务。 -
docker-compose exec
进入指定服务容器,通过在命令后添加服务名称来指定。
-
docker-compose pause
暂停 compose 中所有服务容器或指定服务容器,通过在命令后添加服务名称来指定。 -
docker-compose unpause
恢复 compose 中处于暂停状态的所有服务容器或指定服务容器,通过在命令后添加服务名称来指定。 -
docker-compose stop
在不移除容器的情况下停止运行容器。可以通过docker compose start 重新启动容器。 -
docker-compose start
启动服务或现有容器。
-
docker-compose restart
重新启动所有已停止和正在运行的服务,或仅重新启动指定的服务。
-
docker-compose kill
通过发送 SIGKILL 信号强制运行的容器停止,可以选择性地传递该信号。
-
docker-compose rm
移除已停止的服务容器。
1.4 安装
官方:https://docs.docker.com/compose/install/standalone/
# 下载
curl -SL https://github.com/docker/compose/releases/download/v2.32.4/docker-compose-linux-x86_64 -o /usr/local/bin/docker-compose
#切换目录
cd /usr/local/bin
# 更改名称
mv docker-compose-linux-x86_64 docker-compose
# 给docker-compose可执行权限
chmod +x /usr/local/bin/docker-compose
# 创建软连接
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
# 查看版本
docker-compose --version
1.5 项目说明和构建
说明:同02进阶中的shopms项目,只构建后台java项目即可,此处略
1.5.1 手工启动
手工构建:
- 运行 mysql 容器,恢复数据
- java项目用Dockerfile构建镜像,再运行容器
1.5.2 compose 编排启动
创建目录 /shopapp,在其中编写 compose.yml
用 services 定义若干个服务:
继续定义:
services:
app:
build: ./app #指定 app 服务的镜像./app 中的 Dockerfile 来生成的。./app 表示当前工作目录下的 app 文件夹
container_name: shopapp #指定容器的名称为 shopapp。
ports:
- 9090:9090 #将容器的端口 9090 映射到宿主机的端口 9090。
depends_on:
- db #指定 app 服务依赖于 db 服务。
db:
image: mysql:5.7 #指定 db 服务使用 mysql:5.7 镜像
environment:
MYSQL_ROOT_PASSWORD: 123456 #设置 MySQL 数据库的环境变量,指定 root 用户的密码为 123456
ports:
- 3306:3306 #将容器的端口 3306 映射到宿主机的端口 3306。
volumes:
#将宿主机的 ./db/conf 目录挂载到容器的 /etc/mysql/conf.d 目录。
- ./db/conf:/etc/mysql/conf.d
#将宿主机的 ./db/data 目录挂载到容器的 /var/lib/mysql 目录。
- ./db/data:/var/lib/mysql
检查 compose.yml 语法:
docker-compose config -q
启动:
docker-compose up -d
停止:
docker-compose down
查看容器、镜像:
查看网络:
postman测试api请求:
如果数据库访问失败,检查springboot配置文件,如下:
注意:application.yml
1.5.3 完善 compose.yml
如果修改了compose文件名,如compose2.yml,启动用: docker-compose -f compose2.yml up -d
1.5.4 加入前端容器
2.UI管理平台
希望查看运行中的容器所占用的系统情况,可以使用命令:
docker stats
但是不够直观,可以安装带有UI界面的管理平台,帮助用户进行管理。
2.1 portainer
官网:https://www.portainer.io/
linux安装portainer:https://docs.portainer.io/start/install-ce/server/docker/linux
先拉取镜像:
docker pull portainer/portainer-ce
数据卷:
docker volume create portainer_data
查找位置:
docker volume inspect portainer_data
运行容器:
docker run -d -p 8000:8000 -p 9443:9443 -p 9000:9000 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest
网页访问:
http://192.168.9.3:9000
用 9443 端口也可访问,注意是 https 的协议:
https://192.168.9.3:9443
3.镜像发布
3.1 阿里云
登录 https://www.aliyun.com/ (账号需经过实名认证)
容器镜像服务:
其中的“实例”指的就是镜像仓库,进入个人版实例:
设置“访问凭证”,相当于是登录镜像中心的密码
设置“命名空间”,名字要求全网唯一(可以创建多个)
创建“镜像仓库”,仓库名称相当于镜像名
根据操作指南,测试 push 镜像,先登录(docker login)
把镜像按照要求重新打标签(docker tag)
推送到镜像中心(docker push)
在“镜像版本中”可以看到刚才推送的镜像(digest码一致):
把之前的镜像删除,测试pull :
其他,登出:
docker logout registtry.cn-hangzhou.aliyuncs.com
3.2 Docker Registry
3.2.1 介绍
搭建 Docker 镜像中心最常用的技术是 Docker Registry,尤其是 Docker Distribution,它是 Docker 官方提供的开源镜像仓库。
https://hubgw.docker.com/_/registry
3.2.2 安装
提问deepseek:在 centos7中已经装了docker了,现在要安装 Docker Registry ,并且用 htpasswd 进行验证,怎么做
步骤1.安装 htpasswd
是 Apache 提供的工具,用于创建和管理用户认证文件,如果系统中没有安装,可以通过以下命令安装:
yum install -y httpd-tools
步骤2.创建一个目录来存储认证文件,并生成 htpasswd文件:
# 创建认证文件目录
mkdir -p /opt/docker-registry/auth
# 生成 htpasswd 文件(例如用户名为 tom)
htpasswd -Bc /opt/docker-registry/auth/htpasswd tom
- -B:使用 bcrypt 加密密码(推荐)。
- -c:创建新文件(如果文件已存在,不要使用
-c
,否则会覆盖文件)。
如果需要添加更多用户,可以运行:
# anotheruser为用户名
htpasswd -B /opt/docker-registry/auth/htpasswd anotheruser
步骤3.拉取镜像、运行容器:
docker pull registry
docker run -d \
--name registry \
-p 5000:5000 \
-v /var/lib/registry:/var/lib/registry \
-v /etc/docker/registry-auth:/auth \
-e "REGISTRY_AUTH=htpasswd" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd" \
registry
-v /opt/docker-registry/auth:/auth
:将本地的auth
目录挂载到容器中。-v /opt/docker-registry/data:/var/lib/registry
:将本地的data
目录挂载到容器中,用于存储镜像数据。-e REGISTRY_AUTH=htpasswd
:启用htpasswd
身份验证。-e REGISTRY_AUTH_HTPASSWD_REALM
:认证域的名称(可以自定义)。-e REGISTRY_AUTH_HTPASSWD_PATH
:指定htpasswd
文件的路径。
3.2.3 测试
1.登录 Registry:
docker login localhost:5000
2.推送镜像:
标记一个本地镜像:
docker tag my-image localhost:5000/my-image
推送镜像到 Registry:
docker push localhost:5000/my-image
3.拉取镜像
docker pull localhost:5000/my-image
其他:验证身份验证
如果未登录或登录失败,尝试推送或拉取镜像时会收到以下错误:
unauthorized: authentication required
3.2.4 https 问题
远程登录报错,Docker 客户端默认尝试通过 HTTPS 连接 Registry,而 Docker Registry 是通过 HTTP 运行的。
方法1.配置 Docker 客户端允许 HTTP 连接
在 Docker 客户端机器上,编辑 Docker 的配置文件 /etc/docker/daemon.json
(如果文件不存在,可以创建它)
重启 docker服务,再次测试登录
systemctl restart docker
方法2.使用 HTTPS 配置 Registry(推荐)
步骤1.在Rigistry端进行操作
从 Go 1.15 开始,Go 语言(Docker 是用 Go 编写的)不再支持仅依赖 CN 字段的证书,必须使用 SAN 字段。要解决这个问题,你需要重新生成 TLS 证书,并在证书中包含 SAN 字段。
# 创建目录,用于存放证书等文件
mkdir -p /opt/docker-registry/certs
# 切换目录
cd /opt/docker-registry/certs
# 创建 openssl.cnf 文件
cat > openssl.cnf <<EOF
[req]
default_bits = 4096
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
CN = 192.168.9.4
[v3_ext]
authorityKeyIdentifier=keyid,issuer:always
basicConstraints=CA:FALSE
keyUsage=digitalSignature,nonRepudiation,keyEncipherment
extendedKeyUsage=serverAuth
subjectAltName=@alt_names
[alt_names]
IP.1 = 192.168.9.4
EOF
CN
:Common Name,填写 Registry 的 IP 或域名。subjectAltName
:在[alt_names]
部分定义 SAN,支持 IP 或域名。
生成私钥和证书,使用 OpenSSL 生成私钥和证书:
openssl req -newkey rsa:4096 -nodes -sha256 \
-keyout domain.key \
-out domain.csr \
-config openssl.cnf
# 如果有 CA 证书:
#openssl x509 -req -days 365 -sha256 \
# -in domain.csr \
# -CAcreateserial \
# -CA ca.crt -CAkey ca.key \
# -out domain.crt \
# -extensions v3_ext \
# -extfile openssl.cnf
# 如果没有 CA 证书:
openssl req -x509 -newkey rsa:4096 -nodes -sha256 \
-keyout domain.key \
-out domain.crt \
-days 365 \
-config openssl.cnf \
-extensions v3_ext
生成的 domain.key
和 domain.crt
文件将用于配置 Registry。
步骤2.删除之前的容器,配置 Docker Registry 使用 TLS,重新启动 Registry 容器,并挂载证书文件:
docker run -d \
-p 5000:5000 \
--name registry \
-v /opt/docker-registry/auth:/auth \
-v /opt/docker-registry/data:/var/lib/registry \
-v /opt/docker-registry/certs:/certs \
-e REGISTRY_AUTH=htpasswd \
-e REGISTRY_AUTH_HTPASSWD_REALM="Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
registry
步骤3.在客户端机器上信任证书。将生成的 domain.crt
文件复制到客户端机器,并将其添加到系统的受信任证书列表中。
在 Registry 端把认证文件发送到客户端:
# 在客户端运行
mkdir -p /etc/docker/certs.d/192.168.9.4:5000
cp domain.crt /etc/docker/certs.d/192.168.9.4:5000/ca.crt
- Docker 客户端会检查
/etc/docker/certs.d/<registry-domain>:<port>/
目录下的ca.crt
文件。 - 如果 Registry 使用域名而不是 IP 地址,请将
192.168.9.4
替换为域名。
在客户端机器上重启 Docker 服务以加载新证书:
systemctl restart docker
再次尝试登录:
docker login https://192.168.9.4:5000
需要选择一个镜像进行标记
myapp 1.0 989d89d63bca About a minute ago 642MB
docker tag 989d89d63bca 192.168.9.4:5000/myapp:1.0
**docker tag
**用于为本地镜像创建一个新的标签(tag)
989d89d63bca
这是本地镜像的唯一标识符(镜像 ID)。每个 Docker 镜像都有一个唯一的 ID,可以通过docker images
命令查看。192.168.9.4:5000/myapp:1.0
这是目标镜像的完整名称,包括:192.168.9.4:5000
:这是远程 Docker Registry 的地址和端口。192.168.9.4
是私有 Registry 的 IP 地址,5000
是其服务端口。myapp
:这是镜像的名称。1.0
:这是镜像的版本标签(tag),用于区分不同版本的镜像。
推送镜像到 Registry
docker push 192.168.9.4:5000/myapp:1.0
这是私有 Docker Registry 的地址和端口:
192.168.9.4
是私有 Registry 的 IP 地址。5000
是私有 Registry 的服务端口(默认情况下,Docker Registry 使用 5000 端口)。
#推送的镜像位置 目录名就是镜像名称
#/opt/docker-registry/data/docker/registry/v2/repositories
一个新的标签(tag)
989d89d63bca
这是本地镜像的唯一标识符(镜像 ID)。每个 Docker 镜像都有一个唯一的 ID,可以通过docker images
命令查看。192.168.9.4:5000/myapp:1.0
这是目标镜像的完整名称,包括:192.168.9.4:5000
:这是远程 Docker Registry 的地址和端口。192.168.9.4
是私有 Registry 的 IP 地址,5000
是其服务端口。myapp
:这是镜像的名称。1.0
:这是镜像的版本标签(tag),用于区分不同版本的镜像。
推送镜像到 Registry
docker push 192.168.9.4:5000/myapp:1.0
这是私有 Docker Registry 的地址和端口:
192.168.9.4
是私有 Registry 的 IP 地址。5000
是私有 Registry 的服务端口(默认情况下,Docker Registry 使用 5000 端口)。
#推送的镜像位置 目录名就是镜像名称
#/opt/docker-registry/data/docker/registry/v2/repositories
5.Docker Swarm
5.1 简介
Docker Swarm 是由 Docker 公司推出的 Docker 的原生集群管理系统,它将一个 Docker主机池变成了一个单独的虚拟主机,用户只需通过简单的 API 即可实现与 Docker 集群的通信。
Docker swarm 使用 GO 语言开发,从 Docker 1.12.0版本开始,Docker swarm 已经内置于Docker引擎中,无需再专门的进行安装配置。
官网: https://docs.docker.com/engine/swarm/
5.1.1 节点
在 Docker Swarm 中,Manager 节点是集群的核心管理组件,负责维护集群状态、调度任务、处理 API 请求以及确保集群的高可用性。Manager 节点通过 Raft 一致性算法实现分布式一致性,确保集群的稳定运行。
Manager 节点的作用
- 集群管理:
- Manager 节点负责管理整个 Swarm 集群,包括节点的加入、离开、状态监控等。
- 它维护集群的全局状态,并确保所有节点的一致性。
- 任务调度:
- Manager 节点根据服务的定义和资源需求,将任务(Tasks)调度到合适的 Worker 节点上运行。
- 调度策略包括节点资源、约束条件(constraints)和偏好(preferences)等。
- 高可用性:
- Manager 节点通过 Raft 一致性算法实现高可用性。
- 多个 Manager 节点组成一个高可用集群,确保即使某个 Manager 节点失效,集群仍能正常运行。
- API 服务:
- Manager 节点提供 Docker API 服务,用于接收用户的管理请求(如创建服务、更新配置等)。
- 所有对 Swarm 集群的操作(如
docker service create
)都通过 Manager 节点执行。
- 维护集群状态:
- Manager 节点维护集群的全局状态,包括服务、网络、卷、配置和密钥等信息。
- 这些状态信息通过 Raft 日志在多个 Manager 节点之间同步。
- Leader 选举:
- 在多个 Manager 节点中,会选举出一个 Leader 节点,负责处理集群的管理任务。
- 如果 Leader 节点失效,剩余的 Manager 节点会重新选举一个新的 Leader。
- 安全性:
- Manager 节点负责管理 Swarm 集群的安全配置,如 TLS 证书、加密密钥等。
- 它还控制节点的加入和权限管理。
在 Docker Swarm 中,Worker 节点是 Swarm 集群的重要组成部分,主要负责运行和管理由 Swarm 调度的容器化任务(Tasks)。Worker 节点不参与 Swarm 集群的管理和决策,而是专注于执行实际的工作负载。
Worker 节点的作用
- 运行服务任务:
- Worker 节点负责运行由 Swarm Manager 节点调度的服务任务(Tasks)。
- 每个任务通常对应一个容器实例。
- 负载均衡:
- Worker 节点通过 Swarm 的内置负载均衡机制,确保服务的高可用性和性能。
- Swarm 会自动将任务分配到可用的 Worker 节点上。
- 扩展性和弹性:
- Worker 节点可以根据需要动态扩展或缩减,以应对工作负载的变化。
- 如果某个 Worker 节点失效,Swarm 会将该节点上的任务重新调度到其他健康的 Worker 节点上。
- 资源提供:
- Worker 节点提供计算、存储和网络资源,用于运行容器化应用。
- 与 Manager 节点协作:
- Worker 节点从 Manager 节点接收任务指令,并定期向 Manager 节点报告状态。
- Worker 节点不参与集群管理决策(如 Leader 选举、服务调度策略等)。
5.1.2 服务、任务、容器
- Service(服务)
-
定义:
- Service 是 Swarm 中部署和管理的核心单元,代表一个长期运行的应用或微服务。
- 它定义了应用的镜像、副本数量、网络配置、存储卷、环境变量等。
-
特点:
-
Service 是面向用户的抽象,用户通过创建和管理 Service 来部署应用。
-
Service 可以指定副本数量(Replicated Mode)或全局模式(Global Mode)。
-
Replicated Mode:指定固定数量的任务副本。
-
Global Mode:在每个符合条件的节点上运行一个任务。
-
-
- Task(任务)
-
定义:
- Task 是 Service 的具体实例化单位,代表一个容器化的任务。
- 每个 Task 对应一个容器,由 Swarm Manager 调度到某个节点上运行。
-
特点:
- Task 是 Swarm 调度的最小单位。
- 每个 Task 包含容器的配置信息(如镜像、网络、存储卷等)。
- Task 的状态由 Swarm Manager 监控和管理(如运行中、失败、完成等)。
-
示例:
- 如果一个 Service 定义了 3 个副本,Swarm 会创建 3 个 Task,每个 Task 对应一个容器。
- Container(容器)
- 定义:
- Container 是 Task 的实际运行实例,是 Docker 容器化的具体表现。
- 它是基于镜像创建的运行时环境,包含应用代码、依赖和配置。
- 特点:
- Container 是 Task 的具体实现,由 Task 定义其配置。
- 每个 Container 在某个节点上运行,由 Docker 引擎管理。
- 示例:
- 如果一个 Task 被调度到某个节点上,Docker 会在该节点上启动一个对应的容器。
三者的关系
- 层次结构:
- Service > Task > Container
- 一个 Service 包含多个 Task,每个 Task 对应一个 Container。
- 创建流程:
- 用户创建一个 Service,并指定副本数量。
- Swarm Manager 根据 Service 的定义,创建相应数量的 Task。
- 每个 Task 被调度到某个节点上,并由 Docker 引擎启动对应的 Container。
- 状态管理:
- Swarm Manager 监控 Service、Task 和 Container 的状态。
- 如果某个 Container 失效,Swarm 会重新调度对应的 Task,并在其他节点上启动新的 Container。
1.2 swarm集群
现要搭建一个 docker swarm 集群,包含5个swarm 节点。这5个swarm 节点的IP与暂时的角色分配如下(注意,是暂时的):
hostname | ip | role | required |
---|---|---|---|
docker1 | 192.168.9.3 | manager | 2核2G |
docker2 | 192.168.9.4 | manager | 2核2G |
docker3 | 192.168.9.5 | manager | 2核2G |
docker4 | 192.168.9.6 | worker | 1核1G |
docker5 | 192.168.9.7 | worker | 1核1G |
先了解以下命令:
docker1:
初始化swarm,默认自己会成为 manager 节点。
#在 docker1 初始化 swarm
docker swarm init
注:用 docker info 查看信息
docker4:
把 docker4 作为 worker节点加入swarm
# To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5pj3mb6esgm13y7u2dvyre7jyaw2an7g628yg9nkgynp55ewhd-15di9u6twoea9ghapqmk99ozt 192.168.9.3:2377
docker2 和 docker3:
把 docker2和docker3 作为 manager 节点加入 swarm
# 在docker1上
# To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
docker swarm join-token manager
# 在docker2 和 docker3 上
docker swarm join --token SWMTKN-1-5pj3mb6esgm13y7u2dvyre7jyaw2an7g628yg9nkgynp55ewhd-0b465wi3hij8yqjea9qoqybm1 192.168.9.3:2377
查看命令说明
docker5:
把 docker5 作为 worker节点加入swarm
同理,也可以在docker1 运行:
# 在docker1上用该命令
docker swarm join-token worker
# 在docker5上
docker swarm join --token SWMTKN-1-5pj3mb6esgm13y7u2dvyre7jyaw2an7g628yg9nkgynp55ewhd-15di9u6twoea9ghapqmk99ozt 192.168.9.3:2377
查看节点信息:
docker node ls
5.3 节点维护
5.3.1 退群进群
worker 节点
worker 节点退群,以docker5 为例
# 在docker5上
docker swarm leave
在其他主机如docker1,查看节点信息(发现 docker5 的状态为 down)
docker5 重新加入 swarm
在docker1,查看节点信息,发现有两个 docker5 节点,但是ID不同。
这也就说明节点其实是逻辑概念,某台docker主机上可以存在若干节点。
要删除down节点,可以:docker node rm
再次查看节点
manager 节点
manager 节点退群,以docker3 为例:
这个错误表明你正在尝试从 Docker Swarm 集群中的一个 Manager 节点上执行 docker swarm leave
命令,而该节点当前是 Swarm 集群的管理者之一。由于 Manager 节点在 Swarm 中负责维护集群状态和一致性(通过 Raft 算法),直接离开可能会导致集群失去法定人数(quorum),从而无法正常工作。
错误原因
- Manager 节点的重要性:
- Swarm 集群需要多数(quorum)的 Manager 节点在线才能正常工作。如果过多的 Manager 节点离开,集群将无法达成共识,导致无法管理服务。
- 例如,如果你有 3 个 Manager 节点,至少需要 2 个在线才能维持集群的正常运行。
- 直接离开的后果:
- 如果你从一个 Manager 节点上直接执行
docker swarm leave
,可能会导致集群失去 quorum,从而无法继续运行。
- 如果你从一个 Manager 节点上直接执行
解决方法
方法 1:降级 Manager 节点
如果你希望该节点离开 Swarm 集群,但不影响集群的正常运行,可以先将该节点从 Manager 降级为 Worker 节点,然后再离开。
解决方法
方法 1:降级 Manager 节点
如果你希望该节点离开 Swarm 集群,但不影响集群的正常运行,可以先将该节点从 Manager 降级为 Worker 节点,然后再离开。
-
降级节点:
docker node demote <NODE-ID>
- 将
<NODE-ID>
替换为你要降级的节点的 ID(可以通过docker node ls
查看)。
- 将
-
离开 Swarm:
docker swarm leave
如果你确定要强制该节点离开 Swarm 集群,可以使用 --force
参数。但请注意,这可能会导致集群失去 quorum,从而无法正常工作。
-
强制离开:
docker swarm leave --force
-
如果集群因此失去 quorum,你需要手动恢复集群:
-
在剩余的 Manager 节点上执行以下命令,强制重新初始化集群:
docker swarm init --force-new-cluster
-
这将使当前节点成为新的 Swarm 集群的 Leader,并尝试恢复集群状态。
方法 3:恢复集群
-
如果集群已经失去 quorum 且无法正常工作,可以尝试以下步骤恢复:
-
在剩余的 Manager 节点上执行:
docker swarm init --force-new-cluster
- 这会强制重新初始化 Swarm 集群,并使当前节点成为新的 Leader。
-
重新加入其他节点:
- 使用
docker swarm join-token
获取新的加入令牌,然后让其他节点重新加入集群。
- 使用
测试方法1
把 docker3 降级
此时 docker3 已经从 manager 变为了 worker,从docker1 查看信息如下:
也可以在 docker1 把 docker3 提升为 manager:
5.3.2 更改角色 (升级降级)
在 manager 节点上可以更新节点信息
docker3 降级为 worker:
docker node update --role worker docker3
docker3 升级为 manager:
docker node update --role manager docker3
5.3.3 节点标签
可以给节点添加、更改、删除标签
docker node update --label-add author="tom" --label-add desc="just a test " docker3
#删除
docker node update --label-rm author docker3
1.4 manager 自动锁定
在 manager 集群中,swarm 通过 Raft 日志方式维护了 manager 集群中数据的一致性。即在 manager 集群中每个节点通过 manager 间通信方式维护着自己的 Raft 日志。
但在通信过程中存在有一种风险:Raft 日志攻击者会通过 Raft日志数据的传递来访问篡改 manager 节点中的配置或数据。为了防止被攻击,swarm 开启了一种集群自动锁定功能,为 manager 间的通信启用了 TLS 加密。用于加密和解密的公钥与私钥,全部都维护在各个节点的 Docker 内存中。
开启了自动锁定后,一旦节点的 Docker 重启,则密钥丢失,那么集群就会出问题。
swarm 中通过 autolock 标志来设置集群的自动锁定功能:为 true 则开启自动锁定,为 false 则关闭自动锁定。
5.4.1 开启 autolock
在初始化时可以用 --autolock=true 开启自动锁定:
如果已经初始化过了,但未开启自动锁定,可以通过 docker swarm update 命令进行更新开启自动锁定
用 docker info 查询,之前的案例中,autolock 并未开启:
在任意一台 manager 执行 update 都可开启 autolock:
docker swarm update --autolock=true
此时 docker info:
如果 unlock-key 忘记了,可用以下命令查询:
5.4.2 状况模拟
假设 docker3 宕机了:
在其他 manager 查看节点信息:
假设 docker3 故障排除又开机了:
发现它不会自动成为 manager 节点,因为自动锁定的问题,需要对其进行解锁
此时用 docker info 查看也会发现 swarm 已锁定:
解锁:
注:在生产环境中会开启自动锁定,但为了学习方便,还是不开启自动锁定了。
(docker swarm update --autolock=false)
5.5 创建服务
在 Docker Swarm 中创建服务非常简单,下面以部署 tomcat 服务为例,详细讲解如何创建和管理服务。
使用 docker service create
命令创建 Tomcat 服务。
docker service create --name tomcat -p 8081:8080 --replicas 3 tomcat:8.5.32
参数说明:
--name tomcat
:指定服务名称为tomcat
。-p 8081:8080
:将宿主机的 8080 端口映射到容器的 8081 端口。- 也可以写成
--publish published=8080,target=8081
- 也可以写成
--replicas 3
:指定运行 3 个副本(即 3 个 Tomcat 容器)。tomcat:8.5.32
:使用官方 Tomcat 8.5.32 镜像。--limit-cpu 0.5
:表示限制容器最多可以使用 0.5 个 CPU 核心 的计算资源(1 个 CPU 核心的 50% 的计算能力)。--limit-memory 512m
:限制容器最多可以使用 512 MB 的内存
查看服务情况:
查看日志:
也可以查询某个节点上的任务:
docker node ps docker1
访问对应主机的tomcat服务:(docker3、docker2、docker5)
5.6 服务的负载均衡
此时服务中的任务是启动在 docker2、docker3、docker5上的
分别进入容器内,添加 test.html 页面,内容不同
测试访问 docker2 这台服务器对应的网址,会发现以下效果:
原因:
当一个 service 包含多个 task 时,用户对 service 的访问最终会通过负载均衡方式转发给各个 task 处理。
这个负载均衡为随机策略,且无法通过修改 service 的属性方式进行变更。
但由于该负载均衡为三层负载均衡,所以其可以通过第三方实现负载均衡策略的变更,例如通过 Nginx、HAProxy等。
其他:
也可以用 whoami 镜像测试负载均衡
# 每台都拉取镜像
docker pull containous/whoami
# 创建服务
docker service create --name whoami --replicas 5 -p 80:80 containous/whoami
# 访问测试
curl 192.168.9.3
1.7 扩容缩容与可用性
1.7.1 扩容缩容
5.7.2 availability 可用性
任务数可以大于节点数:
此时如果再扩容到10个任务,会每个节点分摊2个。
假设其中docker4 机器性能较差,不想让其参与扩容,则可以将其暂停,暂停只会影响扩容,不会影响其对外提供服务。
更新节点可用性状态命令:docker node update --availability
此时扩容至10个:
恢复 docker4 的可用性为 active:
测试可用性为 drain(排空、放干) ,此时所有节点都为 active,任务数为10:
更改 docker4 的可用性为 drain:
此时总任务数还是维持10个,但是 docker4不参与服务了
1.8 全局模式部署
service 以副本任务 task 的形式部署在 swarm 集群节点上。
根据 task 数量与节点数量的关系,常见的 service 部署模式有两种:replicated 模式与 global 模式。
默认使用的是副本模式,现测试全局模式。
先把 docker5 leave swarm(为了后面的测试)
创建服务,mode 为 global:
# 全局模式不能使用 --replicas 选项
docker service create --name tomcat -p 8081:8080 --mode global tomcat:8.5.32
此时把 docker5 加入swarm:(先在manager节点查询worker的token)
再查看服务情况: