expose server running on docker as service on the host

130 Views Asked by At

I am trying to get my head around networking with docker. First I create a docker image (based on ubuntu22) with net cat installed:

FROM ubuntu:22.04
RUN apt-get update -y && apt-get upgrade -y
RUN apt-get install -y netcat-openbsd

Build using:

docker build -f foobar.Dockerfile -t foobar .

I then run this as a container with a static IP (on RHEL8) as follows:

docker network create --driver bridge --subnet 172.20.0.0/16 foobar-net &&
docker run -v /home:/home -it --name foobar --network foobar-net --ip 172.20.0.2 -p 1781:1781 foobar /bin/bash

Inside the docker image I get netcat to listen for UDP packets on port 1781 using:

nc -l -u -p 1781

From the host I can see the IP address:

>docker inspect foobar 

    "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "b6019cec78bac4536f1ff66159dc5c724c9f5e205ef68f64fa23b41223a9e66c",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {
            "1781/tcp": [
                {
                    "HostIp": "0.0.0.0",
                    "HostPort": "1781"
                },
                {
                    "HostIp": "::",
                    "HostPort": "1781"
                }
            ]
        },
        "SandboxKey": "/var/run/docker/netns/b6019cec78ba",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "MacAddress": "",
        "Networks": {
            "dcs-net": {
                "IPAMConfig": {
                    "IPv4Address": "172.20.0.2"
                },
                "Links": null,
                "Aliases": [
                    "71efaf0b1ec4"
                ],
                "NetworkID": "84fc84937c72e2461751eb5edb74183c3ce9a5bad83c3310ba81847cd052327d",
                "EndpointID": "28f447f842036eb30e90574a4b6a4d94c826224afc42e2ffa68678c51f0d3331",
                "Gateway": "172.20.0.1",
                "IPAddress": "172.20.0.2",
                "IPPrefixLen": 16,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "02:42:ac:14:00:02",
                "DriverOpts": null
            }
        }
    }

I want to expose this port to the network. To do this I am trying:

firewall-cmd --zone=external --add-port=1781/udp
firewall-cmd --zone=public --add-forward-port=port=1781:proto=udp:toport=1781:toaddr=172.20.0.2

But I am having trouble connecting to it from the local machine:

 >nc -u 127.0.0.1 -p 1781
 hello world!
 Ncat: Connection refused.

 >nc -u 127.0.0.20 -p 1781
 hello world!
 Ncat: Connection refused.

 >nc -u <local machines IP> -p 1781
 hello world!
 Ncat: Connection refused.

I can see the rules I think are relevant using iptables-save:

-A DOCKER -p udp -m udp --dport 1781 -j DNAT --to-destination 172.20.0.2:1781
-A DOCKER ! -i br-84fc84937c72 -p tcp -m tcp --dport 1781 -j DNAT --to-destination 172.20.0.2:1781
-A POSTROUTING -s 172.20.0.2/32 -d 172.20.0.2/32 -p tcp -m tcp --dport 1781 -j MASQUERADE

or:

>firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eno2np1
  sources: 
  services: cockpit dhcpv6-client ssh
  ports: 9200/tcp 1781/udp
  protocols: 
  forward: no
  masquerade: no
  forward-ports: 
    port=1781:proto=udp:toport=1781:toaddr=172.20.0.2
  source-ports: 
  icmp-blocks: 
  rich rules: 

I do not entirely grok what I am doing here. Either my firewalld or docker network or both are wrong. Please help me grok.

This is a very common use case and so likely a duplicate but I cannot find anything which helps me identify what I'm missing so far.

1

There are 1 best solutions below

5
Amin Imani On

By default when you use -p option in docker, it published TCP port. You should use -p 1781:1781/udp

docker run -v /home:/home -it --name foobar --network foobar-net --ip 172.20.0.2 -p 1781:1781 /udp foobar /bin/bash