Running a Temporary DHCP Server in Docker
Sometimes you need a DHCP server for only a short lab window.
dnsmasq in Docker is a simple option because the container is disposable and the configuration is easy to inspect.
These examples assume Docker on Linux, because the container needs direct access to the target Layer 2 segment. Replace ens192 with your real interface name.
Important: run this only on a Layer 2 segment where this should be the active DHCP server. If another DHCP server is already active on the same segment, clients can receive leases from the wrong server.
There are two useful modes:
- Isolated DHCP only - the safer option. The lab segment uses a separate subnet, the host gets a secondary IP on the target interface, and DHCP does not advertise a default gateway or DNS server.
- DHCP with gateway and DNS - clients receive normal network parameters and can reach other networks through the advertised router.
1. Find the Target Interface
The following commands require the iproute2 package.
If you want to use the interface with the current default route:
ip route show default
To list all interfaces:
ip link show
2. Create the Dockerfile
Create Dockerfile:
FROM alpine:3.23.3
RUN apk add --no-cache dnsmasq
EXPOSE 67/udp 53/udp
ENTRYPOINT ["dnsmasq", "-k", "--log-facility=-"]
This keeps dnsmasq in the foreground and sends logs to stdout, so docker compose logs works as expected.
3. Create the Compose File
Create docker-compose.yml:
services:
dnsmasq:
build: .
container_name: temp-dhcp
restart: unless-stopped
network_mode: host
cap_add:
- NET_ADMIN
- NET_RAW
volumes:
- ./dnsmasq.conf:/etc/dnsmasq.conf:ro
network_mode: host is the important part. DHCP uses broadcast traffic, so host networking makes the container behave like a local DHCP service on the target interface.
Option 1: Isolated DHCP Only
Use this when the connected devices should not interact with the current network. The host only gets a temporary secondary IP so you can manage or test devices in the isolated subnet.
Add a temporary IP address to the host:
sudo ip addr add 10.255.255.1/24 dev ens192
Create dnsmasq.conf:
interface=ens192
bind-interfaces
log-dhcp
dhcp-authoritative
port=0
dhcp-range=10.255.255.10,10.255.255.254,255.255.255.0,1h
dhcp-option=option:router
dhcp-option=option:dns-server
What matters here:
interface=ens192binds DHCP to the target interface.port=0disables the DNS service indnsmasq.dhcp-range=...defines the lease pool and lease time.dhcp-option=option:routersuppresses the default router option.dhcp-option=option:dns-serversuppresses the default DNS server option.
Clients will receive only an address and mask from 10.255.255.0/24. They can talk to the host address 10.255.255.1 and to each other on that isolated segment, but they will not receive a default gateway or DNS server.
Option 2: DHCP with Gateway and DNS
Use this when clients should receive full connectivity settings. This must be the only DHCP server on the Layer 2 segment, or clients can receive leases from the wrong server.
Example where an existing router provides connectivity:
interface=ens192
bind-interfaces
log-dhcp
dhcp-authoritative
port=0
dhcp-range=192.168.50.100,192.168.50.150,255.255.255.0,1h
dhcp-option=option:router,192.168.50.1
dhcp-option=option:dns-server,8.8.8.8
In this mode, dnsmasq still does not run DNS itself. It only tells clients which DNS servers to use.
If the Docker host should act as the router for an isolated subnet, advertise the host IP as the gateway and enable IP forwarding and NAT on the host. Example:
sudo ip addr add 10.255.255.1/24 dev ens192
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 10.255.255.0/24 -o eth0 -j MASQUERADE
Then use this DHCP configuration:
interface=ens192
bind-interfaces
log-dhcp
dhcp-authoritative
port=0
dhcp-range=10.255.255.10,10.255.255.254,255.255.255.0,1h
dhcp-option=option:router,10.255.255.1
dhcp-option=option:dns-server,1.1.1.1,8.8.8.8
Replace eth0 in the NAT command with the host interface that has upstream connectivity.
4. Start the DHCP Server
Run:
docker compose up -d --build
docker compose logs -f dnsmasq
For Option 1 and the NAT variant of Option 2, the lease range is:
10.255.255.10 - 10.255.255.254
For the existing-router variant of Option 2, adjust the range, router, and DNS servers to match that network.
5. Stop and Clean Up
When the temporary DHCP window is over:
docker compose down
If you added the secondary IP manually, remove it:
sudo ip addr del 10.255.255.1/24 dev ens192
If you added the NAT rule, remove it too:
sudo iptables -t nat -D POSTROUTING -s 10.255.255.0/24 -o eth0 -j MASQUERADE
Notes
- Make sure no other DHCP server is active on the same Layer 2 segment.
- Replace
ens192andeth0with your real interface names. - Adjust the subnet, range, lease time, router, and DNS servers to fit your environment.
- If you enabled IP forwarding only for this test, disable it again after the test if the host should not route traffic.