host-services-access

Accessing Host Service from Docker Containers

Sometimes services are run on the docker host (eg. database servers, HAProxy, etc) which need to be accessed from within the docker containers.

The usual practice is to bind mount the DB socket inside the container (eg /var/run/mysql/mysqld.sock). The problem with this approach is that if the DB server is restarted on the docker host, the socket will be removed and the bind mount will become stale. Applications inside the docker containers will fail until the container is recreated (docker-compose down; docker-compose up -d).

A better option is to alias a second IP address to the docker host's lo interface and use that IP to access the host services. As the lo interface is internal to the docker host, the same IP can be used on other docker hosts in the same LAN without IP conflicts. Further, using a Link Local Address from the 169.254.0.0/16 segment reduces the chance of IP conflicts with existing subnets.

This setup is particularly useful in a converged deployment where a pair of docker hosts are running MySQL Galera Cluster natively. The applications are installed in docker containers and need to access the local MySQL instance from within the containers. By using the secondary IP on the host's lo interface, the container applications will be routed to their local docker host services. This works well in docker swarms also.

Docker Host Netplan Config

# Sample ubuntu netplan config for aliasing 169.254.254.169/32 as secondary lo IP
network:
  version: 2
  ethernets:
    enp3s0:
      addresses:
        - 192.168.9.10/24
      routes:
        - to: default
          via: 192.168.9.1
          on-link: true
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
        search: [rsubr.in]

    lo:
      addresses: [ 169.254.254.169/32 ]

Docker Host on Proxmox LXC

Proxmox LXC containers do not use either netplan or ifupdown for setting up network interfaces. So if the docker host is a Proxmox LXC container, use /etc/rc.local for setup.

Save the below in /etc/rc.local and chmod 755 /etc/rc.localsystemd will automatically run this script on startup.

#!/bin/sh -e
# Filename: /etc/rc.local

# Alias a link-local IP to loopback so docker-containers can reach host services
ip addr add 169.254.254.169/32 dev lo

exit 0

Configuring Docker Containers

Inside the containers, use the 169.254.254.169 IP to connect to services running on the docker host.

// Sample wp-config.php fragment

/** Database hostname */

define( 'DB_HOST', '169.254.254.169' );

NOTES

  1. This exposes all host services to all containers, even ssh is exposed and is bad for security.
  2. To restrict this, use iptables firewall rules like the one below to prevent access to host ports between 1-1024 on IP 169.254.254.169.
$IPTABLES -A INPUT -p tcp -d 169.254.254.169 --dport 1:1024 -j DROP

#TODO: check the full security implications of this. Can docker containers access the services of other containers? Eg. two WordPress websites are published on the same docker host using Traefik. Can a malicious user on WP1 discover/access WP2 URLs or services?