nginx-proxy is an automated Nginx reverse proxy for Docker that watches containers start and stop and rewrites its own proxy configuration in response, and it is for anyone running containerised services who needs hostname-based routing without hand-editing nginx configuration files.
What it is
nginx-proxy sets up a container running nginx together with docker-gen. docker-gen generates reverse proxy configurations for nginx and reloads nginx whenever containers are started and stopped, so routing follows the containers that are actually running rather than a configuration file someone has to keep current. The project lives in the Docker ecosystem and is written in Python under the MIT licence. It carries 19,914 stars, 3,044 forks and 327 open issues, with the most recent push on 2026-09-16.
The concrete problem it solves is the manual loop of writing nginx server blocks, wiring upstream addresses by hand, and reloading nginx every time a container moves. With nginx-proxy, a container is started with the environment variable VIRTUAL_HOST=subdomain.yourdomain.com; provided DNS resolves that hostname to the machine running nginx-proxy, a request to http://foo.bar.com is routed to the container that declared VIRTUAL_HOST=foo.bar.com. Two conditions apply to proxied containers: they must expose the port to be proxied, either through the EXPOSE directive in their Dockerfile or the --expose flag to docker run or docker create, and they must share at least one Docker network with the nginx-proxy container. By default, when no --net flag is passed, the nginx-proxy container attaches only to the default bridge network and cannot reach containers on other networks.
Key capabilities
- Automatic reverse proxy configuration driven by
docker-gen, which regenerates nginx configs and reloads nginx on container start and stop events.
- Per-container routing declared through the
VIRTUAL_HOST environment variable, with no hand-written nginx configuration required.
- Debian based image
nginxproxy/nginx-proxy:1.11, built on the nginx:mainline image, itself based on the Debian slim image.
- Alpine based variant
nginxproxy/nginx-proxy:1.11-alpine, built on the nginx:alpine image.
-dockergen variant nginxproxy/nginx-proxy:1.11-dockergen, intended for a separate containers setup alongside the official nginx image.
- Docker socket integration through the read-only mount
/var/run/docker.sock:/tmp/docker.sock:ro, which lets docker-gen observe containers.
- Documented handling of virtual ports and custom external HTTP/HTTPS ports for cases where a port number cannot be supplied in
VIRTUAL_HOST.
Who uses it and how
- Single-host Docker deployments that publish port 80 and route many subdomains to many application containers, with
VIRTUAL_HOST set per application.
- Setups built from the standard
docker run pattern, where the proxy container is started detached under the name nginx-proxy and application containers join it on a shared network.
- Separate containers deployments, where the
-dockergen image runs the generator in its own container next to the official nginx image.
- Hosts where multiple Docker networks are in use, which require explicit network attachment so the proxy can reach containers outside the default bridge.
Getting started
Run the proxy with docker run --detach --name nginx-proxy --publish 80:80 --volume /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy:1.11, then start any container to be proxied with the environment variable VIRTUAL_HOST=subdomain.yourdomain.com set. Image flavours are pulled as nginxproxy/nginx-proxy:1.11, nginxproxy/nginx-proxy:1.11-alpine or nginxproxy/nginx-proxy:1.11-dockergen.
How it compares
Within the facts, the only related tools named are nginx itself and docker-gen, and nginx-proxy sits between them rather than beside them: it is the packaging that couples a running nginx to docker-gen's generated configuration. It does not replace nginx, which still serves the traffic, and it does not replace docker-gen, which does the config generation and the reload.
When to use it — and when not to
A self-hoster must operate the Docker host, grant the socket mount to the proxy container, and arrange shared networks and DNS resolution; no database, storage backend or SMTP dependency appears in the facts, so none has to be run. The project should not be chosen by anyone who cannot pin image tags, because the README explicitly warns against using the latest, alpine and dockergen tags in production: those tags point to the latest commit on the main branch, carry no promise of stability, and risk uncontrolled updates to non backward compatible versions. With 327 open issues, users should also expect to read the issue tracker rather than assume every edge case is settled.
project readme (upstream, from github) — read inline

nginx-proxy

nginx-proxy sets up a container running nginx and docker-gen. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
See Automated Nginx Reverse Proxy for Docker for why you might want to use this.
Usage
To run it:
docker run --detach \
--name nginx-proxy \
--publish 80:80 \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/nginx-proxy:1.11
Then start any containers (here an nginx container) you want proxied with an env var VIRTUAL_HOST=subdomain.yourdomain.com
docker run --detach \
--name your-proxied-app \
--env VIRTUAL_HOST=foo.bar.com \
nginx
Provided your DNS is setup to resolve foo.bar.com to the host running nginx-proxy, a request to http://foo.bar.com will then be routed to a container with the VIRTUAL_HOST env var set to foo.bar.com (in this case, the your-proxied-app container).
The containers being proxied must :
- expose the port to be proxied, either by using the
EXPOSE directive in their Dockerfile or by using the --expose flag to docker run or docker create.
- share at least one Docker network with the nginx-proxy container: by default, if you don't pass the
--net flag when your nginx-proxy container is created, it will only be attached to the default bridge network. This means that it will not be able to connect to containers on networks other than bridge.
Note: providing a port number in VIRTUAL_HOST isn't suported, please see virtual ports or custom external HTTP/HTTPS ports depending on what you want to achieve.
Image variants
The nginx-proxy images are available in two flavors.
Debian based version
This image is based on the nginx:mainline image, itself based on the debian slim image.
docker pull nginxproxy/nginx-proxy:1.11
Alpine based version (-alpine suffix)
This image is based on the nginx:alpine image.
docker pull nginxproxy/nginx-proxy:1.11-alpine
Dockergen version (-dockergen suffix)
This image is meant to be used in a separate containers setup with the official nginx image.
docker pull nginxproxy/nginx-proxy:1.11-dockergen
[!IMPORTANT]
A note on latest, alpine and dockergen tags:
It is not recommended to use the latest (nginxproxy/nginx-proxy, nginxproxy/nginx-proxy:latest), alpine (nginxproxy/nginx-proxy:alpine) or dockergen (nginxproxy/nginx-proxy:dockergen) tag for production setups.
Those tags point to the latest commit in the main branch. They do not carry any promise of stability, and using them will probably put your nginx-proxy setup at risk of experiencing uncontrolled updates to non backward compatible versions (or versions with breaking changes). You should always specify the version you want to use explicitly to ensure your setup doesn't break when the image is updated.
Additional documentation
Please check the docs section.
Powered by

About this repository
[!NOTE]
This repository is officially maintained by ZeroSSL as part of our commitment to secure and reliable SSL/TLS solutions.
We welcome contributions and feedback from the community!
For more information about our services, including free and paid SSL/TLS certificates, visit https://zerossl.com.

</a>