升级到 Compose v2 + Docker 20.10+
Docker 在宿主机重启后,找不到容器原来连接的那个网络(ID:b256217ba0f0…)。
网络是“临时”的(compose 默认创建的网络在 /var/lib/docker/network/files/ 里,不会随宿主机重启而持久化),所以重启后网络消失,容器再启动就报 network … not found,只能手动 docker compose down && docker compose up -d 重新创建。
根本原因是:你用的是旧版 docker-compose(v1)或旧版 Engine,默认网络驱动是 bridge,且没有持久化;而容器在重启时会尝试重新加入“旧网络”,但旧网络已随宿主机重启被清空。
解决思路:让网络“长存”,或者让容器不再依赖“旧网络”。
一、准备安装包(在有外网的机器下好,拷进内网)
Docker 引擎
到 https://download.docker.com/linux/static/stable/x86_64/ 下载 docker-20.10.xx.tgz(20.10 以上才带 compose 插件支持)。
Docker Compose
到 https://github.com/docker/compose/releases 下载 docker-compose-linux-x86_64(就是 compose v2 单文件二进制)。
systemd 单元文件
新建一个 docker.service,内容见下一步。
二、安装步骤(内网机器执行)
# 1. 解压引擎并放到系统目录
tar -xzf docker-20.10.xx.tgz
cp docker/* /usr/bin/
# 2. 注册 systemd 服务
cat > /etc/systemd/system/docker.service <<'EOF'
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
ExecStart=/usr/bin/dockerd
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Delegate=yes
KillMode=process
Restart=on-failure
StartLimitBurst=3
StartLimitInterval=60s
[Install]
WantedBy=multi-user.target
EOF
# 3. 安装 compose v2(单文件即插即用)
chmod +x docker-compose-linux-x86_64
mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose
# 4. 启动 Docker
systemctl daemon-reload
systemctl enable --now docker
# 5. 验证
docker version # Server ≥20.10
docker compose version # 能看到 v2.xx 即成功[root@KylinV10 data]# cp -rf docker/* /usr/bin/
cp:是否覆盖'/usr/bin/containerd'? yes
cp:是否覆盖'/usr/bin/containerd-shim-runc-v2'? yes
cp:是否覆盖'/usr/bin/ctr'?
---------------------------------
用 \cp 调用原生命令,屏蔽系统 alias:
\cp -rf docker/* /usr/bin/[root@KylinV10 data]# ln -s /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-compose
ln: 无法创建符号链接 '/usr/local/lib/docker/cli-plugins/docker-compose': 文件已存在
[root@KylinV10 data]#先删掉旧的软链接,再重新建:
rm -f /usr/local/lib/docker/cli-plugins/docker-compose
ln -s /usr/local/bin/docker-compose /usr/local/lib/docker/cli-plugins/docker-composesystemctl daemon-reload
systemctl restart docker
docker compose version
docker version[root@KylinV10 data]# docker version
Client:
Version: 29.1.3
API version: 1.52
Go version: go1.25.5
Git commit: f52814d
Built: Fri Dec 12 14:48:47 2025
OS/Arch: linux/amd64
Context: default
Error response from daemon: client version 1.52 is too new. Maximum supported API version is 1.39
[root@KylinV10 data]# docker compose version
Docker Compose version v5.0.0
[root@KylinV10 data]#刚装的 Docker CLI 是 29.1.3,但 后台 daemon 还是旧版(API 1.39),所以 CLI 提示版本过高,无法通信。
升级必须 连 daemon 一起换掉,否则只能降 CLI 版本——离线环境最简单的做法就是:
先把旧 daemon 停掉
systemctl stop docker
用刚才解压出来的 同版本 dockerd 覆盖
\cp -f docker/dockerd /usr/bin/
重新加载并启动
systemctl daemon-reload
systemctl start docker
再验证
docker version # 两边都应为 29.1.3,API 1.52
docker compose version # v5.0.0 正常重启宿主机
{/collapse-item}
{collapse-item label="创建并加入自定义网络"}
bridge 是 Docker 的默认网络名字,但它有两个硬伤:
1、默认 bridge 不支持容器互相通过名称解析(只能走 IP);自定义 bridge(oracle_net)自带内嵌 DNS,容器之间 ping 容器名 直接通。
2、默认 bridge 在宿主机重启后不会自动重建你之前通过 docker run --net bridge ... 启动的容器网络配置;而 compose 自己建的那个临时 bridge(ID 很长)重启会消失,于是出现 network not found。
把网络显式建出来并设成external: true
相当于告诉 compose:“这网我自己管,重启也在,你别删。
在宿主机上一次性创建该网络(比如web_network以后一直存在,重启也不丢)
# 1、直接命令行创建
docker network create web_network
# 2、创建桥接网络并指定子网
docker network create --driver bridge --subnet=172.19.0.0/16 web_network把正在跑的项目切到这个持久化网络即可,三步完成:
1、把 compose 文件末尾的 networks 段改成:
networks:
web_network: #定义了一个名为 web_network 的网络
external: true #声明这个网络是外部已经存在的,不是由当前 Compose 文件创建的2、给每个 service 显式指定网络
示例:
version: '3.8'
services:
nginx:
networks:
- web_network # 容器连接到外部网络
mysql:
networks:
- web_network # 另一个容器也连接到同一网络
networks:
web_network:
external: true # 使用已存在的网络容器网络通信原理:
┌─────────────────────────────────────────────────────┐
│ Docker Host │
│ │
│ ┌─────────────────────────────────────────────┐ │
│ │ web_network (外部网络) │ │
│ │ 172.19.0.0/16 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ gateway │ │ mysql │ │ redis │ │ │
│ │ │172.19.0.2│◄──►│172.19.0.3│◄──►│172.19.0.4│ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
│ 容器之间通过容器名互相访问(DNS解析) │
│ 例如:gateway 可以访问 mysql:3306 │
└─────────────────────────────────────────────────────┘3、重新应用
docker compose down # 停旧容器、清掉旧的“临时”网络
docker compose up -d # 用新的持久网络重新创建容器完成后验证:
docker network ls # 能看到 web_network
docker inspect web_network # 容器已挂进去
~~reboot # 宿主机重启~~
docker compose start # 不再报 “network not found”比如:
version: '3.8'
services:
nginx:
image: nginx
container_name: nginx
ports:
- "80:80"
environment:
TZ: Asia/Shanghai
volumes:
- /etc/localtime:/etc/localtime:ro
……
restart: unless-stopped
# 不需要 networks 声明,自动使用默认网络
networks:
default: # 覆盖默认网络
external: true # 使用外部网络
name: web_network # 指定外部网络名称网络名称映射原理
配置中声明的网络名 vs 实际使用的网络名
以后任何其他 compose 项目只要:
networks:
default: # 在 Compose 文件中的名称(逻辑名称)
name: web_network # Docker 中的实际网络名称(物理名称)
external: true┌─────────────────────────────────────────────────────────┐
│ Docker 宿主机 │
│ │
│ ┌───────────────────────────────────────────────────┐ │
│ │ web_network (实际网络名) │ │
│ │ 172.19.0.0/16 │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ gateway │ │ mysql │ │ redis │ │ │
│ │ │ 自动连接 │ │ 自动连接 │ │ 自动连接 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ 所有服务都连接到同一个网络,无需声明 networks │
└─────────────────────────────────────────────────────────┘这两种配置方式本质上都是使用外部网络 web_network,区别在于:
第一种是显式声明,每个服务需要指定
第二种是默认映射,所有服务自动使用
只要满足下面两点,就可以“容器名 + 端口”互相访问:
它们挂在同一个自定义 bridge 网络(这里就是 web_network);
目标容器监听了对应端口(EXPOSE 或 -p 都可以,不需要映射到宿主机)。
nginx 容器内部监听 80
tomcat 容器内部监听 8080
同一 web_network 下:
在 tomcat 容器里
curl http://nginx:80
在 nginx 容器里
curl http://tomcat:8080Docker 的内嵌 DNS 会把容器名自动解析成各自的内网 IP,所以跨容器通信无需再记 IP,也无需暴露宿主机端口。
网络必须提前存在,否则 Compose 启动会报错:
ERROR: network "web_network" declared as external, but could not be found{/collapse-item}
评论 (0)