nickjj/docker-django-example for Containerized Django
A production ready example Django app that's using Docker and Docker Compose.
At a glance
- What is it?
- nickjj/docker-django-example packages Django, PostgreSQL, Redis, Celery, asset builds, and common operational defaults into one Docker Compose project. It is a practical starting point for teams familiar with Docker Compose, but it is an example application rather than a turnkey deployment product.
- Who is it for?
- Adopt this repository as a reference or application skeleton if the team wants Django inside Docker Compose and is prepared to replace the sample identity, settings, assets, and infrastructure defaults. Do not adopt it as a finished product or as a substitute for an organization-specific deployment and security review.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 38 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What nickjj/docker-django-example bundles into a Django stack
nickjj/docker-django-example addresses a common handoff problem: turning a small Django application into a containerized stack without starting from an empty Dockerfile and Compose file. The README presents it both as a base for a new project and as a guide to Dockerizing an existing Django application. Its intended audience is a Django developer who wants PostgreSQL, Redis, Celery, static asset processing, and several production-oriented defaults represented in one repository.
The sample is deliberately small. It includes a `pages` app for a home page and an `up` app for health check pages, rather than a complete business domain. The backend uses PostgreSQL, Redis, and Celery. The frontend build uses esbuild, TailwindCSS, and Heroicons, while the repository leaves the choice of a JavaScript framework open. The README names Hotwire, htmx, Alpine.js, Vue.js, React, and jQuery as possible choices, but does not install any of them.
The project also adds Gunicorn as the application server, WhiteNoise for static files, and `django-debug-toolbar` for request information. Ruff performs linting and formatting. Logging goes to `STDOUT`, configuration is exposed through environment variables, and settings live in `src/config/settings.py`. These choices make the example more representative of a deployed service, but they also mean that adopting it involves accepting or reviewing several implementation decisions rather than receiving only a bare Django container.
How the Compose services split application responsibilities
The repository uses separate images and Compose services for different jobs. The Dockerfile begins with an `assets` stage based on `node:24.21.0-trixie-slim`. It installs assets with Yarn, adjusts ownership for the configured user and group, and runs the JavaScript and CSS builds when `NODE_ENV` is not `development`. In development it creates `/app/public` instead, leaving room for the asset service and file watching arrangement described elsewhere in the project.
A later `app-build` stage is based on `python:3.14.7-slim-trixie`. It installs build tools and PostgreSQL client support, copies `uv` and `uvx` from the project image, and copies Python dependency metadata. The selected environment includes `PYTHONUNBUFFERED=true`, `PYTHONPATH=.`, compiled bytecode, and a project environment under `/home/python/.local`. This separates dependency preparation and asset compilation from the normal runtime rather than requiring every development tool in the final image, although the truncated Dockerfile does not expose its complete final stage here.
In `compose.yaml`, reusable anchors define the common application and assets setup. The application receives `.env`, restart policy, a short stop grace period, and a mount for collected static files. PostgreSQL and Redis have persistent volumes and optional resource limits exposed through environment variables. Their profiles allow the default development file to start local infrastructure, while the `.env.example` notes that production deployments can omit them in favor of managed cloud services.
The `web` service depends on PostgreSQL and Redis with `required: false`. That Compose mechanism permits a deployment where either service is supplied externally, although dependency startup ordering does not replace application-level retry and health handling. Celery appears as a worker service and dependency. This is a service-oriented layout rather than one container containing Django, the database, Redis, workers, and the asset compiler.
Installing Docker Compose v2 and starting the sample
The README requires Docker. It also specifies Docker Compose v2 2.20.2 or newer because the configuration uses features unavailable in earlier Compose releases. On Windows, the documented workflow expects WSL or WSL 2 because the tutorial uses shell commands. Clone the repository and enter its directory as follows:
git clone https://github.com/nickjj/docker-django-example hellodjango
cd hellodjangoThe real `.env` file is excluded from version control, so copy the example before starting the services:
cp .env.example .envThe example environment selects the `postgres`, `redis`, `assets`, `web`, and `worker` profiles. It also enables development mode, sets `DEBUG=true`, and uses an insecure development secret. These values are appropriate for trying the sample, not for copying unchanged into production.
Build and start the stack with:
docker compose up --buildThe README says the first build can take 5 to 10 minutes because Docker must download images and build Python and Yarn dependencies. If port 8000 is already occupied, the README directs the reader to `.env` and the `DOCKER_WEB_PORT_FORWARD` variable. Compose profiles can also change which optional services run.
After the containers are running, initialize the database from a second terminal:
./run manage migrateThe reader should then open `http://localhost:8000` in a browser and see the sample Django application. This is the first useful acceptance check because it confirms that the web process, Django configuration, database connection, collected asset location, and migration path can work together.
Configuration defaults that shape local and production use
The `.env.example` separates mandatory settings from development conveniences. It sets `COMPOSE_PROJECT_NAME=hellodjango`, which controls the Compose project namespace independently of the checkout directory. It also configures BuildKit through `DOCKER_BUILDKIT=1`, enables bytecode suppression for development through `PYTHONDONTWRITEBYTECODE=true`, and supplies `SECRET_KEY=insecure_key_for_dev`.
The file explicitly warns that a production secret should be a random string of at least 50 characters and points to `./run secret` for generating one. This is a concrete operational boundary. The sample is not intended to be launched with its development secret, and the README does not claim that changing `DEBUG` alone makes an application production ready.
Compose build arguments derive container ownership from `APP_UID` and `APP_GID`, falling back to 1000. This avoids assuming that every developer writes files as UID 1000 and matters when a bind-mounted project directory is shared with a non-root container user. Resource ceilings for PostgreSQL and Redis are controlled through variables such as `DOCKER_POSTGRES_CPUS`, `DOCKER_POSTGRES_MEMORY`, `DOCKER_REDIS_CPUS`, and `DOCKER_REDIS_MEMORY`. Zero-valued defaults leave those limits unset.
The static-file layout is also explicit. Django is configured to serve from `public/`, while `collectstatic` writes to `public_collected/`. The application service mounts `${DOCKER_WEB_VOLUME:-./public_collected:/app/public_collected}` by default. This keeps generated static output separate from source assets, but it also makes the host directory and volume path part of the deployment contract.
Dependency upgrades and the cost of changing this reference stack
The example pins direct Python dependencies rather than accepting an open-ended version range. `pyproject.toml` lists Django 6.1.1, Celery 5.6.3, `psycopg` 3.3.5, Redis 8.1.0, Gunicorn 26.2.0, WhiteNoise 6.12.0, `ruff` 0.16.7, and other packages at exact versions. It requires Python 3.13 or newer, while the Dockerfile currently uses Python 3.14.7. Infrastructure images are likewise explicit, including `postgres:18.6-trixie` and `redis:8.10.1-trixie`.
That precision makes the repository reproducible as a reference, but it also transfers upgrade work to whoever adopts it. Python package changes can require lockfile regeneration through `uv.lock`. A Django update can affect settings, middleware, or application behavior. A PostgreSQL or Redis image update introduces a separate infrastructure change, and a Node update can affect Yarn and the frontend build even when Django is untouched.
The repository has no GitHub releases, so there is no published release history to use as an upgrade channel. Its last push was on 2026-09-15. That date is evidence of recent repository activity, but the repository itself is not a maintained Django distribution with release notes or a compatibility policy. An adopting team must define which versions it wants and test the resulting container stack.
The README specifically points to `./run` for package operations and describes `uv` as the package manager. It also includes GitHub Actions, although GitHub Actions workflow definitions are not shown here. Before changing versions, the relevant checks are dependency locking, a complete image build, database migration, static asset generation, and the health check pages.
Where the example is the wrong deployment choice
The largest limitation is its identity as an example. It does not model authentication, authorization, tenant isolation, billing, audit history, or a substantive Django domain. Adopting the repository does not solve those product requirements. The `pages` and `up` apps make the starter functional, but they also leave application security and business behavior largely to the adopter.
It also assumes a host that can run Docker Compose and provides Docker Desktop guidance for Windows. A deployment platform that supports only a single application container and does not provide local PostgreSQL, Redis, or persistent volumes would require a different operating model. The README mentions managed cloud services as a reason to omit local PostgreSQL and Redis, but it does not document TLS termination, secret injection, database provisioning, or external service connectivity.
A direct deployment is the clearest alternative. Instead of packaging Django, services, and commands into Compose, an operator can install the dependencies from `pyproject.toml`, run migrations against an installed database, and launch Gunicorn directly. The trade-off is operational separation. Direct deployment avoids the Compose topology and its image build layer, but it makes Python, PostgreSQL, Redis, process startup, and asset delivery separate environment concerns.
This repository is also a poor fit for teams that want a finished Django CMS, REST API, single-page application starter, or opinionated JavaScript stack. It intentionally leaves the frontend framework undecided. Teams choosing React or Vue would need to add that architecture themselves, while teams satisfied with Django templates and esbuild can use the included structure with little frontend scaffolding.
MIT licensing and the boundary before production adoption
The repository is licensed under the MIT License. The repository includes a `LICENSE` file. The practical point for engineers is that the project can be used as a basis for an application, while preserving the applicable copyright and license notice. That is a repository licensing fact, not a conclusion about security, suitability, or fitness for a particular deployment.
Production adoption requires more than replacing the package name. The visible defaults include development-oriented values such as `DEBUG=true` and an insecure secret. The example environment also starts PostgreSQL, Redis, assets, web, and worker profiles for development. A production environment can select different profiles, including managed services, but the repository does not provide a complete production environment specification in the visible files.
The project-specific checks are therefore clear. Confirm the Compose version, replace `SECRET_KEY`, set `DEBUG=false`, choose `NODE_ENV=production`, decide whether PostgreSQL and Redis run locally, and inspect persistent volume handling. Then verify migration behavior, collected static files, Celery worker startup, and the `up` health check pages. These steps are tied directly to files and behavior in the repository rather than to a generic production checklist.
Editorial conclusion
Adopt this repository as a reference or application skeleton if the team wants Django inside Docker Compose and is prepared to replace the sample identity, settings, assets, and infrastructure defaults. Do not adopt it as a finished product or as a substitute for an organization-specific deployment and security review. Verify first that Docker Compose v2 2.20.2 or newer is available, then review `.env`, `compose.yaml`, `pyproject.toml`, and the image tags before using the project outside local development.
Frequently asked questions
What does nickjj/docker-django-example include?
It includes a Django application with PostgreSQL, Redis, Celery, Gunicorn, WhiteNoise, esbuild, TailwindCSS, and Ruff. The repository also provides Docker Compose services, environment configuration, health check pages, and scripts for common project operations.
What version of Docker Compose does nickjj/docker-django-example require?
The README requires Docker Compose v2 2.20.2 or newer because the Compose configuration uses specific features added in that release line. Docker must also be installed.
How do I start nickjj/docker-django-example for the first time?
Clone the repository, copy `.env.example` to `.env`, run `docker compose up --build`, and execute `./run manage migrate` from another terminal. The sample is then available at `http://localhost:8000` according to the README.
Can nickjj/docker-django-example use managed PostgreSQL and Redis services?
The `.env.example` says that PostgreSQL and Redis do not need to run in production when managed cloud services are used. The Compose `depends_on` configuration marks these dependencies as optional, although the visible documentation does not provide a complete external-service setup.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/nickjj-docker-django-example)Was this useful?