Skip to main content

UPnP with Docker

How-to

Getting straight to the point. How do I set up a docker container to continuously configure UPnP entries to point to the host with configurable ports?

First, you'll need a bash script to execute the required commands to create or update the UPnP entry:

update_upnp
#!/bin/bash

port=$1
protocol=$2
echo "Updating UPnP entry with port [$port] and protocol [$protocol]"

gateway=$(ip route | head -1 | awk '{print $3}')
echo "Detected gateway is [$gateway]"

# port - e.g. 80
# protocol - TCP or UDP
upnpc -e 'your-app-name' -r $port $protocol

echo "Done updating UPnP entry with port [$port] and protocol [$protocol]"

Second, a Dockerfile with the required packages and configured crontab:

Dockerfile
FROM alpine:latest

RUN apk update
RUN apk add bash
RUN apk add miniupnpc

RUN mkdir /scripts
WORKDIR /scripts
COPY update_upnp .
RUN chmod a+x ./update_upnp

# cron to update each UPnP entries every 5 minutes
RUN echo -e "*/5\t*\t*\t*\t*\tbash /scripts/update_upnp 8080 TCP" >> /etc/crontabs/root

CMD ["crond", "-f"]

Finally, a docker-compose.yml file (only for reproduceability), that sets the network_mode of the container to host. Without this line, the container would see the docker network default route instead of the real default route and UPnP will not work.

docker-compose.yml
version: "3.4"
services:
upnp:
restart: always
network_mode: host # this is the important line!
build:
context: .

References