知其然,知其所以然
Docker 容器原理 2026-10-10

端口发布:-p 在 iptables 里生成了哪些规则

在 Docker Desktop(macOS)上实测端口映射:-p 9780:8000 同时绑定 0.0.0.0 和 [::],局域网也能访问,写上 127.0.0.1 后局域网地址被拒绝;-P 把 EXPOSE 的 8000/tcp 和 9000/udp 映射到随机的 55000;不写 /udp 默认是 TCP;Mac 上监听端口的是 com.docker.backend;宿主机端口冲突时退出码 125、容器停在 created。

Docker 端口映射 -p -P UDP Docker Desktop 真实验证 动画演示
Docker 容器原理 2026-10-10

网络别名:同一个名字解析到多个容器

在 Docker Engine 29.8.2 里实测网络别名:--network-alias 写进该网络下的 Aliases,默认 bridge 没有;别名按网络生效,docker network connect --alias 可以给第二个网络设不同的别名;3 个容器共用别名 db 时一次解析返回全部 3 个地址,顺序变化;断开网络或删除容器后别名随之消失。

Docker 网络别名 network-alias DNS 自定义网络 真实验证 动画演示
Docker 容器原理 2026-10-10

host.docker.internal:容器怎么访问宿主机上的服务

在 Docker Desktop(macOS)上实测 host.docker.internal:解析到 192.168.65.254(外加 IPv6),gateway.docker.internal 是 192.168.65.1;容器能访问 Mac 上只监听 127.0.0.1 的服务;容器自己的 127.0.0.1 是容器自己;--add-host host.docker.internal:host-gateway 让 /etc/hosts 里多两行;--network host 的容器也能用。

Docker host.docker.internal Docker Desktop 访问宿主机 gateway.docker.internal 真实验证 动画演示
Docker 容器原理 2026-10-10

网络 MTU:包太大被丢弃的现象

在 Docker Desktop 上实测网络 MTU:虚拟机、docker0 和默认容器的 eth0 都是 65535;docker network create -o com.docker.network.driver.mtu=1400 让容器 eth0 和虚拟机里的网桥都变成 1400;容器之间 TCP 连接的 MSS 分别是 32741(默认)、1348(MTU 1400)、1228(MTU 1280)。

Docker 网络 MTU MSS Docker Desktop 真实验证 动画演示
Docker 容器原理 2026-10-10

手动搭一个网络命名空间:ip netns 与 veth 复刻 bridge

实测容器网卡的真身:容器里 eth0@if2364 的对端是虚拟机里的 veth8554796(两端 ifindex 与 iflink 互指,类型 veth,挂在 docker0 上),两端计数器的增量相同(10504 字节);并在特权容器里手动用 ip netns 和 veth 搭了一对连通的虚拟网线。

Docker veth 网络命名空间 ifindex iflink docker0 真实验证 动画演示
Docker 容器原理 2026-10-10

容器里的 /etc/resolv.conf:DNS 配置从哪里来

在 Docker Engine 29.8.2 里实测容器的 /etc/resolv.conf:它是来自 /var/lib/docker/containers/容器ID/resolv.conf 的单文件 bind mount,默认复制虚拟机的 nameserver 192.168.65.7;在容器里改它会同步到那个文件,但 restart 或 stop 再 start 后被重新生成;--dns、--dns-search、--dns-opt 逐项写入;daemon.json 里没有 dns 配置。

Docker resolv.conf DNS --dns --dns-search 容器启动 真实验证 动画演示
Docker 容器原理 2026-10-10

--add-host 与 /etc/hosts:谁在写这个文件

在 Docker Engine 29.8.2 里实测容器的 /etc/hosts:默认 6 行固定内容加“容器 IP + 容器 ID 前 12 位”;--add-host 的条目排在固定行之后,--hostname 与 --domainname 决定最后一行;/etc/hosts 优先于 DNS(--add-host github.com:10.9.9.11 让 ping 解析到该地址,而 nslookup 不受影响);容器里手改的内容在 restart 后丢失,--add-host 保留。

Docker /etc/hosts --add-host --hostname host-gateway 真实验证 动画演示
Docker 容器原理 2026-10-10

容器的 IPv6:开启条件与地址分配

在 Docker Engine 29.8.2 里实测容器的 IPv6:默认 bridge 没有(EnableIPv6=false,eth0 无 IPv6 地址、没有默认 IPv6 路由);docker network create --ipv6 自动选出 fd5c:c1ec:db63::/64,容器之间能按 IPv6 地址和名字(AAAA 记录)互通,还能 ping6 通外网的 2606:4700:4700::1111(往返约 202 ms)。

Docker IPv6 --ipv6 AAAA ULA 容器网络 真实验证 动画演示
Docker 容器原理 2026-10-10

连接跟踪:NAT 条目与大量短连接

进入 Docker Desktop 虚拟机读 iptables 与 conntrack:172.17.0.0/16 出网有 MASQUERADE,发布端口新增 DNAT 和放行规则;一次出站连接的 conntrack 条目显示回来方向的目的地址是虚拟机而不是容器;Mac 访问发布端口时 DNAT 包计数不增(监听者是 dockerd),容器经 172.17.0.1 访问则 DNAT +3;nf_conntrack_max=262144,删除容器后规则被清除。

Docker iptables NAT MASQUERADE DNAT conntrack 端口映射 真实验证 动画演示
Docker 容器原理 2026-10-10

depends_on 与健康检查:start 顺序不等于 ready

在 Docker Compose v5.5.1 里实测 depends_on:只写服务名时 web 比需要 3 秒才就绪的 db 只晚 0.10 秒启动;condition: service_healthy 让 web 等到健康检查通过(晚 3.61 秒);service_completed_successfully 在任务 exit 1 时让 up 以 1 退出、web 停在 Created;启动 c 会连带启动依赖,--no-deps 则只启动自己。

Docker Docker Compose depends_on healthcheck service_healthy 启动顺序 真实验证 动画演示
Docker 容器原理 2026-10-10

Compose profiles:按场景启动不同服务

在 Docker Compose v5.5.1 里实测 profiles:没有 profile 的服务总是启动,带 profile 的默认不启动,--profile 或 COMPOSE_PROFILES 才启动;点名一个服务(up debug、run tools)会直接激活它;没有 profile 的服务依赖带 profile 的服务时会报 invalid compose project;不带 profile 的 down 不会停掉带 profile 的服务。

Docker Docker Compose profiles COMPOSE_PROFILES 服务分组 真实验证 动画演示
Docker 容器原理 2026-10-10

Compose 覆盖文件:多个 -f 的合并规则

用 docker compose config 实测 Compose 多文件合并:不带 -f 时 compose.override.yaml 自动合并;单值覆盖、environment 和 labels 按键合并、ports 追加、volumes 按挂载目标合并;-f 越靠后优先级越高;!reset 清空、!override 整体替换列表。

Docker Docker Compose override 多文件合并 !reset !override 真实验证 动画演示
京ICP备2026067502号-1京公网安备11010502063487号