How can I set a static IP address in a Docker cont

2019-01-16 10:03发布

I'm perfectly happy with the IP range that docker is giving me by default 176.17.x.x, so I don't need to create a new bridge, I just want to give my containers a static address within that range so I can point client browsers to it directly. I tried using

RUN echo "auto eth0" >> /etc/network/interfaces
RUN echo "iface eth0 inet static" >> /etc/network/interfaces
RUN echo "address 176.17.0.250" >> /etc/network/interfaces
RUN echo "netmask 255.255.0.0" >> /etc/network/interfaces
RUN ifdown eth0
RUN ifup eth0

from a Dockerfile, and it properly populated the interfaces file, but the interface itself didn't change. In fact, running ifup eth0 within the container gets this error:

RTNETLINK answers: Operation not permitted Failed to bring up eth0

11条回答
家丑人穷心不美
2楼-- · 2019-01-16 10:47

I'm using the method written here from the official Docker documentation and I have confirmed it works:

# At one shell, start a container and
# leave its shell idle and running

$ sudo docker run -i -t --rm --net=none base /bin/bash
root@63f36fc01b5f:/#

# At another shell, learn the container process ID
# and create its namespace entry in /var/run/netns/
# for the "ip netns" command we will be using below

$ sudo docker inspect -f '{{.State.Pid}}' 63f36fc01b5f
2778
$ pid=2778
$ sudo mkdir -p /var/run/netns
$ sudo ln -s /proc/$pid/ns/net /var/run/netns/$pid

# Check the bridge's IP address and netmask

$ ip addr show docker0
21: docker0: ...
inet 172.17.42.1/16 scope global docker0
...

# Create a pair of "peer" interfaces A and B,
# bind the A end to the bridge, and bring it up

$ sudo ip link add A type veth peer name B
$ sudo brctl addif docker0 A
$ sudo ip link set A up

# Place B inside the container's network namespace,
# rename to eth0, and activate it with a free IP

$ sudo ip link set B netns $pid
$ sudo ip netns exec $pid ip link set dev B name eth0
$ sudo ip netns exec $pid ip link set eth0 up
$ sudo ip netns exec $pid ip addr add 172.17.42.99/16 dev eth0
$ sudo ip netns exec $pid ip route add default via 172.17.42.1

Using this approach I run my containers always with net=none and set IP addresses with an external script.

查看更多
男人必须洒脱
3楼-- · 2019-01-16 10:48

Docker containers by default do not have sufficient privileges to manipulate the network stack. You can try adding --cap-add=NET_ADMIN to the run command to allow this specific capability. Or you can try --privileged=true (grants all rights) for testing.

Another option is to use pipework from the host.

查看更多
Deceive 欺骗
4楼-- · 2019-01-16 10:48

For completeness: there's another method suggested on the Docker forums. (Edit: and mentioned in passing by the answer from Андрей Сердюк).

Add the static IP address on the host system, then publish ports to that ip, e.g. docker run -p 192.0.2.1:80:80 -d mywebserver.

Of course that syntax won't work for IPv6 and the documentation doesn't mention that...

It sounds wrong to me: the usual wildcard binds (*:80) on the host theoretically conflict with the container. In practice the Docker port takes precedence and doesn't conflict, because of how it's implemented using iptables. But your public container IP will still respond on all the non-conflicting ports, e.g. ssh.

查看更多
Bombasti
5楼-- · 2019-01-16 10:51

Actually, despite my initial failure, @MarkO'Connor's answer was correct. I created a new interface (docker0) in my host /etc/network/interfaces file, ran sudo ifup docker0 on the host, and then ran

docker run --net=host -i -t ... 

which picked up the static IP and assigned it to docker0 in the container.

Thanks!

查看更多
Animai°情兽
6楼-- · 2019-01-16 10:51

You can set up SkyDns with service discovery tool - https://github.com/crosbymichael/skydock

Or: Simply create network interface and publish docker container ports in it like here https://gist.github.com/andreyserdjuk/bd92b5beba2719054dfe

查看更多
登录 后发表回答