我想通过在我的网络上为 Docker 容器分配静态 IP 地址,使它们看起来和感觉起来像一个真实的系统。
目前我在主机上设置了一个网桥 (br0)。我已经DOCKER_OPTS="-b=br0"
在 /etc/default/docker
文件中进行了配置。我可以通过每个容器的/etc/network/interface
文件为其分配静态地址。
问题是 Docker 将继续自行分配 IP 地址。(如何停止这种情况?)更麻烦的是,它现在将使用桥接网络的 IP 方案。这将导致网络问题,因为它可以/将分配网络上已在使用的地址。
问题:
网络挂起/暂停
ping 容器时响应的地址可能会改变。
Error messages such as this are seen in the logs of the host:
kernel: [31912.876161] br0: port 3(vethb228701) entered disabled state
kernel: [31913.441517] device veth122d9f8 left promiscuous mode
kernel: [22491.609856] audit: type=1400 audit(1434148604.621:124): apparmor="DENIED" operation="getattr" info="Failed name lookup - disconnected path" error=-13 profile="/usr/sbin/ntpd" name="var/lib/docker/aufs/diff/eb00895db3d297979df741cd560ccbea2ab4d572264bd703fc6cbc7ea2acb5c4/usr/lib" pid=30955 comm="ntpd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0
/etc/hosts
Docker 还为容器分配了一个与我的网络位于同一子网的地址。起初我以为这只是在容器文件中添加一行。它确实做到了,但即使删除它后仍然会出现问题。
例子:
root@myhostname:/# cat /etc/hosts
X.X.192.3 myhostname.mydomain.com myhostname
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
root@myhostname:/# ifconfig
eth0 Link encap:Ethernet HWaddr 02:42:09:1a:c0:03
inet addr:X.X.X.X Bcast:X.X.X.X Mask:255.255.252.0
inet6 addr: fe80::42:9ff:fe1a:c003/64 Scope:Link
UP BROADCAST RUNNING MTU:1500 Metric:1
RX packets:231 errors:0 dropped:26 overruns:0 frame:0
TX packets:46 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:23719 (23.7 KB) TX bytes:3960 (3.9 KB)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
如果未通过命令行(-h)分配主机名来启动容器,它将使用随机分配的主机名
环境:
Host:
OS: Ubuntu 14.04.2
Arch: PPC64LE
Kernel: 3.16.0-30
docker version
:
Client version: 1.4.1-dev
Client API version: 1.17
Go version (client): gccgo (GCC) 5.0.0 20150118 (experimental)
Git commit (client): 7294f26
OS/Arch (client): linux/ppc64le
Server version: 1.4.1-dev
Server API version: 1.17
Go version (server): gccgo (GCC) 5.0.0 20150118 (experimental)
Git commit (server): 7294f26
硬件:
IBM Power 8, 8247-22L
CPUs: 192
Memory: 512GB
容器:
OS: Ubuntu 14.04.2
Arch: PPC64LE
Kernel: 3.16.0-30
网络:
brctl show
bridge name bridge id STP enabled interfaces
br0 8000.6cae8b6aaf64 no eth0
br0 Link encap:Ethernet HWaddr 6c:ae:8b:6a:af:64
inet addr:X.X.X.X Bcast: X.X.X.X Mask:255.255.252.0
inet6 addr: fe80::6eae:8bff:fe6a:af64/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:6750867 errors:0 dropped:80 overruns:0 frame:0
TX packets:1586308 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:1049658934 (1.0 GB) TX bytes:6936734104 (6.9 GB)
eth0 Link encap:Ethernet HWaddr 6c:ae:8b:6a:af:64
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7155242 errors:0 dropped:7598 overruns:0 frame:0
TX packets:6347549 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1212526214 (1.2 GB) TX bytes:7339350703 (7.3 GB)
Interrupt:249
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
RX packets:238 errors:0 dropped:0 overruns:0 frame:0
TX packets:238 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:22564 (22.5 KB) TX bytes:22564 (22.5 KB)
答案1
前段时间我也尝试过解决这个问题。我找不到一种方法来改变 docker 的 IP 分配行为,而无需禁用整个网络功能 ( --net=none
)。因此,我将一个尚未使用的子网分配给 docker 桥接接口,并让 docker 进行分配。我还编写了一个守护进程,用于监听某些 docker API 事件,然后将动态更新推送到我们的 DNS 服务器,这样我就不必关心 IP,而可以通过名称来寻址容器。
这是 DNS 守护进程的 github repo。 https://github.com/cschritt/docker-dns-daemon 我很快就会推送我的最新改动和一些重构。
答案2
不幸的是,似乎没有办法阻止 Docker 在桥接模式下为容器分配 IP 地址。为了pre-up ip addr flush dev eth0
将/etc/network/interface
Docker 的 IP 地址视为描述在这里。下面是如何实现的示例:
auto eth0
iface eth0 inet static
pre-up ip addr flush dev eth0
address 192.168.0.249
netmask 255.255.255.0
gateway 192.168.0.1
这种方法的缺点是,当 Docker 将其自己的错误/覆盖的 IP 地址注入容器/etc/hosts
文件中时,多个容器就会出现这种情况。我发现解决这个问题的唯一方法是安装inotify-tools
包并运行以下脚本,以便/etc/hosts
在 Docker 更改它时立即恢复到其预定义状态:
#!/bin/sh
while /usr/bin/inotifywait -e close /etc/hosts; do
cp -v /etc/hosts.orig /etc/hosts
done
上述脚本要求您将有效/etc/hosts.orig
文件添加到容器中。
答案3
从 Docker 1.10 开始,计划在未来几天发布,您可以在启动容器时使用和选项明确指定静态 IP 地址--ip=
,--ip6=
分别指定 IPv4 和 IPv6 地址。这些可以与docker run
和一起使用docker network connect
,只要容器存在,它们就会一直存在。