Usually, when launching Docker containers we don’t really know or care what IP address a specific container will be given. If proper service discovery and registration is configured, we just launch containers as needed and they make it into the application ecosystem seamlessly. Recently, I was working on a very edge-case multi-container application where every container needed to know (or be able to predict) every other containers’ IP address at run time. This was not a cascaded need where successor containers learn predecessors’ IP addresses, but more like a full mesh.
In Docker Engine 1.10 the docker run
command received a new flag namely the --ip
flag. This allows you to define a static IP address for a container at run time. Unfortunately, Docker Compose (1.6.2) did not support this option. I guess we can think of Engine as being upstream of Compose, so some new Engine features take a while to make it into Compose. Luckily, this has already made it into mainline dev for Compose and is earmarked for release with the 1.7.0 milestone (which should coincide with Engine 1.11). Find the commit we care about here.
get the dev build for Compose 1.7.0:
# cd /usr/local/bin
# wget -q https://dl.bintray.com/docker-compose/master/docker-compose-Linux-x86_64
# chmod 755 docker-compose-Linux-x86_64
# mv docker-compose-Linux-x86_64 docker-compose$(./docker-compose-Linux-x86_64 --version | awk '{print "-"$3$5}' | sed -e 's/,/_/')
# mv docker-compose docker-compose$(./docker-compose --version | awk '{print "-"$3$5}' | sed -e 's/,/_/')
# ln -s docker-compose-1.7.0dev_85e2fb6 docker-compose
# ls
lrwxrwxrwx 1 root root 31 Mar 30 08:38 docker-compose -> docker-compose-1.7.0dev_85e2fb6
-rwxr-xr-x 1 root root 7929597 Mar 24 08:01 docker-compose-1.6.2_4d72027
-rwxr-xr-x 1 root root 7938771 Mar 29 09:14 docker-compose-1.7.0dev_85e2fb6
#
In this case I decided to keep the 1.6.2 docker-compose
binary along with the 1.7.0 docker-compose
binary, then create a symlink to the one I wanted to use as the active docker-compose
Here’s a sample of how you might define a static IP address in docker-compose.yml
that would work using docker-compose
1.7.0
version: "2"
services:
host1:
networks:
mynet:
ipv4_address: 172.25.0.101
networks:
mynet:
driver: bridge
ipam:
config:
- subnet: 172.25.0.0/24
This feature looks pretty cool. I have a slightly different situation though; I want to scale services across multiple servers (docker-machines), and each of those servers has multiple IP addresses assigned. The problem is two of those services expose HTTP/HTTPS ports (80/443), but I want to be able to run both services on each docker-machine, just binding to separate IPs. Any ideas how I could achieve that?
Thanks for the comment! There are a few things to consider. You could run your services on alternate random ports and let a service discovery/registration mechanism notify upstream resources where the service is located. For example if you were running a webserver behind a reverse proxy, you could let docker choose random ports for the webserver and then use consul to register the service and notify your load balancer what ephemeral ports the service is available on.
You can also explicitly or implicitly tell docker where to schedule containers. In a swarm cluster, you can use compose to explicitly define a “constraint” on which docker engine a container will be scheduled. Using “volumes_from” implies that the containers will be scheduled on the same engine node, and defining “ports” will prevent containers using the same ports to be on the same host, essentially mutually excluding them from the same engine node.
In docker run you can define a port binding with -p and you can give it a host IP as well. For example docker run -p 192.168.1.201:80:80 will bind the host IP address 192.168.1.201 port 80 to the container port 80. You could then run multiple other containers on different host IPs using the same port (i.e. -p 192.168.1.202:80:80, -p 192.168.1.203:80:80).
We always assume (but isn’t always the case) that docker-compose follows docker run and that every docker run command is available to use in a docker-compose file. I would think you could define the “port” for a container and give it a host IP address to use for binding.
Cheers!
TODO: test port definition in compose file with IP defined
TODO: test swarm automatic scheduling with multiple engine node IPs available and identical statically defined host binding ports
Pingback: Change Docker network bridge IP range | ã‚‚ããƒã‚°