理解 Docker 怎么处理网络和存储,才能在生产环境不出事。网络模式、存储驱动、卷类型——这里一次性讲透。
网络模式#
Docker 提供五种网络驱动:
bridge(默认,最常用)
默认 rootful bridge 网络通常使用 docker0;自定义 bridge 使用自己的网桥,容器有独立的内网 IP。
# 默认 bridge
docker run -d --name web nginx:alpine
# 容器获得 172.17.0.x IP,通过 docker0 桥接出去
# 其他容器不能通过容器名访问它
# 自定义 bridge(推荐!)
docker network create mynet
docker run -d --name web --network mynet nginx:alpine
docker run -d --name db --network mynet -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password --mount type=bind,src=/path/to/protected-password-file,dst=/run/secrets/db_password,readonly postgres:16-alpine
# web 和 db 可以通过容器名互相 ping 通
# Docker 内置 DNS 服务器,自动解析容器名 → IPgraph LR
subgraph "宿主机"
ETH0["eth0 / 192.0.2.10"]
NAT["NAT 转发"]
BRIDGE["docker0 / 示例网桥地址"]
end
subgraph "容器"
C1["web / 172.17.0.2"]
C2["db / 172.17.0.3"]
end
C1 --- BRIDGE
C2 --- BRIDGE
BRIDGE --- NAT --- ETH0host
容器直接使用宿主机的网络栈,不自己做端口映射。
docker run --network host nginx:alpine
# 容器的 80 端口 = 宿主机的 80 端口
# 不需要 -p
# 减少特定网络路径开销,效果需测量;共享网络栈增加暴露面和端口冲突风险none
容器没有网络。
docker run --network none alpine ash
# 容器内只有 lo(回环),无法访问任何网络
# 用于需要禁用常规容器网络的场景overlay(需要 Swarm 控制平面)
跨宿主机通信,容器分布在不同物理机器上但共享同一个虚拟网络。
docker network create -d overlay myoverlay
# 需要 Swarm 模式开启macvlan / ipvlan
给容器分配一个真实的物理网络 IP(和宿主机在同一子网)。
docker network create -d macvlan \
--subnet=192.0.2.0/24 \
--gateway=192.0.2.1 \
-o parent=eth0 \
mymacvlan
# 容器直接获得 192.0.2.x 的 IP
# 物理路由器能直接看到容器网络驱动选择速查#
| 场景 | 推荐驱动 |
|---|---|
| 单机多容器(最常用) | bridge(自定义) |
| 性能优先(不需要端口映射) | host |
| Swarm 多节点 | overlay |
| 容器需要物理 IP | macvlan / ipvlan |
| 禁用常规容器网络 | none |
端口映射详解#
# 基本格式:宿主机IP:宿主机端口:容器端口/协议
# 映射到所有网卡
docker run -p 8080:80 nginx:alpine
# 0.0.0.0:8080 → 容器 80
# 只映射到本机(不对外暴露)
docker run -p 127.0.0.1:8080:80 nginx:alpine
# 显式绑定 loopback;旧 Engine 版本及特殊路由条件仍需核对访问边界
# 映射到指定 IP
docker run -p 192.0.2.10:8080:80 nginx:alpine
# 随机端口(宿主机端口不关心)
docker run -P nginx:alpine
# -P 自动映射 Dockerfile EXPOSE 声明的所有端口到随机宿主端口存储驱动#
怎么选
# 查看当前存储驱动
docker info | grep "Storage Driver"| 驱动 | 适用文件系统 | 备注 |
|---|---|---|
| overlay2 | 兼容的 ext4、xfs 等 | 经典存储驱动常用;Engine 29+ 新安装默认使用 containerd image store,按实际配置判断 |
| fuse-overlayfs | 任意 | rootless overlay 不可用时的选择,具体内核及功能要求需核对 |
| devicemapper | — | 旧版,不推荐 |
| btrfs | btrfs | 需配置和维护,不因宿主文件系统类型自动成为最佳选择 |
| zfs | ZFS | 需配置和维护,按负载测试 |
overlay2 原理(简化)
镜像层(只读):
Layer 4: COPY app.py
Layer 3: RUN pip install
Layer 2: COPY requirements.txt
Layer 1: FROM python:3.12
容器层(读写):
Container Layer ← 你做的所有修改都存在这一层镜像只读层可被多个容器共享;容器写入采用自己的可写层,copy-up 可能复制整个文件,并非所有重复内容都自动去重。
卷类型对比#
| 类型 | 数据位置 | 生命周期 | 适用场景 |
|---|---|---|---|
| Volume(命名卷) | /var/lib/docker/volumes/ |
手动删除才消失 | 数据库、持久化数据 |
| Bind Mount(绑定挂载) | 你指定的宿主机路径 | 宿主机目录的生命周期 | 开发环境代码同步 |
| tmpfs | 内存 | 容器停止即丢 | 临时文件、缓存、密码 |
挂载权限
# 只读挂载(容器只能读,不能写)
docker run -v /host/config:/app/config:ro nginx:alpine
# └┘ 只读
# z/Z 标签(SELinux 启用时按策略选择;会重标记宿主文件,勿对系统目录盲用)
docker run -v /data:/data:Z nginx:alpine
# :Z = 这个卷只被这一个容器用
# :z = 可以被多个容器共享共享数据#
多个容器共享同一个卷
docker volume create shared
docker run -d --name writer -v shared:/data alpine sh -c "echo data > /data/file && sleep infinity"
docker run --name reader -v shared:/data alpine cat /data/file
# 输出:data从其他容器挂载(--volumes-from)
docker run -d --name db -v pgdata:/var/lib/postgresql/data -e POSTGRES_PASSWORD_FILE=/run/secrets/db_password --mount type=bind,src=/path/to/protected-password-file,dst=/run/secrets/db_password,readonly postgres:16-alpine
docker run --rm --volumes-from db:ro --mount type=bind,src=/path/to/backup.sh,dst=/backup.sh,readonly alpine sh /backup.sh
# backup 容器可以直接访问 db 的所有卷数据与网络的实际前提#
图中的 IP 是文档示意,实际子网需避开现有路由且配置网关;macvlan 还可能限制宿主与容器直接通信。host 模式受平台和 Desktop 设置支持范围约束。端口发布可能绕过部分宿主防火墙常规链,应按 Docker 网络规则验证暴露面。
卷存储路径受 daemon data-root、rootless、Desktop VM 与驱动影响。绑定挂载遮蔽容器已有目录内容,而非删除镜像目录。空卷复制由挂载方式与 nocopy 等选项决定。tmpfs 数据也可能进入 swap,不能称为绝对只在内存的秘密存储。--volumes-from 只提供访问,不生成一致性备份;数据库需要停止写入、快照或原生备份流程。
参考与延伸
根据技术笔记重新整理,示例使用通用名称。