深色模式
Docker 网络
概述
Docker 网络最容易搞混的,是两件看起来很像、实际完全不同的事:容器之间怎么互相访问,宿主机外部又怎么访问容器。前者主要是网络连通性问题,后者主要是端口映射问题。
只要这两个概念没分开,很多现象都会显得反常。明明容器能互相访问,宿主机却连不上;或者端口已经映射出来了,容器之间却还是不能靠服务名通信。问题通常不在 Docker 脾气古怪,而在网络语境没切对。
先看有哪些常见网络模式
Docker 里最常见的网络模式有这些:
bridgehostnone
还可以看到一种较少单独使用的 container 模式,它表示和另一个现有容器共享网络命名空间。知道它存在就够了,大多数日常场景不需要把它当主角。
查看当前网络:
sh
docker network ls默认 bridge 是最常见起点
bridge 是最常见的默认网络模式。Docker 启动后,通常会在宿主机上创建一套桥接网络,用来让容器拥有自己的网络空间,同时又能通过宿主机和外界通信。
只跑一个容器时,这层通常没什么存在感。一旦有多个容器协作,bridge 网络就开始变成真正要理解的东西。
自定义 bridge 网络通常比默认网络更好用
日常实践里,比起直接把多个容器都扔进默认网络,更常见也更清楚的做法,是创建一个自定义 bridge 网络:
sh
docker network create app-net然后把容器放进去:
sh
docker run -d --name app --network app-net my-app
docker run -d --name db --network app-net mysql:8.4这样做的好处通常有两个:
- 容器之间的关系更清楚
- 同一网络内的容器更容易通过名字互相访问
这也是为什么 Compose 项目通常都会自动创建自己的默认网络。它本质上就在帮你做这件事。
容器间通信和端口映射不是一回事
这是 Docker 网络里最值得先记住的一句话。
例如:
app容器要连db容器,重点是它们是不是在同一个 Docker 网络里- 浏览器要访问
app容器,重点是容器端口有没有映射到宿主机
所以这两个问题要分开看:
- 容器到容器:看
docker network - 宿主机到容器:看
-p或 Compose 的ports
很多人第一次配数据库连接时,会下意识去想“是不是没映射端口”。其实如果两个容器已经在同一个 Docker 网络里,容器之间往往根本不需要宿主机端口映射。
在同一个网络里,通常可以直接按名字访问
如果多个容器位于同一个自定义 bridge 网络中,常见做法就是直接用容器名或服务名通信。
例如应用容器连接数据库时,可以把主机写成:
text
db而不是宿主机 IP。
在 Compose 里,这种体验会更明显。服务名本身通常就会成为网络内可解析的名字,所以 DB_HOST=db 这类写法会很常见。
host 模式什么时候会用到
host 模式的含义是,容器直接复用宿主机网络栈,不再拥有单独的容器网络隔离。
它的特点很直接:
- 性能路径更短
- 端口映射概念会弱化
- 网络隔离也会变少
这类模式更适合少数明确知道自己在做什么的场景。日常 Web 应用、数据库、缓存服务,大多还是先从 bridge 或 Compose 默认网络开始。
none 模式就是不给网络
none 模式下,容器默认不会配置常规网络连接能力。它适合极少数明确需要完全自管网络的场景。一般业务容器几乎不会从这里起步。
常用网络命令
查看网络列表:
sh
docker network ls查看网络详情:
sh
docker network inspect app-net创建网络:
sh
docker network create app-net删除网络:
sh
docker network rm app-net如果确实需要指定子网,也可以显式创建:
sh
docker network create --driver bridge --subnet 172.30.0.0/16 app-net但这类自定义网段通常只在网络规划有明确需求时才值得提前介入。普通项目先别把事情想复杂。
一条实用判断线
- 容器之间要互相访问:先看是不是在同一个 Docker 网络
- 外部要访问容器:再看端口有没有映射出来
- Compose 项目里优先按服务名通信,不要先去找宿主机 IP
只要把这条线理顺,Docker 网络的大部分日常问题都不会再显得神秘。
