ufw snippets

How to access a service running on the host from a docker container

Tagged container, docker, host, ip, docker-compose, subnet, ufw  Languages bash

How to access a service running on the host from a docker container? Easy…

  1. Create a custom network (bridge)
  2. Make the docker container use the network
  3. On the host make the service listen to the hosts IP address on the custom network
version: "3.8"
services:
  "mycontainer":
    image: registry.gitlab.com/xxx/mycontainer:v1
    networks:
      - mynetwork
    env_file: ./mycontainer.env
networks:
  mynetwork:
    ipam:
      config:
        - subnet: 172.25.0.0/16

The docker container will be assigned an IP from the 172.25.0.0/16 subnet.

Now, just make sure the service is listening to the host’s IP address on the network which should be 172.25.0.1.

Lastly, remember to allow the traffic in the firewall. See UFW example below:

# Check where the connection is coming from:
sudo dmesg
# Unblock the connections by source IP
sudo ufw allow in from "172.25.0.5" to 172.17.0.1 port 5432
# Or, unblock the connections by network name
sudo ufw allow in on <name of network> to 172.17.0.1 port 5432

Bad ideas

There are many other ways of achieving this, which are more or less bad ideas…

  • Option 1: docker hostnames

This option is mostly useful in development environments:

# Mac
ping docker.for.mac.localhost

# Windows
ping docker.for.win.localhost

# Linux: use the Docker IP or the hosts external IP, see:
# https://github.com/docker/for-linux/issues/264#issuecomment-385698947
  • Option 2: host networking

This option is not a good idea if you plan on hosting many projects on the same server.

Note that it’s not possible to use host networking on Mac or Windows, only Linux:

The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.

See:

UFW + Docker = No firewall

Tagged docker, elasticsearch, gotcha, iptables, ufw, wtf  Languages 

TLDR: Docker can and will override existing iptable rules and expose your services to the Internet

This means you have to think twice when installing Docker on a machine that is only protected by an iptables-based firewall such as UFW. You might think you are protected by your firewall, but you very likely are not. This is probably one of the more common reasons why Elasticsearch servers, which are unprotected by default, are exposed to the internet.

For details, see: https://github.com/docker/for-linux/issues/690

Solution 1: External firewall

One solution is to use a firewall provided by the hosting provider (DO, AWS, GCP, etc.).

Solution 2: Disable Docker’s iptables “feature”

Disable iptables in Docker by adding the following switch:

--iptables=false

Solution 2: Listen on private IPs

This is perhaps the easiest to implement and easiest to forget: expose your containers and services on one of the following private IP address ranges:

  • 10.0.0.0 to 10.255.255.255
  • 172.16.0.0 to 172.31.255.255
  • 192.168.0.0 to 192.168.255.255

Note that binding to 127.0.0.1 will not work with Docker Swarm.