docker创建nginx+keepalived+nacos集群(仅测试环境)

文章目录

测试环境

VM PRO 17

虚拟机centos Centos Linux 7 (Core)

Kernel 3.10.0-327.10.1.e17.x86_64 on an x86_64

连接类型 NAT 子网地址192.168.127.0

创建macvlan 网络

当前虚拟机ip 是 192.168.127.128,docker如何创建一个centos系统 ip是192.168.127.x呢

主要有两种方法:使用 macvlan 网络驱动(推荐)或创建自定义的 bridge 网络。但优先推荐 macvlan。

网关验证
ip route | grep default

我网关是192.168.127.2

查看网卡名字
ip addr

我的网卡是eno16777736

老内核记得开混杂模式
sudo ip link set eno16777736 promisc on

1)创建 macvlan 网络

执行以下命令,请务必将 --subnet, --gateway, -o parent 这三个参数替换为你自己的网络信息。

bash 复制代码
# 请根据你的实际网络环境修改以下参数
docker network create -d macvlan \
--subnet=192.168.127.0/24 \
--gateway=192.168.127.2 \
-o parent=eno16777736 \
macvlan_net

一、先验证你刚才创建的 macvlan 网络是否成功

查看所有 Docker 网络

bash 复制代码
docker network ls

你会看到 macvlan_net 说明创建成功。

查看 macvlan 详细配置

bash 复制代码
docker network inspect macvlan_net

里面会显示:

  • subnet: 192.168.127.0/24
  • gateway: 192.168.127.2
  • parent: eno16777736

二、如果要删除(重建用)

删除 macvlan 网络

bash 复制代码
docker network rm macvlan_net

删除后再用 docker network ls 确认消失即可。


三、重新创建

bash 复制代码
docker network create -d macvlan \
--subnet=192.168.127.0/24 \
--gateway=192.168.127.2 \
-o parent=eno16777736 \
macvlan_net

四、启动一个容器 指定同网段IP 测试

我们用最简单的 alpine 镜像测试。

启动容器(指定IP:192.168.127.120)

bash 复制代码
docker run -d \
--name macvlan_test \
--network macvlan_net \
--ip 192.168.127.120 \
alpine sleep 3600

五、最终验证:容器是否真的在同网段

进入容器查看 IP

bash 复制代码
docker exec -it macvlan_test ifconfig
# 或者
docker exec -it macvlan_test ip addr

在 局域网其他机器 ping 这个IP

在你电脑/另一台服务器执行:

复制代码
ping 192.168.127.120

注意:Linux 内核限制,宿主机 ping 不通容器 ,但局域网其他设备一定能通


六、用完清理

bash 复制代码
docker stop macvlan_test
docker rm macvlan_test

全套命令速查

bash 复制代码
sudo ip link set eno16777736 promisc on
# 查看
docker network ls
docker network inspect macvlan_net

# 删除
docker network rm macvlan_net

# 创建
docker network create -d macvlan --subnet=192.168.127.0/24 --gateway=192.168.127.2 -o parent=eno16777736 macvlan_net

# 启动测试容器
docker run -d --name macvlan_test --network macvlan_net --ip 192.168.127.120 alpine sleep 3600

# 进入容器查看IP
docker exec -it macvlan_test ifconfig

ip设计

进入正题,我们先设计一下ip地址

nginx+keepalived+nacos集群

nacos集群ip地址 192.168.127.121,192.168.127.122,192.168.127.123

nginx+keepalived集群ip地址 192.168.127.131,192.168.127.132

keepalived VIP地址 192.168.127.141

mysql ip地址 192.168.127.130

创建nacos集群

Nacos 集群必须外部数据库 这里用MySQL 8.0

创建 MySQL 容器(Nacos 集群必须使用外部数据库)

启动 MySQL 并挂载数据(推荐指定版本,好像不能高过8.0.22,老版本nacos会有版本兼容问题)

bash 复制代码
docker pull mysql:8.0

docker run -d \
  --name mysql-nacos \
  --network macvlan_net \
  --ip 192.168.127.130 \
  --restart=always \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -e MYSQL_DATABASE=nacos_config \
  -e MYSQL_USER=nacos \
  -e MYSQL_PASSWORD=nacos123 \
  mysql:8.0 \
  --character-set-server=utf8mb4 \
  --collation-server=utf8mb4_unicode_ci

验证 MySQL 容器运行状态

bash 复制代码
docker ps | grep mysql-nacos
docker exec -it mysql-nacos mysql -uroot -proot123
show databases;
show grants for nacos@'%';
# 退出mysql
exit

拉一下nacos,这里用的v2.4.0的镜像,这里没开鉴权好像,里面自带sql没有user

bash 复制代码
# docker pull nacos/nacos-server:v2.4.0
# 拉取国内镜像
docker pull nacos-registry.cn-hangzhou.cr.aliyuncs.com/nacos/nacos-server:v2.4.0

# 重命名为官方名称(后续启动不用改命令)
docker tag nacos-registry.cn-hangzhou.cr.aliyuncs.com/nacos/nacos-server:v2.4.0 nacos/nacos-server:v2.4.0

# 1. 临时启动 nacos 2.4.0
docker run -d --name nacos-temp nacos/nacos-server:v2.4.0

# 2. 把内置的 mysql-schema.sql 复制到宿主机
docker cp nacos-temp:/home/nacos/conf/mysql-schema.sql ./nacos-mysql-2.4.0.sql

# 导入数据库
docker exec -i mysql-nacos mysql -uroot -proot123 nacos_config < nacos-mysql-2.4.0.sql

# 3. 删除临时容器
docker rm -f nacos-temp

三、启动 Nacos 集群(3 节点)

创建配置目录并编写 application.properties

bash 复制代码
mkdir nacos-cluster && cd nacos-cluster

创建配置文件(注意节点不共用,记得修改nacos.server.ip):

bash 复制代码
cat > application.properties <<EOF
# 基础配置
server.port=8848
nacos.mode=cluster
spring.datasource.platform=mysql

# MySQL 配置(保留你的修复参数)
db.num=1
db.url.0=jdbc:mysql://192.168.127.130:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
db.user.0=nacos
db.password.0=nacos123

# ==================== 集群核心修复(关键!) ====================
# Nacos 2.X 集群节点列表(必须带 7848 端口,raft 通信端口)
nacos.member.list=192.168.127.121:7848,192.168.127.122:7848,192.168.127.123:7848

# 固定自身IP(macvlan 必须加,让节点知道自己是谁)
# 注意:启动哪个节点,就把这个IP改成对应节点的!!
nacos.server.ip=192.168.127.121

# 其他基础配置
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=180000
nacos.naming.empty-service.clean.period-time-ms=180000
server.tomcat.accesslog.enabled=true
EOF

启动三个 Nacos 节点,增加重启策略与 JVM 限制

bash 复制代码
# 节点1 (192.168.127.121)
sed -i 's/nacos.server.ip=.*/nacos.server.ip=192.168.127.121/' application.properties
docker run -d \
  --name nacos1 \
  --network macvlan_net \
  --ip 192.168.127.121 \
  --restart=always \
  -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m \
  -e NACOS_SERVERS="192.168.127.121:8848,192.168.127.122:8848,192.168.127.123:8848" \
  -v $(pwd)/application.properties:/home/nacos/conf/application.properties \
  nacos/nacos-server:v2.4.0

# 节点2 (192.168.127.122)
sed -i 's/nacos.server.ip=.*/nacos.server.ip=192.168.127.122/' application.properties
docker run -d \
  --name nacos2 \
  --network macvlan_net \
  --ip 192.168.127.122 \
  --restart=always \
  -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m \
  -e NACOS_SERVERS="192.168.127.121:8848,192.168.127.122:8848,192.168.127.123:8848" \
  -v $(pwd)/application.properties:/home/nacos/conf/application.properties \
  nacos/nacos-server:v2.4.0

# 节点3 (192.168.127.123)
sed -i 's/nacos.server.ip=.*/nacos.server.ip=192.168.127.123/' application.properties
docker run -d \
  --name nacos3 \
  --network macvlan_net \
  --ip 192.168.127.123 \
  --restart=always \
  -e JVM_XMS=512m -e JVM_XMX=512m -e JVM_XMN=256m \
  -e NACOS_SERVERS="192.168.127.121:8848,192.168.127.122:8848,192.168.127.123:8848" \
  -v $(pwd)/application.properties:/home/nacos/conf/application.properties \
  nacos/nacos-server:v2.4.0

验证 Nacos 集群状态

浏览器访问任意节点:http://192.168.127.121:8848/nacos/index.html

默认账号密码 nacos/nacos(我这里没开鉴权)

进入"集群管理"→"节点列表",应显示三个节点为 UP

补充检查 gRPC 端口(Nacos 2.x 依赖):
docker exec nacos1 netstat -tulpn | grep -E "9848|9849"

构建 nginx + keepalived

创建构建目录
mkdir nginx-keepalived && cd nginx-keepalived

文件 1:Dockerfile

因为这虚拟机的centos内核很老了,这里用alpine:3.18,没有用最新的

bash 复制代码
cat > Dockerfile <<EOF
FROM alpine:3.18
RUN apk add --no-cache nginx keepalived bash
COPY nginx.conf /etc/nginx/nginx.conf
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
EOF

文件 2:nginx.conf(反向代理到 Nacos 集群)

bash 复制代码
cat > nginx.conf <<'NEOF'
worker_processes auto;
events {
    worker_connections 1024;
}

http {
    upstream nacos_cluster {
        server 192.168.127.121:8848;
        server 192.168.127.122:8848;
        server 192.168.127.123:8848;
    }

    server {
        listen 80;
        location /nacos {
            proxy_pass http://nacos_cluster;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        location / {
            return 302 /nacos;
        }
    }
}
NEOF

文件 3:entrypoint.sh(VIP 配置去掉子网掩码)

我遇到点PID BUG先这么解决吧

bash 复制代码
cat > entrypoint.sh <<'EOF'
#!/bin/bash
set -e

# 1. 准备目录
mkdir -p /etc/keepalived

# 2. 生成 Keepalived 配置(简化版,去掉 global_defs 里的 pid_file)
cat > /etc/keepalived/keepalived.conf <<KEEP
global_defs {
    # 跳过检查源地址,适合容器环境
    vrrp_skip_check_adv_addr
    # 禁止严格模式(否则容易因为网卡问题报错)
    # vrrp_strict  <-- 注释掉这行
}

vrrp_instance VI_1 {
    state ${KEEPALIVED_STATE:-MASTER}
    interface eth0
    virtual_router_id 51
    priority ${KEEPALIVED_PRIORITY:-100}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        192.168.127.141
    }
}
KEEP

# 3. 【关键】清理所有 Keepalived 可能存放 PID 的路径
# 不管它想往哪写,先把可能的地方都删了
echo "Cleaning up possible PID files..."
rm -f /var/run/keepalived.pid
rm -f /run/keepalived.pid
rm -f /tmp/keepalived.pid
rm -rf /run/keepalived/
mkdir -p /run/keepalived/ # 有些版本会尝试往这个目录写

echo "Testing nginx configuration..."
nginx -t

echo "Starting nginx..."
nginx

echo "Starting keepalived..."
# 增加 --vrrp 来明确只启动 VRRP 功能,减少复杂度
exec keepalived --dont-fork --log-console --release-vips --vrrp
EOF

chmod +x entrypoint.sh

构建镜像,这里network用宿主机的dns

bash 复制代码
docker build --network=host -t nginx-keepalived-nacos .
# docker build --no-cache --network=host -t nginx-keepalived-nacos .

启动两个高可用节点(增加 --privileged 和重启策略)

bash 复制代码
# 主节点
docker run -d \
  --name nginx-kp1 \
  --network macvlan_net \
  --ip 192.168.127.131 \
  --privileged \
  --restart=always \
  -e KEEPALIVED_STATE=MASTER \
  -e KEEPALIVED_PRIORITY=100 \
  nginx-keepalived-nacos

# 备节点
docker run -d \
  --name nginx-kp2 \
  --network macvlan_net \
  --ip 192.168.127.132 \
  --privileged \
  --restart=always \
  -e KEEPALIVED_STATE=BACKUP \
  -e KEEPALIVED_PRIORITY=90 \
  nginx-keepalived-nacos

查看日志
docker logs nginx-kp1 --tail 60
docker logs nginx-kp2 --tail 60

通过 VIP 访问 Nacos

在局域网任意设备浏览器访问:http://192.168.127.141/nacos

应出现 Nacos 登录页,并能正常登录即可。

查看 VIP 所在位置

bash 复制代码
docker exec nginx-kp1 ip addr show eth0 | grep 192.168.127.141   # MASTER 应有
# inet 192.168.127.141/32 scope global eth0
docker exec nginx-kp2 ip addr show eth0 | grep 192.168.127.141   # BACKUP 应无

测试故障转移
docker stop nginx-kp1

稍等 2~3 秒,再次访问 http://192.168.127.141/nacos 仍然可用。

检查 VIP 已漂移到备机:
docker exec nginx-kp2 ip addr show eth0 | grep 192.168.127.141

恢复主节点并观察 VIP 抢回:
docker start nginx-kp1

稍后 VIP 会自动回到 nginx-kp1
docker exec nginx-kp1 ip addr show eth0 | grep 192.168.127.141

PS:Keepalived双主模式

如果要做双主模式改一下keepalived.conf配置就好,不做过多展开了

修改entrypoint.sh

bash 复制代码
cat > entrypoint.sh <<'EOF'
#!/bin/bash
set -e

# 默认值设置
# 实例 1 (默认配置)
STATE_1=${KEEPALIVED_STATE:-MASTER}
PRIORITY_1=${KEEPALIVED_PRIORITY:-100}
VIP_1=${KEEPALIVED_VIP_1:-192.168.127.141}

# 实例 2 (双主新增配置)
# 如果没设置 STATE_2,默认不启动实例 2 (保持向后兼容单主模式)
STATE_2=${KEEPALIVED_STATE_2:-}
PRIORITY_2=${KEEPALIVED_PRIORITY_2:-90}
VIP_2=${KEEPALIVED_VIP_2:-192.168.127.142}

# 1. 准备目录
mkdir -p /etc/keepalived

# 2. 生成 Keepalived 配置
cat > /etc/keepalived/keepalived.conf <<KEEP
global_defs {
    vrrp_skip_check_adv_addr
}

# ------------ VRRP 实例 1 ------------
vrrp_instance VI_1 {
    state ${STATE_1}
    interface eth0
    virtual_router_id 51
    priority ${PRIORITY_1}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234
    }
    virtual_ipaddress {
        ${VIP_1}
    }
}
KEEP

# ------------ VRRP 实例 2 (双主模式) ------------
# 只有当设置了 KEEPALIVED_STATE_2 环境变量时才追加这一段配置
if [ -n "$STATE_2" ]; then
    cat >> /etc/keepalived/keepalived.conf <<KEEP2

vrrp_instance VI_2 {
    state ${STATE_2}
    interface eth0
    virtual_router_id 52        # 注意:ID 必须与实例 1 不同
    priority ${PRIORITY_2}
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1234           # 密码可以相同
    }
    virtual_ipaddress {
        ${VIP_2}
    }
}
KEEP2
fi

# 3. 清理 PID
echo "Cleaning up possible PID files..."
rm -f /var/run/keepalived.pid /run/keepalived.pid /tmp/keepalived.pid
rm -rf /run/keepalived/ && mkdir -p /run/keepalived/

echo "Testing nginx configuration..."
nginx -t

echo "Starting nginx..."
nginx

echo "Starting keepalived (Dual Master Mode)..."
# 注意:去掉了 --vrrp 参数,因为现在有多个实例需要管理
exec keepalived --dont-fork --log-console --release-vips
EOF

chmod +x entrypoint.sh

重新构建

bash 复制代码
# 停止删除旧容器
docker stop nginx-kp1 nginx-kp2
docker rm nginx-kp1 nginx-kp2

# 重新构建镜像 (因为改了 entrypoint.sh)
docker build --network=host -t nginx-keepalived-nacos-active-active .

启动docker

bash 复制代码
docker run -d \
  --name nginx-kp1 \
  --network macvlan_net \
  --ip 192.168.127.131 \
  --privileged \
  --restart=always \
  -e KEEPALIVED_STATE=MASTER \
  -e KEEPALIVED_PRIORITY=100 \
  -e KEEPALIVED_VIP_1=192.168.127.141 \
  -e KEEPALIVED_STATE_2=BACKUP \
  -e KEEPALIVED_PRIORITY_2=90 \
  -e KEEPALIVED_VIP_2=192.168.127.142 \
  nginx-keepalived-nacos-active-active
 
 docker run -d \
  --name nginx-kp2 \
  --network macvlan_net \
  --ip 192.168.127.132 \
  --privileged \
  --restart=always \
  -e KEEPALIVED_STATE=BACKUP \
  -e KEEPALIVED_PRIORITY=90 \
  -e KEEPALIVED_VIP_1=192.168.127.141 \
  -e KEEPALIVED_STATE_2=MASTER \
  -e KEEPALIVED_PRIORITY_2=100 \
  -e KEEPALIVED_VIP_2=192.168.127.142 \
  nginx-keepalived-nacos-active-active

查看节点 1 (kp1):
docker logs nginx-kp1 --tail 30

你会看到:

VRRP_Instance(VI_1) Entering MASTER STATE (拿到 .141)

VRRP_Instance(VI_2) Entering BACKUP STATE (待命 .142)

查看节点 2 (kp2):
docker logs nginx-kp2 --tail 30

你会看到:

VRRP_Instance(VI_1) Entering BACKUP STATE (待命 .141)

VRRP_Instance(VI_2) Entering MASTER STATE (拿到 .142)

两URL都可以访问了

http://192.168.127.141/nacos/

http://192.168.127.142/nacos/

查看http://192.168.127.141/nacos/的集群节点

相关推荐
ErizJ2 小时前
Docker | 学习笔记
笔记·学习·docker
绘梨衣54712 小时前
Docker+FastAPI+MySQL 项目部署报错汇总
mysql·docker·fastapi
百年੭ ᐕ)੭*⁾⁾14 小时前
docker使用neo4j
docker·容器·neo4j
Harvy_没救了16 小时前
【网络部署】 Win11 + VMware CentOS8 + Nginx 文件共享服务 Wiki
运维·网络·nginx
春风有信16 小时前
【2026.05.01】Windows10安装Docker Desktop 4.71.0.0步骤及问题解决
运维·docker·容器
遇见火星21 小时前
Nginx限流配置:防止接口被刷,服务器稳如泰山
运维·服务器·nginx
sthnyph21 小时前
docker compose安装redis
redis·docker·容器
W.A委员会21 小时前
Docker基本使用流程
运维·docker·容器
GuokLiu1 天前
260502-Clawith-Docker安装过程
运维·docker·容器·claw