Skip to content

Instantly share code, notes, and snippets.

@mikejoh
Last active April 3, 2024 16:37
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save mikejoh/04978da4d52447ead7bdd045e878587d to your computer and use it in GitHub Desktop.
Save mikejoh/04978da4d52447ead7bdd045e878587d to your computer and use it in GitHub Desktop.
Short guide on how to set up a Docker container as a DHCP server

Setting up a Docker container as a DHCP server

In this guide I’ve tested a number of different commands and configurations using Docker to run a container with dhcpd (+macvlan driver) to serve my clients in my home network. In the end i’ll migrate from my Windows 2012 R2 Server running DHCP to a much more lightweight Docker container (7.42 MB in total). Wow.

My home environment:

  • Firewall (Juniper)
    • I’m running IP helper for bootp which in this case means that i relay DHCP requests from various VLANs into one where i've placed my Windows 2012 R2 server. This is also where my container will live. See the FW configuration below:
forwarding-options {
	helpers {
		bootp {
			description "Global DHCP relay service";
			server 10.0.99.6;
			maximum-hop-count 4;
			interface {
				ge-0/0/x.XX;
				ge-0/0/x.XX;
			}
		}
	}
}
  • ESXi v6.5
    • Running a VM (Debian Jessie) where I’ve installed Docker. The VM have two network interfaces assigned to it, one in a “DMZ” zone and one which I will trunk all VLANs to via ESXi and a port group with VLAN id 4095 (trunk all VLANs).
    • On the port group that will be used for trunking VLANs i had to enable Promiscuous mode via the Security-settings.

dhcpd-as-container

Dockerfile

FROM alpine:latest
RUN set -xe \
	&& apk add --update --no-progress dhcp \
	&& rm -rf /var/cache/apk/*
RUN ["touch", "/var/lib/dhcp/dhcpd.leases"]
CMD ["/usr/sbin/dhcpd", "-4", "-f", "-d", "--no-pid", "-cf", "/etc/dhcp/dhcpd.conf"]

docker-compose.yml

version: '3'

services:
    dhcpd:
        build: .
        restart: unless-stopped
        networks:
            internal_network:
                ipv4_address: 10.0.99.6

        volumes:
            - ./dhcpd.conf:/etc/dhcp/dhcpd.conf

networks:
    internal_network:
        external:
            name: macvlan0

Configuring Docker and running container

  1. Create a VLAN interface on the Docker host and give it an address in the subnet
iface ens192.99 inet static
  address 10.0.99.5
  netmask 255.255.255.0
  1. Create a network using the macvlan driver.
docker network create -d macvlan --subnet=10.0.99.0/24 --gateway=10.0.99.1 -o parent=ens192.30 macvlan0
  1. Here's the Docker container repo: docker-dhcpd
  2. My dhcpd.conf that have worked for me, remember that i'm using a DHCP relay between the client and server
authoritative;

default-lease-time 86400;
max-lease-time 86400;

# This is a workaround to let this dhcpd server serve requests to other subnets
# then it's own.
# If this is not present then the dhcpd daemon will throw an error and exit.
subnet 10.0.99.0 netmask 255.255.255.0 {
}

# This is my WLAN subnet
subnet 10.0.100.0 netmask 255.255.255.0 {
	option routers 10.0.100.1;
	option subnet-mask 255.255.255.0;
	range 10.0.100.150 10.0.100.200;
	option broadcast-address 10.0.100.255;
	option domain-name-servers 8.8.8.8, 8.8.4.4;
}
  1. Build the Docker image (from within project directory)
docker build . -t dhcpd
  1. Run the container
docker run -d --restart unless-stopped --ip 10.0.99.6 --net=macvlan0 dhcpd

or simply

docker-compose up -d
  1. Copy the dhcpd.lease file from the container to your local filesystem to check if you have any active leases
docker cp <Container ID>:/var/lib/dhcp/dhcpd.leases .
@nbctcp
Copy link

nbctcp commented Oct 16, 2020

I have some questions
Let say I have 2 dhcp servers. now I set range manually like you
Is there I can set automatically, so that if 1 dhcp server down, the other will take whole range
tq

@Eusono
Copy link

Eusono commented Nov 17, 2020

I have some questions
Let say I have 2 dhcp servers. now I set range manually like you
Is there I can set automatically, so that if 1 dhcp server down, the other will take whole range
tq

The way the DHCP helper statements work is top-down. If you had two DHCP servers running and one went down, L3 device would recognize that the DHCP server is unavailable and send the request to the next server in the list. All you need to do is make sure that the DHCP server checks if the IP is in use before creating a lease. With dhcpd, this is done by default see here. Essentially the "failover" DHCP server will start handing out new leases, and the devices that got DHCP from the pervious server retain their IP config for the duration of the lease. When they request a new address, it will certainly change, because the lease table is different on server 2. You could do some RSYNC magic to make sure the lease tables are matched up, but honestly I don't think this is a big deal. If you are using DDNS, just make sure both DHCP servers update BIND correctly, and you're all set. The one part I'm unsure about here is having the old DNS entry removed...

There are HA options with DHCP servers... windows for example has a DHCP failover feature, but really it's more like the range is split 80/20 between the two servers. It's not like LB with HAProxy and two Apache servers for example.

@evertos
Copy link

evertos commented Feb 18, 2021

Awesome explanation on how the network part is working within Docker!

@conan202
Copy link

conan202 commented Apr 29, 2021

hi ,why parent=ens192.30 and not parent=ens192.99?,i try make ansible playbook with this but i can't test dhcp with nmap --script broadcast-dhcp-discover -e ens192.99(or interface name) but i can't recive respose of request.

The proyect is in :

https://github.com/conan202/dhcpdeploy.git

Thank's!!!

@r0binary
Copy link

r0binary commented Sep 4, 2022

I used https://github.com/cmatsuoka/dhcpcheck succesfully in the past.

@flyemsafe
Copy link

hi ,why parent=ens192.30 and not parent=ens192.99?,i try make ansible playbook with this but i can't test dhcp with nmap --script broadcast-dhcp-discover -e ens192.99(or interface name) but i can't recive respose of request.

The proyect is in :

https://github.com/conan202/dhcpdeploy.git

Thank's!!!

Did you figure out why no response with the nmap dhcp discover? I am seeing the same issue.

@Julinius
Copy link

Hi, do you think it could be deployed in a production environment ? pros ? cons ? Thanks ;-)

@sat437
Copy link

sat437 commented Jul 5, 2023

is there a way to run it under proxy dhcp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment