🌐 Docker 高级网络配置
1️⃣ 使用自定义网桥
默认情况下,Docker 使用 docker0
网桥。但您可以创建自定义网桥,并在启动容器时指定使用它:
sudo docker network create --driver bridge my_custom_bridge
sudo docker run -d --network=my_custom_bridge <image_name>
2️⃣ 容器专用网络
除了默认的共享网络,您还可以为每个容器创建独立的网络命名空间:
sudo docker network create --driver bridge --subnet 10.0.0.0/16 isolated_nw
sudo docker run -d --network=isolated_nw <image_name>
此容器现在运行在其自己的网络命名空间中,与其他容器隔离。
3️⃣ 容器间的链接
使用 --link
选项可以让一个容器访问另一个容器的网络栈:
sudo docker run -d --name containerA <image_name>
sudo docker run -d --link containerA:alias_for_A <another_image_name>
containerA
的网络现在可以在第二个容器中通过 alias_for_A
访问。
4️⃣ 配置容器的 IP 地址
您可以在创建容器时手动为其指定 IP 地址:
sudo docker network create --subnet=192.168.1.0/24 my_nw
sudo docker run -d --net my_nw --ip 192.168.1.5 <image_name>
5️⃣ 使用主机网络
使用主机网络意味着容器将共享其主机的网络命名空间,而不是在其自己的命名空间中运行:
sudo docker run -d --network host <image_name>
6️⃣ 配置容器的 DNS
您可以在启动容器时指定 DNS 服务器:
sudo docker run -d --dns 8.8.8.8 --dns 8.8.4.4 <image_name>
7️⃣ Docker 网络插件
Docker 支持第三方网络插件,例如 Weave、Calico 和 Flannel,使您可以进一步定制和扩展 Docker 网络。
🌐 Docker 网络快速配置指南
以下是一个简明的 Docker 网络配置指南,为您提供了主要命令和选项的概述:
🌉 Docker 服务启动时的网络选项
-
指定桥接网络:
docker daemon -b BRIDGE # 或 docker daemon --bridge=BRIDGE
-
定制 docker0 掩码:
docker daemon --bip=CIDR
-
Docker 服务端接收命令的通道:
docker daemon -H SOCKET # 或 docker daemon --host=SOCKET
-
容器间通信:
docker daemon --icc=true/false
-
容器间通信的 IP 转发:
docker daemon --ip-forward=true/false
-
允许 Docker 添加 iptables 规则:
docker daemon --iptables=true/false
-
设置容器网络的 MTU:
docker daemon --mtu=BYTES
-
设置默认 DNS 服务器:
docker daemon --dns=IP_ADDRESS
-
设置默认 DNS 搜索域:
docker daemon --dns-search=DOMAIN
📦 容器启动时的网络选项
-
设置容器主机名:
docker run -h HOSTNAME # 或 docker run --hostname=HOSTNAME
-
链接到其他容器:
docker run --link=CONTAINER_NAME:ALIAS
-
设置容器的网络模式:
docker run --net=bridge/none/container:NAME_or_ID/host
-
映射容器端口到宿主机:
docker run -p SPEC # 或 docker run --publish=SPEC
-
映射容器所有端口到宿主机:
docker run -P # 或 docker run --publish-all=true/false
🤖 Docker 容器访问控制指南
让我们深入探讨 Docker 容器之间和外部网络之间的访问控制,并为每一点提供相应的代码示例。
1️⃣ 容器访问外部网络
要使容器能够访问外部网络,首先确保 Linux 主机已经启用了 IP 转发。
# 检查 IP 转发是否已启用
$ sysctl net.ipv4.ip_forward
如果输出为 net.ipv4.ip_forward = 0
,那么需要启用 IP 转发:
# 启用 IP 转发
$ sysctl -w net.ipv4.ip_forward=1
启动 Docker 时,使用 --ip-forward=true
参数可以确保 Docker 自动启用 IP 转发。
# 启动 Docker 服务并启用 IP 转发
$ dockerd --ip-forward=true
2️⃣ 容器之间的通信
📌 访问所有端口
如果 Docker 使用默认配置(--icc=true
),那么容器之间可以自由通信。
# 启动 Docker 并设置 icc 为 true
$ dockerd --icc=true
但为了增强安全性,可以设置 --icc=false
,从而禁止容器之间的通信。
# 启动 Docker 并设置 icc 为 false
$ dockerd --icc=false
📌 访问指定端口
如果关闭了 --icc
之间的通信,仍然可以使用 --link
选项来允许两个容器之间的特定通信。
# 运行容器 A
$ docker run --name containerA -d some_image
# 运行容器 B 并连接到容器 A
$ docker run --link containerA:aliasname -d another_image
🔗 Docker 的 iptables 规则
Docker 使用 iptables 规则来控制容器之间和容器与外部网络之间的通信。
# 查看当前 iptables 规则
$ sudo iptables -nL
如果使用了 --link
选项,将会看到为这两个容器添加的 ACCEPT
规则,以及一个默认的 DROP
规则,该规则将禁止所有其他通信。
⚠️ 注意事项
- 使用
--link
选项时,必须使用 Docker 分配的容器名称或使用--name
选项指定的名称。当前不支持使用容器的主机名。 - 在进行网络相关配置时,一定要确保了解每个设置的含义,以及它们对容器和主机安全性的影响。
🚪 Docker 端口映射详解
端口映射是 Docker 使容器能够与外部网络交互的关键机制。下面我们将详细探讨这一点,并为每一部分提供示例。
1️⃣ 容器访问外部网络
容器可以默认访问外部网络,这是通过 IP 地址伪装实现的。
# 查看主机的 NAT 规则。
$ sudo iptables -t nat -nL
此命令将显示 MASQUERADE
规则,该规则将所有从 172.17.0.0/16
地址范围发出的流量的源地址伪装为宿主机的 IP 地址。
2️⃣ 外部网络访问容器
要使外部网络能够访问 Docker 容器,您可以使用 -p
或 -P
参数。
# 使用 -P 参数运行容器
$ docker run -P some_image
# 查看 NAT 规则
$ sudo iptables -t nat -nL
此命令将显示一个新的 DNAT
规则,该规则将从宿主机的一个随机端口(例如 49153
)到容器内的特定端口(例如 80
)的所有流量重定向。
或者,使用 -p
参数指定特定的端口映射。
# 使用 -p 参数映射宿主机的 80 端口到容器的 80 端口
$ docker run -p 80:80 some_image
# 查看 NAT 规则
$ sudo iptables -t nat -nL
此命令将显示一个新的 DNAT
规则,该规则将从宿主机的端口 80
到容器内的端口 80
的所有流量重定向。
🔐 限制外部访问
为了增加安全性,您可能希望限制哪些外部地址可以访问容器。
# 仅允许 IP 192.168.1.100 访问容器的 80 端口
$ docker run -p 192.168.1.100:80:80 some_image
此外,如果您想将 Docker 守护程序绑定到固定的 IP 地址,您可以修改 Docker 的配置文件。
// /etc/docker/daemon.json
{
"ip": "0.0.0.0"
}
确保在修改配置文件后重启 Docker 服务以应用更改。
🌉 Docker 网桥(docker0
)配置详解
Docker 的网络模型默认使用一个名为 docker0
的网桥来连接所有的容器。这使得容器之间、以及容器与主机之间能够相互通信。下面我们将详细探讨这一点,并为每个部分提供代码示例。
1️⃣ 查看当前 docker0
配置
首先,我们可以查看当前 docker0
网桥的状态。
# 使用 ip 命令查看 docker0 的状态
$ ip addr show docker0
2️⃣ 修改 docker0
的默认配置
Docker 允许您在启动时自定义 docker0
网桥的 IP 和 MTU。这是通过 --bip
和 --mtu
参数实现的。
# 例如,将 docker0 的 IP 设置为 192.168.1.5,并设置 MTU 为 1400
$ dockerd --bip=192.168.1.5/24 --mtu=1400
3️⃣ 查看网桥及其连接的接口
Linux 提供了一个名为 brctl
的工具来查看和管理桥接接口。
# 使用 brctl 查看当前系统中的所有网桥及其连接的接口
$ sudo brctl show
4️⃣ 查看容器内的网络配置
当您启动一个容器时,它会连接到 docker0
网桥,并从 Docker 的 IP 池中获取一个 IP 地址。
# 启动一个新的容器
$ sudo docker run -i -t --rm base /bin/bash
# 在容器内查看 eth0 的状态
$ ip addr show eth0
# 在容器内查看路由配置
$ ip route
通过上述命令,您可以看到容器的 eth0
接口的 IP 地址、子网掩码、以及默认网关(通常是 docker0
的 IP 地址)。
📌 小结
Docker 的网络模型为容器提供了灵活的网络通信能力。虽然默认配置对大多数用例来说已经足够,但知道如何自定义和管理这些配置对于高级用户和管理员来说非常有用。
🌉 自定义 Docker 网桥详解
Docker 默认使用 docker0
网桥,但您可以创建自己的网桥并让 Docker 使用它。下面我们将详细探讨这一点,并为每个部分提供代码示例。
1️⃣ 删除默认的 docker0
网桥
如果 Docker 服务正在运行,并且您希望使用自定义的网桥,首先需要停止 Docker 服务并删除 docker0
网桥。
# 停止 Docker 服务
$ sudo systemctl stop docker
# 删除 docker0 网桥
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0
2️⃣ 创建并配置自定义网桥 bridge0
# 创建新的网桥 bridge0
$ sudo brctl addbr bridge0
# 为 bridge0 分配 IP 地址
$ sudo ip addr add 192.168.5.1/24 dev bridge0
# 启动 bridge0
$ sudo ip link set dev bridge0 up
# 查看 bridge0 的配置
$ ip addr show bridge0
3️⃣ 配置 Docker 使用自定义网桥
编辑 Docker 的配置文件 /etc/docker/daemon.json
,并将 Docker 的默认网桥设置为您刚创建的 bridge0
。
{
"bridge": "bridge0"
}
4️⃣ 启动 Docker 服务
# 启动 Docker 服务
$ sudo systemctl start docker
5️⃣ 创建容器并验证其使用了 bridge0
# 创建一个新容器
$ sudo docker run -i -t --rm base /bin/bash
# 在容器中查看网络配置
$ ip addr
$ ip route
📌 小结
使用自定义的网桥可以使 Docker 的网络配置更加灵活。这允许您根据自己的需求和网络环境进行细致的网络配置。
🔧 工具与示例详解
为了更好地理解 Docker 的网络配置和如何自定义它,有一些第三方工具和示例可以供您参考。这里我们将探讨其中两个:pipework
和 playground
。
1️⃣ pipework
介绍:pipework
是一个强大的 shell 脚本,它可以帮助用户在复杂的场景中连接容器。这个工具非常适合那些想要创建复杂的网络拓扑或连接容器到多个网络接口或 VLAN 的人。
示例:假设您想将容器连接到一个特定的 VLAN:
# 使用 pipework 将容器 "my_container" 连接到 eth1 上的 VLAN 5,IP 地址 192.168.5.5/24
$ sudo pipework eth1 -i eth2 my_container 192.168.5.5/24@5
2️⃣ playground
介绍:playground
是一个项目,它提供了完整的 Docker 容器网络拓扑管理,包括路由、NAT 防火墙等功能。此外,还包括一些服务器,如 HTTP、SMTP、POP、IMAP、Telnet、SSH 和 FTP 服务器。这是一个完美的沙盒,供那些想要玩弄 Docker 网络配置的人使用。
使用:
- 克隆
playground
仓库。 - 使用其中的 Dockerfile 创建您的容器。
- 根据
playground
的文档和示例进行实验。
示例:
# 克隆 playground 仓库
$ git clone https://github.com/brandon-rhodes/playground
# 进入仓库目录
$ cd playground
# 使用 Dockerfile 创建容器
$ docker build -t my_playground .
# 运行容器
$ docker run -d --name playground_instance my_playground
📌 小结
这两个工具和示例可以帮助您更深入地了解 Docker 的网络配置和如何自定义它。但请注意,这些工具和示例可能需要您已经具备一定的 Docker 和网络知识。如果您是初学者,建议您首先熟悉 Docker 的基础知识,然后再使用这些高级工具和示例。
📝 编辑网络配置文件
Docker 允许用户在运行中的容器里编辑网络相关的配置文件。这为用户提供了额外的灵活性,允许在容器运行时进行网络设置的微调。但是要注意,这些修改是临时性的,它们不会永久保存,也不会包含在创建的 Docker 镜像中。
🛠️ 操作步骤:
-
进入容器的交互式 shell:
$ docker exec -it [CONTAINER_ID_OR_NAME] /bin/bash
这里,
[CONTAINER_ID_OR_NAME]
是您要进入的容器的 ID 或名称。 -
编辑
/etc/hosts
:该文件用于映射主机名到 IP 地址。您可以使用文本编辑器(如
vi
或nano
)来修改它:$ nano /etc/hosts
添加或修改映射,然后保存文件。
-
编辑
/etc/hostname
:该文件包含容器的主机名。要更改它,只需使用文本编辑器编辑文件内容:
$ nano /etc/hostname
更改主机名,然后保存文件。
-
编辑
/etc/resolv.conf
:该文件用于 DNS 解析。它列出了容器将用于名称解析的 DNS 服务器。要修改它,只需使用文本编辑器编辑文件内容:
$ nano /etc/resolv.conf
添加或修改 DNS 服务器的条目,然后保存文件。
-
退出容器:
$ exit
🚫 注意事项:
- 所做的更改是临时的。当容器停止或重新启动时,这些更改将丢失。
- 使用
docker commit
提交容器为新的镜像时,这些更改不会被保存。 - 在编辑配置文件时要小心,因为错误的配置可能会导致容器的网络功能出现问题。
总之,Docker 提供了在运行时修改容器网络配置的能力,但这些更改不是永久性的。在生产环境中使用时,请确保了解这些更改的持久性,并在必要时持久化所需的配置。
📝 配置 HTTP/HTTPS 网络代理
在使用 Docker 的过程中,您可能会遇到需要通过代理服务器访问 Internet 的场景。以下是如何为 Docker 配置 HTTP/HTTPS 代理的步骤。
1️⃣ 为 dockerd 设置网络代理
🛠️ 操作步骤:
-
创建配置文件夹:
sudo mkdir -p /etc/systemd/system/docker.service.d
-
创建代理的配置文件:
echo -e '[Service]\nEnvironment="HTTP_PROXY=http://proxy.example.com:8080/"\nEnvironment="HTTPS_PROXY=http://proxy.example.com:8080/"\nEnvironment="NO_PROXY=localhost,127.0.0.1,.example.com"' | sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf
-
刷新配置并重启 Docker 服务:
sudo systemctl daemon-reload sudo systemctl restart docker
2️⃣ 为 docker 容器设置网络代理
🛠️ 操作步骤:
-
更改 Docker 客户端配置:
echo '{ "proxies": { "default": { "httpProxy": "http://proxy.example.com:8080/", "httpsProxy": "http://proxy.example.com:8080/", "noProxy": "localhost,127.0.0.1,.example.com" } } }' > ~/.docker/config.json
-
运行容器时指定环境变量:
docker run --env HTTP_PROXY="http://proxy.example.com:8080/" --env HTTPS_PROXY="http://proxy.example.com:8080/" --env NO_PROXY="localhost,127.0.0.1,.example.com" [IMAGE]
3️⃣ 为 docker build 过程设置网络代理
🛠️ 操作步骤:
-
使用
--build-arg
指定环境变量:docker build \ --build-arg "HTTP_PROXY=http://proxy.example.com:8080/" \ --build-arg "HTTPS_PROXY=http://proxy.example.com:8080/" \ --build-arg "NO_PROXY=localhost,127.0.0.1,.example.com" .
-
在 Dockerfile 中指定环境变量:
FROM ubuntu:20.04 ENV HTTP_PROXY="http://proxy.example.com:8080/" ENV HTTPS_PROXY="http://proxy.example.com:8080/" ENV NO_PROXY="localhost,127.0.0.1,.example.com"
然后正常进行
docker build
操作。
🚫 注意事项:
- 请确保使用您自己的代理服务器地址和端口替换
http://proxy.example.com:8080/
。 - 如果您的网络环境不需要代理服务器,您可以跳过这些步骤。
📝 实例:创建一个点到点连接
在 Docker 中,可以创建一个点到点连接,使两个容器可以直接相互通信而不通过主机网桥。以下是步骤示例:
1️⃣ 启动两个容器
启动两个容器并设置网络为 none
,这样容器不会连接到任何网络。
docker run -i -t --rm --net=none base /bin/bash
得到容器的 Shell,然后在新的终端中再次运行相同的命令启动第二个容器。
2️⃣ 获取容器的进程 ID
使用 docker inspect
获取每个容器的进程 ID。
docker inspect -f '{{.State.Pid}}' [容器ID或名称]
3️⃣ 创建网络命名空间的链接
这是为了在后面的步骤中使用 ip netns
命令。
sudo mkdir -p /var/run/netns
sudo ln -s /proc/[第一个容器的PID]/ns/net /var/run/netns/[第一个容器的PID]
sudo ln -s /proc/[第二个容器的PID]/ns/net /var/run/netns/[第二个容器的PID]
4️⃣ 创建点到点连接
创建两个虚拟以太网接口,并将它们分别连接到两个容器。
sudo ip link add A type veth peer name B
sudo ip link set A netns [第一个容器的PID]
sudo ip netns exec [第一个容器的PID] ip addr add 10.1.1.1/32 dev A
sudo ip netns exec [第一个容器的PID] ip link set A up
sudo ip netns exec [第一个容器的PID] ip route add 10.1.1.2/32 dev A
sudo ip link set B netns [第二个容器的PID]
sudo ip netns exec [第二个容器的PID] ip addr add 10.1.1.2/32 dev B
sudo ip netns exec [第二个容器的PID] ip link set B up
sudo ip netns exec [第二个容器的PID] ip route add 10.1.1.1/32 dev B
5️⃣ 测试连接
现在你可以在一个容器中 ping 另一个容器的 IP 地址来测试连接。
在第一个容器中:
ping 10.1.1.2
在第二个容器中:
ping 10.1.1.1
这就是如何在 Docker 中创建点到点连接的方法。这种连接不需要子网和子网掩码,是一个直接的连接。