# docker-gen: rendering config files from Docker container metadata

> docker-gen watches the Docker API and re-renders a template every time containers start or stop. It is the engine behind nginx-proxy, and it is useful anywhere container metadata has to become a file on disk.

**nginx-proxy/docker-gen** — Generate files from docker container meta-data

- Repository: https://github.com/nginx-proxy/docker-gen
- Stars: 4,632 · Forks: 610
- Language: Go
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/nginx-proxy-docker-gen

## What docker-gen actually generates, and for whom

docker-gen is a file generator. It renders a Go template against Docker container metadata and writes the result to a destination path. The README lists the intended uses: centralized logging configs for fluentd or logstash, logrotate files for container JSON logs, reverse proxy configs for nginx and haproxy, and service-discovery scripts that register containers in etcd or hipache.

The audience is narrower than "Docker users". It is for people who already have a daemon that reads a config file and reloads on a signal, and who want that file to be a function of which containers are running. The canonical example is nginx-proxy: docker-gen renders templates/nginx.tmpl into an nginx conf.d file, then sends HUP to nginx. If your proxy reads routes from an API or a database, docker-gen adds a file-watching layer you do not need.

The template is the product. docker-gen supplies the data and the trigger; deciding what a container's VIRTUAL_HOST or VIRTUAL_PORT means is entirely the template author's job.

## The watch, render, notify loop

The mechanism has three stages. First, docker-gen connects to the Docker API, by default over unix:///var/run/docker.sock, and lists containers, applying any -container-filter key=value pairs. Second, it renders the template with that container list plus the host's own metadata. Third, it writes the destination file and runs the notification step.

Notifications are where the tool is more careful than it first appears. -notify-sighup container-ID sends SIGHUP to a container, equivalent to docker kill -s HUP container-ID. -notify-container takes a container and a signal via -notify-signal, where -1 means call docker restart. -notify-filter selects containers by filter instead of by name. -notify runs an arbitrary command after regeneration, and -notify-output logs that command's stdout and stderr. A plain -notify restart xyz is the documented example.

In watch mode the loop is event-driven. The README states that by default docker-gen listens for the container events start, stop, die and health_status, and -event-filter narrows or extends that set, for instance -event-filter event=connect -event-filter event=disconnect. The -interval option sets a notify command interval in seconds, which matters because a burst of container events can otherwise cause a burst of reloads. -keep-blank-lines preserves blank lines in the rendered output, which is useful when a human has to read the generated file.

The data itself comes from the Docker API through github.com/fsouza/go-dockerclient, and templates get the Sprig function library, so string, list and arithmetic helpers are available without writing custom functions. Configuration can also come from files passed with -config, and the README notes that config files are merged when the option is repeated.

## Running docker-gen as a separate container

The README gives three deployment shapes: on the host, bundled inside another application's container, and as a standalone container next to the application it configures. The standalone shape is the one to copy when you do not want the Docker socket bound to a publicly exposed service.

Start the consumer with a shared volume for its config directory:

```bash
docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx
```

Fetch the nginx template and start docker-gen with the same volume, the Docker socket, and the notify flag:

```bash
mkdir -p /tmp/templates && cd /tmp/templates
curl -o nginx.tmpl https://raw.githubusercontent.com/nginx-proxy/docker-gen/main/templates/nginx.tmpl
docker run -d --name nginx-gen --volumes-from nginx \
   -v /var/run/docker.sock:/tmp/docker.sock:rw \
   -v /tmp/templates:/etc/docker-gen/templates \
   -t nginxproxy/docker-gen -notify-sighup nginx -watch -only-exposed /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
```

The last argument pair is template then destination. -watch keeps the process running and re-renders on events; -only-exposed restricts the container list to those with exposed ports. Then start a workload and give it the environment variables the template reads:

```bash
docker run --env VIRTUAL_HOST='example.com' --env VIRTUAL_PORT=80 ...
```

If the container starts and nginx returns the default page, the usual cause is a template that never matched the container, not a docker-gen crash. Read the generated /etc/nginx/conf.d/default.conf inside the nginx container to see what was actually rendered.

For a host install, the README's route is to download a release tarball, extract it and put the binary on your PATH:

```bash
wget https://github.com/nginx-proxy/docker-gen/releases/download/0.16.0/docker-gen-linux-amd64-0.16.0.tar.gz
tar xvzf docker-gen-linux-amd64-0.16.0.tar.gz
./docker-gen
```

Building from source is a single Makefile target. The Makefile stamps the version from git describe into the binary via -ldflags, and the module declares go 1.26. Repository layout separates cmd/docker-gen (the entry point), app/, internal/ and templates/, with integration/ holding the end-to-end tests.

## Where docker-gen stops being the right tool

The Docker socket is the first constraint. Mounting /var/run/docker.sock into a container grants that container the ability to talk to the Docker API, which is a broader privilege than reading a rendered config file suggests. The README acknowledges this by presenting the separate-container shape as a way to avoid binding the socket to a publicly exposed service, but the socket is still mounted.

The second constraint is that docker-gen has no opinion about correctness. It renders whatever the template says and writes the file. If the template emits invalid nginx syntax, docker-gen still succeeds and still sends the reload signal; the failure surfaces in the consumer's logs. There is no validation hook documented in the README.

The third is scope. docker-gen reads container metadata, not orchestrator state. Health-based routing, retries, circuit breaking and per-route middleware are outside it. A team that needs those has outgrown a file generator, and template complexity becomes the symptom: nginx.tmpl is a large file precisely because nginx-proxy pushes routing semantics into it.

Finally, watch mode is event-driven, and the README does not document rollback, a dry-run mode, or an atomic write guarantee for the destination file. If a consumer reads the file at the exact moment it is being rewritten, that is a race the documentation does not address.

## docker-gen compared with Traefik's provider model

Traefik is the natural alternative for the reverse proxy use case, and the difference is architectural rather than a matter of features. Traefik is the proxy. It has Docker and other providers built in, watches the Docker API itself, and computes routing internally. There is no template, no destination file, and no reload signal, because the routing table lives in the proxy's memory.

docker-gen is the opposite arrangement: a generator that knows nothing about proxying, paired with a proxy that knows nothing about Docker. The coupling point is a text file and a signal. That makes docker-gen work with nginx or haproxy as they are, including any module or directive you already depend on, and it makes the generated config inspectable with cat and diff. It also means you own the template, its Sprig usage, and every edge case in it.

If your requirement is a proxy that discovers containers, Traefik removes a moving part. If your requirement is nginx with a specific configuration, or a generated logrotate file, or an etcd registration script, docker-gen keeps the file-based workflow you already have. The README's own examples lean the second way: templates/fluentd.conf.tmpl, templates/logrotate.tmpl and templates/nginx.tmpl are all files for other daemons to consume.

## Licence, releases and the cost of staying current

docker-gen is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the whole of the licence implication here; questions about your own distribution obligations belong with your legal team, not with this article.

The release cadence visible in the repository is steady: 0.17.0, 0.17.1 and 0.17.2 all landed in July 2026, and the last push to main was on 2026-09-22. The project is not archived.

Upgrade cost is dominated by the template, not the binary. Replacing the docker-gen binary is a container tag or tarball swap, but a template written against an older release can depend on data fields or Sprig behaviour that changed, and the failure mode is a silently different rendered file rather than a build error. The integration/ directory and the Go tests give the maintainers coverage; a downstream template has no equivalent unless you write one. Pinning the docker-gen image tag and diffing the generated output before and after an upgrade is the practical way to bound that risk. Note also that the README's host-install example still references release 0.16.0, so do not copy that URL expecting the newest version.

## Conclusion

Adopt docker-gen when a file on disk has to track container state and you are willing to own the template: nginx-proxy users get it bundled, and anyone generating logrotate, fluentd or service-registration files can run it standalone against /var/run/docker.sock. Do not adopt it if you need a control plane with an API, health checks and per-route TLS policy, or if you cannot grant read access to the Docker socket. Before rolling it out, verify that your template renders under the Go template functions docker-gen ships, and that the notify command you pass to -notify-sighup or -notify actually reloads the consumer, because a wrong reload command leaves a stale config file in place with no error from docker-gen itself.

## FAQ

### What is docker-gen?

It is a file generator that renders Go templates using Docker container metadata and writes the result to a destination path. Typical outputs are nginx or haproxy reverse proxy configs, logrotate files and centralized logging configs.

### How does docker-gen relate to nginx-proxy?

The nginx-proxy/nginx-proxy image runs docker-gen inside the same container as nginx, rendering templates/nginx.tmpl into an nginx config file. The README presents that trusted build as the bundled-container example.

### Can I run docker-gen without mounting the Docker socket into my proxy container?

Yes. The separate-container deployment runs nginx and docker-gen as two containers sharing a config volume, with the Docker socket mounted only into the docker-gen container. The README describes this as a way to avoid binding the socket to a publicly exposed service.

### Which container events trigger a re-render?

By default docker-gen listens for start, stop, die and health_status. The -event-filter flag adds or narrows filters, for example -event-filter event=connect -event-filter event=disconnect.

### Does docker-gen validate the file it generates?

The README documents no validation step. docker-gen writes the rendered output and runs the notify command, so a template that produces invalid syntax for the consumer surfaces as a failure in that consumer, not in docker-gen.

## Sources

- [Issues](https://github.com/nginx-proxy/docker-gen/issues)
- [License: MIT](https://github.com/nginx-proxy/docker-gen/blob/main/LICENSE)
- [nginx-proxy/docker-gen on GitHub](https://github.com/nginx-proxy/docker-gen)
- [README](https://github.com/nginx-proxy/docker-gen/blob/main/README.md)
- [Releases](https://github.com/nginx-proxy/docker-gen/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nginx-proxy-docker-gen
