Problem
I'm using Docker-Compose and want to set a locally-addressable IP (such as 10.1.1.100) for one of the containers. This IP is not on my host machine's subnet.
Vagrant style
In a similar Vagrant project, there's a line:
config.vm.network :private_network, ip: "10.1.2.100"
This works great in that project. I can target the machine at 10.1.2.100 as if it's an available IP on my network. I don't even have to create a subnet.
Question
I've been looking for how I'd setup a container with a locally-addressable IP with Docker (specifically Docker-Compose), but haven't been able to get it working.
Failed configurations
I've tried adding networks, and assigned a static IP with ipv4_address: 10.1.1.100. Sadly, it seems as though this entire network is only accessible via Docker itself, not via the host machine.
If I try to use ports to expose an IP as 10.1.1.100:80:80, I get this error instead:
Cannot start service SERVICE_NAME: Ports are not available: listen tcp 10.1.1.100:80: bind: can't assign requested address.
But this works fine if I simply put 80:80. So it must be the IP binding that causes this issue.
I also tried setting network_mode on only this service and neither host nor bridge worked correctly.
Lastly, I found I could add to driver_opts:
com.docker.network.bridge.host_binding_ipv4: "10.1.1.100"
This made it impossible to start the container similar to the same error I received when using the ports method.
Related
I am using Docker Windows with WSL2.
From some answers I understand that connecting to an IP address exposed to the host network can be done from within a Docker container without any particular setup, but I cannot do it. Note that I do not want to access localhost, but a specific IP address (and port) of another device exposed to the host network.
I read a couple reasons on what could be the issue:
Missing firewall exception to allow communication between the external IP and the IP of the container.
I may have to use network_mode: "host", which however only seems to work in Linux
Many thanks.
Here is my situation:
First,I run a MySQL container(IP:172.17.0.2) on centOS;
Then I run a Nacos contanier with specified datasource(MySQL above) on the same host, but i didn't use the ip of the MySQL container, instead I used the ip of the bridge Gateway(172.17.0.1)(two containers both link to the default bridge).
What surprised me was that Nacos works well, it can query config data from MySQL container normally.
How did this happen? I have read some documention but didn't get the answer.It really confused me.
On modern Docker installations, try to avoid using the default bridge network. docker network create a network (it doesn't need any special options, but it does need to be created) and then launch your containers on --net that network. If you're using Compose, it creates a ("user bridge") network named default for you.
On your CentOS host, if you run ifconfig, you should see a docker0 interface with the 172.17.0.1 address. When you launch a container with the docker run -p option, that container is accessible via the first port number on all host interfaces, including the docker0 interface.
Meanwhile, inside a container (on the default bridge network), it sees that same IP address as the normal IPv4 gateway address (try docker run --rm busybox route -n). So, when you connect to 172.17.0.1:3306, you're connecting out to the host, and then connecting to the published port of the database container.
This isn't a totally standard way to connect between containers, though it will work. You should prefer using Docker named networks, which will let you connect to another container using the container's name without manually doing any IP-address lookups. If you really can't move off of the default bridge network, then the standard approach is to --link to the other container, but this entire path is considered outdated.
I have services defined in my own docker-compose.yaml file, and they
have their own bridged network to communicate with each other.
One of this services needs access to services running on the host machine.
According to this answer I added the following lines to my service within the docker-compose.yaml file:
extra_hosts:
- "host.docker.internal:host-gateway"
This works, despite the fact that the services running on the host need to bind to 0.0.0.0. If I bind to localhost, I'm not able to access them. But I don't want to expose the port to anyone else.
Is there a way to achieve this with bridged network mode?
I'm using the following versions:
Docker version 20.10.5, build 55c4c88
docker-compose version 1.28.5, build unknown
and I'm running on aarch64
the solution was just a misunderstanding from other readings. e.g.
another SO article
a baeldung article
As I explicitly defined an additional bridged network within my docker-compose.yaml file I assumed that I had to bind the service on the host to the IP address of that particular interface (I checked the IP address of the container and then looked up the address on the host's interface list) which was 172.20.0.1)
But docker0 was 172.17.0.1 (which should be the default one).
After binding the service on the host to the docker0 IP address, and adding
extra_hosts:
- "host.docker.internal:host-gateway"
to `docker-compose.yaml', I was able to access it, but it was also blocked from anyone else.
The explanation why this is working is probably, as explained here, b/c the IP route within each docker container includes the docker0 IP address, even if you have your own network set up.
Please correct me in case I mixed something up.
I am learning docker network. I created a simple docker-compose file that starts two tomcat containers:
version: '3'
services:
tomcat-server-1:
container_name: tomcat-server-1
image: .../apache-tomcat-10.0:1.0
ports:
- "8001:8080"
tomcat-server-2:
container_name: tomcat-server-2
image: .../apache-tomcat-10.0:1.0
After I start the containers with docker-compose up I can see that tomcat-server-1 responses on http://localhost:8001. At the first glance, the tomcat-server-2 is not available from localhost. That great, this is what I need.
When I inspect the two running containers I can see that they use the following internal IPs:
tomcat-server-1: 172.18.0.2
tomcat-server-2: 172.18.0.3
I see that the tomcat-server-1 is available from the host machine via http://172.18.0.2:8080 as well.
Then the following surprised me:
The tomcat-server-2 is also available from the host machine vie http://172.18.0.3:8080 despite port mapping is not defined for this container in the docker-compose.yml file.
What I would like to reach is the following:
The two tomcat servers must see each other in the internal docker network via hostnames.
Tomcat must be available from the host machine ONLY if the port mapping is defined in the docker-compose file, eg.: "8001:8080".
If no port mapping definition then the container could NOT be unavailable. Either from localhost or its internal IP, eg.: 172.18.0.3.
I have tried to use different network configurations like the bridge, none, and host mode. No success.
Of course, the host mode can not work because both tomcat containers use internally the same port 8080. So if I am correct then only bridge or none mode that I can consider.
Is that possible to configure the docker network this way?
That would be great to solve this via only the docker-compose file without any external docker, iptable, etc. manipulation.
Without additional firewalling setup, you can't prevent a Linux-native host from reaching the container-private IP addresses.
That having been said, the container-private IP addresses are extremely limited. You can't reach them from other hosts. If Docker is running in a Linux VM (as the Docker Desktop application provides on MacOS or Windows) then the host outside the VM can't reach them either. In most cases I would recommend against looking up the container-private IP addresses up at all since they're not especially useful.
I wouldn't worry about this case too much. If your security requirements need you to prevent non-Docker host processes from contacting the containers, then you probably also have pretty strict controls over what's actually running on the host and who can log in; you shouldn't have unexpected host processes that might be trying to connect to the containers.
I have several services specified inside a docker compose file that are communication with each other via links. Now I want one of these services to talk to the outside world and fetch some data from another server in the host network. But the docker service uses its internally assigned IP address which leads to the firewall of the host network blocking his requests. How can I tell this docker service to use the IP address of the host instead?
EDIT:
I got a step further, what I'm looking for is the network_mode option with the value host. But the Problem is that network_mode: "host" cannot be mixed with links. So i guess i have to change the configuration of all the docker services to not use links. I will try how this works out.
You should open a port like to that service
ports:
8000:8000
The 8000 on the left is the host port and the 8000 on the right will be the IP port