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 用户的密码为 123456ports:- 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:5000cp 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)

再查看服务情况:

相关文章:
docker高级
文章目录 1.Docker Compose1.1 介绍1.2 compose文件1.3 常用命令1.4 安装1.5 项目说明和构建1.5.1 手工启动1.5.2 compose 编排启动1.5.3 完善 compose.yml1.5.4 加入前端容器 2.UI管理平台2.1 portainer 3.镜像发布3.1 阿里云3.2 Docker Registry3.2.1 介绍3.2.2 安装3.2.3 测…...
Redis Stream基本使用及应用场景
一、概念 Redis Streams是Redis5.0提供的一种消息队列机制,支持多播的可持久化的消息队列,用户实现发布订阅的功能,借鉴了kafka设计。 二、常用命令 命令名称描述XADD key ID field value [field value ...]添加一条消息 key:St…...
DAY40|动态规划Part08|LeetCode: 121. 买卖股票的最佳时机 、 122.买卖股票的最佳时机II 、 123.买卖股票的最佳时机III
目录 LeetCode:121. 买卖股票的最佳时机 暴力解法 贪心法 动态规划法 LeetCode:122.买卖股票的最佳时机II 基本思路 LeetCode: 买卖股票的最佳时机III、IV 基本思路 C代码 LeetCode:121. 买卖股票的最佳时机 力扣题目链接 文字讲解:121. 买卖股票的最佳时…...
【安装及调试旧版Chrome + 多版本环境测试全攻略】
👨💻 安装及调试旧版Chrome 多版本环境测试全攻略 🌐 (新手友好版 | 覆盖安装/运行/调试全流程) 🕰️ 【背景篇】为什么我们需要旧版浏览器测试? 🌍 🌐 浏览器世界的“…...
【Linux】进程间通信——命名管道
文章目录 命名管道什么是命名管道**命名管道 vs. 无名管道**如何创建命名管道 用命名管道实现进程间通信MakefileComm.hppServer.hppClient.hppServer.cppClient.cpp 效果总结 命名管道 什么是命名管道 命名管道,也称为 FIFO(First In First Out&#…...
Qt在Linux嵌入式开发过程中复杂界面滑动时卡顿掉帧问题分析及解决方案
Qt在Linux嵌入式设备开发过程中,由于配置较低,加上没有GPU,我们有时候会遇到有些组件比较多的复杂界面,在滑动时会出现掉帧或卡顿的问题。要讲明白这个问题还得从CPU和GPU的分工说起。 一、硬件层面核心问题根源剖析 CPU&#x…...
AI学习第六天-python的基础使用-趣味图形
在 Python 编程学习过程中,turtle库是一个非常有趣且实用的工具,它可以帮助我们轻松绘制各种图形。结合for循环、random模块以及自定义方法等知识点,能够创作出丰富多彩的图案。下面就来分享一下相关的学习笔记。 一、基础知识点回顾 &…...
[VMware]卸载VMware虚拟机和Linux系统ubuntu(自记录版)
记录一下,不是教程,只是防止我做错了可以回溯一下 我打开vscode,就会跳出下图 虚拟机,Linux还是很久之前学习安装的,种途可能卸载过(不太记得了),现在尝试彻底卸载 彻底卸载VMware虚拟机的详细步骤-CSDN博客虚拟机Vmware 转移 克隆 卸载及移除Linux系统_克隆的虚拟机怎么移除-…...
J-LangChain,用Java实现LangChain编排!轻松加载PDF、切分文档、向量化存储,再到智能问答
Java如何玩转大模型编排、RAG、Agent??? 在自然语言处理(NLP)的浪潮中,LangChain作为一种强大的模型编排框架,已经在Python社区中广受欢迎。然而,对于Java开发者来说,能…...
Cuppa CMS v1.0 任意文件读取(CVE-2022-25401)
漏洞简介: Cuppa CMS v1.0 administrator/templates/default/html/windows/right.php文件存在任意文件读取漏洞 漏洞环境: 春秋云镜中的漏洞靶标,CVE编号为CVE-2022-25401 漏洞复现 弱口令行不通 直接访问administrator/templates/defau…...
可以免费无限次下载PPT的网站
前言 最近发现了一个超实用的网站,想分享给大家。 在学习和工作的过程中,想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量,但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制࿰…...
STM32中使用PWM对舵机控制
目录 1、硬件JIE 2、PWM口配置 3、角度转换 4、main函数中应用 5、工程下载连接 1、硬件介绍 单片机:STM32F1 舵机:MG995 2、PWM口配置 20毫秒的PWM脉冲占空比,对舵机控制效果较好 计算的公式: PSC、ARR值的选取…...
使用插件 `vue2-water-marker`添加全局水印
使用插件 vue2-water-marker添加全局水印 效果图 1、安装插件 npm install vue2-water-marker --save2、全局注册 // main.js import Vue from vue import Vue2WaterMarker from vue2-water-markerVue.use(Vue2WaterMarker)3、在组件中使用 <template><div id&q…...
MySQL表约束的种类与应用
在MySQL数据库中,表约束是确保数据完整性的关键。约束限制了可以在表中插入或更新的数据类型,保证数据的准确性和可靠性。了解MySQL中的各种表约束对于数据库设计和数据维护至关重要。以下是MySQL支持的主要表约束类型及其应用的详细介绍。 1. 主键约束…...
【大模型+知识图谱】大模型与知识图谱融合:技术演进、实践应用与未来挑战
【大模型+知识图谱】大模型与知识图谱融合:技术演进、实践应用与未来挑战 大模型与知识图谱融合:技术演进、实践应用与未来挑战引言:为什么需要融合?一、技术融合的三重路径1.1 知识图谱增强大模型1.2 大模型赋能知识图谱1.3 协同推理框架二、工业级应用场景落地2.1 智能问…...
MS SQL 2008 技术内幕:T-SQL 语言基础
《MS SQL 2008 技术内幕:T-SQL 语言基础》是一部全面介绍 Microsoft SQL Server 2008 中 T-SQL(Transact-SQL)语言的书籍。T-SQL 是 SQL Server 的扩展版本,增加了编程功能和数据库管理功能,使得开发者和数据库管理员能…...
MySQL-MATCH ... AGAINST工具
在MySQL中,MATCH……AGAINST是全文索引(Full-Text index)的查询语法,它允许你对文本进行高效的全文搜素,支持自然语言搜索和布尔搜索模式。以下是MATCH……AGAINST的详细用法和示例 一、全文索引的基本概念 全文索引适…...
微服务合并
有的团队为了节约机器成本、有的团队为了提升研发效率、有的团队为了降低人均服务数 微服务合并,可以从多个角度入手 代码重构融合:人工拷贝代码、解决冲突,然后分阶段实施迁移重构。代码合并打包:将多个代码仓库,拉取…...
Shell脚本基础:用Bash自动化任务
Shell脚本基础:用Bash自动化任务 在Linux运维中,手动执行重复性任务既耗时又容易出错,而Shell脚本则为自动化提供了强大支持。 从基础概念到实用案例,逐步掌握用Bash实现自动化的核心技能。Shell脚本是Linux自动化的基石…...
基于W2605C语音识别合成芯片的智能语音交互闹钟方案-AI对话享受智能生活
随着科技的飞速发展,智能家居产品正逐步渗透到我们的日常生活中,其中智能闹钟作为时间管理的得力助手,也在不断进化。基于W2605C语音识别与语音合成芯片的智能语音交互闹钟,凭借其强大的联网能力、自动校时功能、实时天气获取、以…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
