# dockerize: the wrapper that makes old apps behave in containers

> dockerize is Jason Wilder's MIT-licensed Go utility for wrapping applications in Docker containers: it generates configuration files from Go templates and environment variables at startup, tails log files to stdout and stderr, and waits for dependencies over TCP, HTTP or unix sockets before launching the main process. Releases arrive monthly, with v0.15.1 on 2026-09-12.

**jwilder/dockerize** — Utility to simplify running applications in docker containers

- Repository: https://github.com/jwilder/dockerize
- Stars: 5,209 · Forks: 422
- Language: Go
- License: MIT
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/jwilder-dockerize

## Three jobs around one process

dockerize does three things, and the README states them as a list: generate application configuration files at container startup from templates and environment variables, tail multiple log files to stdout and stderr, and wait for other services over TCP, HTTP(S) or unix sockets before starting the main process. The typical case is an application with configuration files whose values you want to control through the environment, and the README's example is precise: a Python application using SQLAlchemy cannot consume environment variables directly, requiring the database URL in a settings file as SQLALCHEMY_DATABASE_URI, so dockerize lets you set DATABASE_URL and rewrites the Python file when the container starts, optionally delaying the application until the database is listening. The second case is the logging inversion containers demand, applications writing to files when the ecosystem reads stdout, nginx and its access.log and error.log being the canonical offender. The mechanics are a wrapper: dockerize sits in ENTRYPOINT or CMD and launches your process only after its own work is done. The tool is written in Go, licensed MIT, and its origin is documented in a 2014 blog post by Jason Wilder titled A Simple Way To Dockerize Applications, which makes it one of the longer-lived utilities of the container ecosystem's first decade.

## The one-line nginx command that explains everything

The README's central example compresses all three features into a single CMD:

```dockerfile
CMD dockerize -template /etc/nginx/nginx.tmpl:/etc/nginx/nginx.conf -stdout /var/log/nginx/access.log -stderr /var/log/nginx/error.log -wait tcp://web:8000 nginx
```

Read left to right, it generates nginx.conf from a template, sends the access log to standard output and the error log to standard error so docker logs shows both, waits for a host named web to accept a TCP connection on port 8000, and only then starts nginx. Every flag is repeatable, multiple templates, multiple tailed files, multiple waits, so the wrapper scales from this simple case to applications with elaborate configuration trees and several dependencies. The colon syntax in -template, source and destination separated, is the whole convention, and files that already exist at the destination are overwritten unless -no-overwrite says otherwise.

## Go templates, sprig functions and directory mode

Templates use Go's text/template package, and the dependency list shows the practical upgrade: Masterminds sprig v3 is a direct dependency, the function library that adds string manipulation, defaults, math and date helpers to the standard template vocabulary, which is what makes real configuration files expressible without preprocessing. A template's destination can be omitted to render to stdout, useful for debugging, and a template source can be a directory, in which case every file inside is processed in the sorted order ioutil.ReadDir returns and written under the same name in the destination directory. The -delims flag swaps the {{ and }} delimiters for alternatives like <% %>, for the common collision where the configuration file's own syntax uses the braces dockerize wants. The examples directory demonstrates the two shapes that matter, an nginx configuration and a JSON case, the latter pairing with the gojq dependency for querying JSON structures during generation. Sprig is what makes the templates practical, contributing the functions configuration files actually need, defaults, string replacement, list and dictionary helpers, so a database host and port arriving from the environment become a connection string inside the template itself rather than in a wrapper script.

## Tail to stdout, with an inotify escape hatch

The logging half is built on the hpcloud/tail library, and its interface is repetition: pass -stdout for each file bound to standard output and -stderr for each bound to standard error, and dockerize follows them for the life of the container. This solves the troubleshooting problem the README names, where an application logging to the filesystem is invisible to docker logs and each application needs its own bespoke workaround. One environmental caveat is documented plainly: if inotify does not work in your container, some runtimes and configurations break file-watching, the -poll flag switches to polling for file changes instead. That single flag is the difference between working and broken on several minimal and security-hardened base images, and its presence as a first-class option rather than a footnote is typical of the tool's age and the breadth of environments it has been deployed into. The tails run alongside the main process rather than through a supervisor, and stop signals still reach the application through the exec layer, whose signal handling is covered by the repository's dedicated exec_signal_test.

## Waiting for services that started but are not ready

The waiting feature addresses a race every Compose user has met: a linked container having started does not mean the service inside it is listening, and the ecosystem's answer at the time was shell script hacks. dockerize waits on a protocol before launching the application, supporting file, tcp, tcp4, tcp6, http, https and unix targets, and the checks repeat for as many dependencies as the command line carries, the documented example combining tcp://db:5432, http://web:80 and file:///tmp/generated-file in a single invocation.

```bash
$ dockerize -wait tcp://db:5432 -wait http://web:80 -timeout 10s
```

A -timeout flag, defaulting to 10 seconds, bounds the wait, and on expiry the process exits with status code 1 so orchestrators see the failure rather than inheriting a half-started application. HTTP waits can carry headers, with a Basic Authorization example in the documentation, covering health endpoints behind authentication. The README links the historical Docker Compose issue where this capability was debated and declined at the ecosystem level, which is the origin story of the tool's most-used feature.

## Distroless base image and seven tarballs

Distribution covers the realistic matrix. Release artifacts are tarballs for linux amd64, armel, arm64 and armhf, alpine amd64, and darwin amd64 and arm64, seven targets covering the common server and developer machines. The jwilder/dockerize image is a base image built on gcr.io/distroless/static, with the binary in PATH, and its Dockerfile shows the discipline: a static CGO-disabled build stamped with the version, copied into a distroless nonroot image that runs as USER nonroot and defaults to --help, so the image contains a binary and essentially nothing else. For teams building their own images, the README carries copy-paste snippets for Ubuntu, fetching the tarball with wget then purging it, and Alpine, adding and removing wget and openssl around the download. That a logging-and-templating utility ships as a nonroot distroless artifact reads as a model of what a small container tool should be. The darwin builds let the same wrapper be tried on a workstation before it meets a cluster, and the ARM Linux targets cover the small-board and Graviton-style hosts that x86-only tooling quietly strands.

## A 2014 idea still shipping monthly in 2026

The project's origin is a 2014 blog post, A Simple Way To Dockerize Applications, and the codebase retains that era's virtues: a handful of Go files, exec.go, tail.go, template.go, each with tests including signal-handling and exec-error cases, an e2e directory, a Makefile running golangci-lint and go test with the race detector, and goreleaser producing those seven tarballs. Against that age, the release cadence is startlingly current, v0.14.0 on 2026-07-15, v0.15.0 on 2026-08-29 and v0.15.1 on 2026-09-12, with the last push the same day, on Go 1.27. Part of the waiting problem has since been absorbed into Compose healthchecks and depends_on conditions, but template generation and filesystem log tailing remain outside the orchestrator's scope, which is why this small wrapper from the industry's first container decade is still earning monthly releases. Nothing in the repository suggests a rewrite is coming, and the file count remains small enough to read in one sitting, which for infrastructure glue is the highest available compliment.

## Conclusion

Use dockerize when containerizing applications that read configuration from files rather than the environment, write logs to the filesystem instead of stdout, or crash when their dependencies are merely started rather than ready. Use Compose healthchecks with depends_on conditions when your only need is the waiting half and your stack already runs Compose natively. Verify first that your templates work with Go's text/template syntax and the sprig function library, decide whether inotify works in your runtime or the -poll fallback is needed, and pin an exact release tarball or the distroless base image tag in your Dockerfile.

## FAQ

### What is dockerize, the container tool?

dockerize is Jason Wilder's MIT-licensed Go utility for wrapping containerized applications. At startup it generates configuration files from Go templates and environment variables, tails log files to stdout and stderr, and waits for dependencies over TCP, HTTP(S) or unix sockets before starting the main process.

### How do you install dockerize?

Download a release tarball from GitHub, with builds for Linux amd64 and ARM variants, Alpine, and macOS amd64 and arm64, or use the jwilder/dockerize base image, which is distroless-based with the binary in PATH. The README also carries Ubuntu and Alpine Dockerfile snippets for installing the binary into your own images.

### How does dockerize wait for dependencies?

Pass -wait with a protocol URL, for example -wait tcp://db:5432, using the file, tcp, tcp4, tcp6, http, https or unix schemes, repeated for multiple dependencies. A -timeout flag, defaulting to 10 seconds, makes the process exit with status code 1 if services are not ready in time.

## Sources

- [Issues](https://github.com/jwilder/dockerize/issues)
- [jwilder/dockerize on GitHub](https://github.com/jwilder/dockerize)
- [License: MIT](https://github.com/jwilder/dockerize/blob/master/LICENSE)
- [README](https://github.com/jwilder/dockerize/blob/master/README.md)
- [Releases](https://github.com/jwilder/dockerize/releases)

---

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