How to assign public IP address to Docker container, so that I can access them on my network?

I know there are several similar questions, but none seems to work for me. I’ve scoured the internet for answer for two days. I have following situation:

VM host (VMware ESXI 5.5) with centos 7, running Docker 17.06. Two docker containers, running an app. Developers need to access that app via IP in our company network. I can’t use port mapping, because the app that will connects to the containers, will throw an error of mismatching IPs (input host ip vs. container ip, which is returned to connected app). I tried creating docker network:

docker network create
–driver bridge
–subnet=10.0.20.0/24
–gateway=10.0.20.1
–opt “com.docker.network.bridge.name”=“docker1”
shared_nw
And then run my container:

docker run --name container1 --net shared_nw --ip 10.11.40.xxx -d someimage
I am able to ping my laptop (ie. 10.140.134.56) from inside the container, but not the other way. I also tried using macvlan drivers, but to no avail.

docker network create
–driver macvlan
–subnet=10.0.20.0/24
–gateway=10.0.20.1
-o parent=eth0
shared_nw
According to what I found online, this should be quite easy to achieve, but I haven’t been able to do so.

To use public IP thats part of company network, you would need to use macvlan driver. What is the issue that you are facing with macvlan driver? Are you trying to ping from host to container where container is located or across the network? If you are trying to ping from same host, you need a macvlan interface on host as well.
In the bridge example you mentioned above, you gave subnet of 10.0.20.0/24, but ip you have mentioned 10.11.40.xxx, not sure if that is a typo. bridge network would not help your usecase since nat translation is done.
For more details of Docker macvlan network plugin, you can refer my blog here(https://sreeninet.wordpress.com/2016/05/29/docker-macvlan-and-ipvlan-network-plugins/)

Yes, I that is a typo. IP of my VM is 10.11.40.166 and my created docker network has 10.11.40.0/24. My container has ip 10.11.40.180. With the setting
docker network create
–driver bridge
–subnet=10.11.40.0/24
–gateway=10.11.40.1
–opt “com.docker.network.bridge.name”=“docker1”
shared_nw
I was able to ping from inside the container to my PC (docker exec -it Source ping 10.140.134.56), but I am not able to ping the container from my laptop (ping 10.11.40.180).

Is the container running directly on the laptop or is there a VM in the middle?
Try checking the route table in the laptop. Not sure if the nat rule is allowing 1 direction to work, but not work in another direction.

In a typical bridge network case, I have seen that the container ip is reachable from host and host ip is reachable from container. This would still not solve your public ip problem which you mentioned in your original question.

The Docker with all containers is running in VM. But our developers need to access these containers directly via ip from their computers, so they can test the changes they made to the code.

Since bridge with port mapping is not an option for you and that you want to use public ip address for container, macvlan driver is the way to go.

I’ve already tried that, is there something wrong with my setting? Or could it be, that the router does not support multiple mac adresses from single source?

is this what you are trying?
Host has an underlay interface eth0
Container running on host with macvlan driver with parent interface eth0

You are trying to ping container from host?

With macvlan bridge driver, you cannot directly ping host to container, it is blocked. You need to create 1 more macvlan interface in same host and then container can communicate to host.

For macvlan driver across hosts, promiscuous mode needs to be turned on the interfaces.

No, you don’t understand. I need to ping container from another PC in the same network. I don’t care about host and containers.

Ok. In macvlan, since a single interface has multiple mac and ip, some interface drivers drop packets in ingress unless promiscuous mode is turned on. That is 1 thing I would check in your case.

It is off. It must be turned on for the switch, that means, all the virtual machines in the network would have promiscuous mode and I can’t do that.

I’m not sure if I understand your use case but I understand u do not want promiscuous mode on.
But, if it is for developer’s support access via http to these applications, maybe a dedicated http reverse proxy would do?
How To: attach container-based fabio/nginx/… (I used fabio for automatic service discovery based configuration) to the network you use to communicate between containerized applications (in my case it was an overlay network) and expose needed endpoints via mapped IP:port on that “router”. This way application communication scheme does not change. For improved security, it can be made accessible from your development network only. Extra features are available on proxy should you need these.

I will look into it, but from the brief reading I am not sure, it will help.
My use case is following:

Our developed app needs ip and port to establish a connection to the second app. For example 10.11.40.166:2100.
I have container running, which have IP 172.17.0.2 with open port 2100. So our app connects to 10.11.40.166 on port 2100 which is forwarded to our containers port 2100. BUT the app inside the container will send back response with it’s “real” IP (172.17.0.2), and there is our conflict. Our developed app compares the input IP (10.11.40.166) and the “actual” (172.17.0.2) and throws an error.

so do I get it correctly :

  1. u want to access dockerized server by second out-of-docker client application that u now develop and that application is on non-docker network (10.11.x.y) - correct ?
  2. You do not intend to move this client application into container - correct ?
  3. If you publish server on 10.11.x.y then client app does some ip header comparison (what and why?) and throws an error ?
    ??

its only with macvlan ? or i can do it other way ?

Yes, that developed app is on non-docker network and I do not intend to move it to container, because it would be complicated for the developers if they would want to test their code (localhost). They can run the developed java app on their machine and just connect to the containers.
And yes, it uses the IP and port as a unique key, so when the app connects, it asks for host details (such as hostname, ip, port, …) And that is different from user input, so it ends with error, that it cannot connect on given endpoint.
Is it understandable now?

i did

docker network create -d macvlan --subnet=172.16.9.0/24 --gateway=172.16.9.1 -o parent=eno16780032 pub_net

docker run --net pub_net --ip 172.16.9.148 -v /mnt/tomcat_PROD/conf:/opt/tomcat/conf -v /mnt/tomcat_PROD/redouteapps:/opt/tomcat/redouteapps -p 8030:8030 -d centos_java8_tomcat8.5.16

but i cant ping the container from the host :frowning:

That is correct, you can’t ping the container from your host. But can you ping it from other pc in that network?

no :frowning: i can not …

do i need to create a macvlan interface in the host ?