Docker容器网络

时游大约 3 分钟

Docker 容器网络

网络模式

docker run 时通过 --network 指定:

模式说明场景
bridge(默认)桥接:容器接到 docker0 网桥,独立内网 IP常规单机容器
host与宿主机共享网络命名空间,无独立 IP,不用 -p追求网络性能
none无网络安全敏感/离线任务
container:容器名/id与指定容器共享网络(两个容器 localhost 互通)k8s pod 内容器通信模型
自定义网络docker network create 创建的 bridge容器间按名互访(推荐)
# 查看网络列表
docker network ls

# 查看某个网络详情(能看到接入的容器和分配的 IP)
docker network inspect bridge

端口映射

docker run -d -p 8080:80 nginx           # 宿主机8080 -> 容器80
docker run -d -p 127.0.0.1:8080:80 nginx # 只绑定本机回环,外网不可访问
docker run -d -P nginx                   # 自动随机映射 EXPOSE 声明的端口
docker port 容器id                       # 查看容器端口映射

-p 是把容器端口"发布"到宿主机,供外部访问;容器之间通信不需要 -p,走内部网络。

容器互联:为什么要自定义网络

默认 bridge 下容器之间只能通过 IP 互访,容器重建后 IP 会变。自定义网络自带 DNS,容器名即域名:

# 1. 创建网络
docker network create --subnet 172.18.0.0/16 mynet

# 2. 两个容器接入同一网络,并命名
docker run -d --name mysql01 --network mynet -e MYSQL_ROOT_PASSWORD=a123456 mysql
docker run -d --name web01 --network mynet nginx

# 3. web01 内部直接用容器名访问 mysql01
docker exec -it web01 ping mysql01     # 可以 ping 通

旧的 --link 容器名 已废弃(单向、不支持动态更新),新项目一律用自定义网络。

容器访问宿主机

  1. host.docker.internal(Docker Desktop / 新版 Linux --add-host=host.docker.internal:host-gateway)
  2. Linux 下直接用 docker0 网桥地址:172.17.0.1
# 容器内的程序要连宿主机上的 MySQL(3306 只监听 127.0.0.1 时不行,需监听 0.0.0.0)
docker run -d --add-host=host.docker.internal:host-gateway myapp
# 应用配置里写:mysql://root@host.docker.internal:3306

Demo:nginx + Spring Boot + MySQL 互联

docker network create app-net

# MySQL
docker run -d --name mysql --network app-net \
	-v /home/mysql/data:/var/lib/mysql \
	-e MYSQL_ROOT_PASSWORD=a123456 mysql

# 后端(spring boot 打好的 jar)
docker run -d --name backend --network app-net \
	-v /home/app/app.jar:/app/app.jar openjdk:8 \
	java -jar /app/app.jar --spring.datasource.url=jdbc:mysql://mysql:3306/blog

# nginx 前端,对外只暴露 80
docker run -d --name nginx --network app-net -p 80:80 \
	-v /home/nginx/conf.d:/etc/nginx/conf.d nginx

nginx 反向代理到后端容器(upstream backend 直接用容器名):

server {
    listen 80;

    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://backend:8080/;   # backend 是容器名
    }
}

手动管理三个容器已经很繁琐——这正是 docker-compose 要解决的问题。

常用网络命令汇总

docker network ls                        # 网络列表
docker network create 网络名             # 创建自定义 bridge
docker network connect 网络名 容器名     # 把已运行的容器接入网络
docker network disconnect 网络名 容器名  # 移出网络
docker network rm 网络名                 # 删除网络
docker network prune                     # 清理无用网络
Loading...