Network routing for docker container using macvlan - docker

TLDR; I cannot ping my docker containers from my other network clients. Only when a container actively pings the gateway I am able to reach the containers afterwards.
On my homenetwork (192.168.0.0/24) I run a gateway 192.168.0.1 which hosts a DNS server and also routes the internet traffic. My docker host (192.168.0.100) has a macvlan network, created with
docker network create -d macvlan --subnet=192.168.0.0/24 --gateway=192.168.0.100 -o parent=eth0 dockernet
My containers now do get static IPs, like 192.168.0.200. The containers can actively ping other physical hosts on the network, so that works fine.
But if I spin up a new container, it cannot be pinged from my physical network. Not from the docker host (which is expected as this seems to be a limitation of the macvlan network), nor from the gateway or any other client.
Once the container actively pings the gateway, it gets also reachable for other clients.
So I guess some routing needs to be done and there I need your help.
Clients run on debian buster and I use an unmanaged switch to connect the clients.

The missing information above was that I am running docker on raspbian.
So this question is actually a duplicate of Docker MACVLAN only works Outbound
runsudo rpi-update on the host to make it work

Related

Sharing VirtualBox VM and Docker Container network

I have an headless server with VirtualBox. It run multiple virtual machines. One of them is a web proxy. It redirect external access to the right VM in function of the subdomain. Those VMs are communicating between them with internal network (intnet).
I would like to add some docker container to this configuration. How could I successfully create a network shared between my docker containers and this proxy VM ?
I tried to create a bridge network with docker docker network create my_net and then connect the VM with a additional network card in 'bridged' mode.
With this config ping works but not the actual connection. It isn't impossible to display the web page into a browser.
Am I missing some configuration here ? Also, is it a good practice to connect one VM to a docker network ?
Run the containers on one of the VMs. Use a totally normal Docker setup here: create a network for inter-container communication but don't configure it, and completely ignore the container-private network details and IP addresses.
When you use the docker run -p option, that will publish a container's port on its VM's network interface(s). From that point, other VMs can call the published port using that VM's IP address, just as if it were a non-container process running on the VM. Conversely, containers should be able to make outbound calls to the other VMs without special setup.

Docker: how to access the hosts network with a docker container?

How can I access the hosts network with a docker container? Can I put a container in the hosts network with another IP from the hosts network?
Current situation:
Docker container (default bridge network): 172.17.0.2/16
Host (server): 10.0.0.2/24
Question:
Can I put the docker container on the 10.0.0.0/24 network as a secondary address?
(or) Can I access the hosts network on the container and vica versa?
Reason:
I want to access the hosts network from my container (for example: monitoring server).
I want the container to act as a server accessible from the hosts network on all ports.
Note:
I run several docker containers so a few ports are already forwarded from the host and these should remain so. So an all-port-forward from the hosts IP isn't really a solution here.
Setup on host:
basic docker system
Centos 7
Macvlan networks may be the solution you are looking for.
You could assign multiple MAC/IP addresses on virtual NICs over single physical NIC.
There are some prerequisites for using Macvlan.

docker-compose networking and publishing ports

I'm trying to better understand docker networking, but I'm confused by the following:
I spin up 2 contains via docker-compose (client, api). When I do this, a new network is created, myapp_default, and each container joins this network. The network is a bridge network, and it's at 172.18.0.1. The client is at 172.18.0.2 and the api is at 172.18.0.3.
I can now access the client at 172.18.0.2:8080 and the api at 172.18.0.3:3000 -- this makes total sense. I'm confused when I publish ports in docker-compose: 8080:8080 on the client, and 3000:3000 on the api.
Now I can access the containers from:
Client at 172.18.0.1:8080, 172.18.0.2:8080, and on the docker0 network at 172.17.0.1:8080
API at 172.18.0.1:3000, 172.18.0.3:8080, and on the docker0 network at 172.17.0.1:3000
1) Why can I access the client and api via the docker0 network when I publish ports?
2) Why can I connect to containers via 172.17.0.1 and 172.18.0.1 at all?
You can only access the container-private IP addresses because you're on the same native-Linux host as the Docker daemon. This doesn't work in any other environment (different hosts, MacOS or Windows hosts, environments like Docker Toolbox where Docker is in a VM) and even using docker inspect to find these IP addresses usually isn't a best practice.
When you publish ports they are accessible on the host at those ports. This does work in every environment (in Docker Toolbox "the host" is the VM) and is the recommended way to access your containers from outside Docker space. Unless you bind to a specific address, the containers are accessible on every host interface and every host IP address; that includes the artificial 172.17.0.1 etc. that get created with Docker bridge networks.
Publishing ports is in addition to the other networking-related setup Docker does; it doesn't prevent you from reaching the containers by other paths.
If you haven't yet, you should also read Networking in Compose in the Docker documentation. Whether you publish ports or not, you can use the names in the docker-compose.yml file like client and api as host names, connecting the the (unmapped) port the actual server processes are listening on. Between this functionality and what you get from publishing ports you don't ever actually need to directly know the container-private IP addresses.

How to expose the docker container ip to the external network?

i want to expose the container ip to the external network where the host is running so that i can directly ping the docker container ip from an external machine.
If i ping the docker container ip from the external machine where the machine hosting the docker and the machine from which i am pinging are in the same network i need to get the response from these machines
Pinging the container's IP (i.e. the IP it shows when you look at docker inspect [CONTAINER]) from another machine does not work. However, the container is reachable via the public IP of its host.
In addition to Borja's answer, you can expose the ports of Docker containers by adding -p [HOST_PORT]:[CONTAINER_PORT] to your docker run command.
E.g. if you want to reach a web server in a Docker container from another machine, you can start it with docker run -d -p 80:80 httpd:alpine. The container's port 80 is then reachable via the host's port 80. Other machines on the same network will then also be able to reach the webserver in this container (depending on Firewall settings etc. of course...)
Since you tagged this as kubernetes:
You cannot directly send packets to individual Docker containers. You need to send them to somewhere else that’s able to route them. In the case of plain Docker, you need to use the docker run -p option to publish a port to the host, and then containers will be reachable via the published port via the host’s IP address or DNS name. In a Kubernetes context, you need to set up a Service that’s able to route traffic to the Pod (or Pods) that are running your container, and you ultimately reach containers via that Service.
The container-internal IP addresses are essentially useless in many contexts. (They cannot be reached from off-host at all; in some environments you can’t even reach them from outside of Docker on the same host.) There are other mechanisms you can use to reach containers (docker run -p from outside Docker, inter-container DNS from within Docker) and you never need to look up these IP addresses at all.
Your question places a heavy emphasis on ping(1). This is a very-low-level debugging tool that uses a network protocol called ICMP. If sending packets using ICMP is actually core to your workflow, you will have difficulty running it in Docker or Kubernetes. I suspect you aren’t actually. Don’t worry so much about being able to directly ping containers; use higher-level tools like curl(1) if you need to verify that a request is reaching its container.
It's pretty easy actually, assuming you have control over the routing tables of your external devices (either directly, or via your LAN's gateway/router). Assuming your containers are using a bridge network of 172.17.0.0/16, you add a static entry for the 172.17.0.0/16 network, with your Docker physical LAN IP as the gateway. You might need to also allow this forwarding in your Docker OS firewall configuration.
After that, you should be able to connect to your docker container using its bridge address (172.17.0.2 for example). Note however that it will likely not respond to pings, due to the container's firewall.
If you're content to access your container using only the bridge IP (and never again use your Docker host IP with the mapped-port), you can remove port mapping from the container entirely.
You need to create a new bridge docker network and attach the container to this network. You should be able to connect by this way.
docker network create -d bridge my-new-bridge-network
or
docker network create --driver=bridge --subnet=192.168.0.0/16 my-new-bridge-network
connect:
docker network connect my-new-bridge-network container1
or
docker network connect --ip 192.168.0.10/16 my-new-bridge-network container-name
If the problem persist, just reload docker daemon, restart the service. Is a known issue.

Docker container doesn't connect to another docker container on server

I'm using a Digital Ocean docker droplet and have 3 docker containers: 1 for front-end, 1 for back-end and 1 for other tools with different dependencies, let's call it back-end 2.
The front-end calls the back-end 1, the back-end 1 in turn calls the back-end 2. The back-end 2 container exposes a gRPC service over port 50051. Locally, by running the following command, I was able to identify the docker service to be running with the IP 127.17.0.1:
docker network inspect bridge --format='{{json .IPAM.Config}}'
Therefore, I understand that my gRPC server is accessible from the following url 127.17.0.1:50051 within the server.
Unfortunately, the gRPC server refuses connections when running from the docker droplet while it works perfectly well when running locally.
Any idea what may be different?
You should generally set up a Docker private network to communicate between containers using their container names; see e.g. How to communicate between Docker containers via "hostname". The Docker-internal IP addresses are subject to change if you delete and recreate a container and aren't reachable from off-host, and trying to find them generally isn't a best practice.
172.17.0.0/16 is a typical default for the Docker-internal IP network (127.0.0.0/8 is the reserved IPv4 loopback network) and it looks like you might have typoed the address you got from docker network inspect.
Try docker run with following command:
docker run -d -p {server ip}:12345 {back-end 2 image}
It will expose IP port to docker container and will be accessible from other servers.
Note: also check firewall rules, if firewall is blocking access.
You could run docker binding to ip and port as shown by Aakash. Please restrict access to this specific IP and port to be accessed only from the other docker IP and port - this will help to run docker private and doesn't allow other (even the other docker/instances within your network).

Resources