{"id":13468708,"url":"https://github.com/nickjj/docker-django-example","last_synced_at":"2025-05-14T16:04:46.087Z","repository":{"id":41413466,"uuid":"342038855","full_name":"nickjj/docker-django-example","owner":"nickjj","description":"A production ready example Django app that's using Docker and Docker Compose.","archived":false,"fork":false,"pushed_at":"2025-04-03T10:37:55.000Z","size":1191,"stargazers_count":1276,"open_issues_count":4,"forks_count":356,"subscribers_count":25,"default_branch":"main","last_synced_at":"2025-04-13T01:54:43.565Z","etag":null,"topics":["celery","django","docker","docker-compose","esbuild","postgres","redis","tailwindcss"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nickjj.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"nickjj","custom":["https://www.paypal.me/nickjanetakis"]}},"created_at":"2021-02-24T21:20:34.000Z","updated_at":"2025-04-07T15:05:16.000Z","dependencies_parsed_at":"2023-02-09T21:00:49.176Z","dependency_job_id":"1fd2ec9b-62b2-4b9c-b754-dd9c4041b7a4","html_url":"https://github.com/nickjj/docker-django-example","commit_stats":{"total_commits":309,"total_committers":4,"mean_commits":77.25,"dds":0.009708737864077666,"last_synced_commit":"de8ff6fc6f4c48ac1028b45b0174db93c92766ce"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickjj%2Fdocker-django-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickjj%2Fdocker-django-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickjj%2Fdocker-django-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nickjj%2Fdocker-django-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nickjj","download_url":"https://codeload.github.com/nickjj/docker-django-example/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654051,"owners_count":21140235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["celery","django","docker","docker-compose","esbuild","postgres","redis","tailwindcss"],"created_at":"2024-07-31T15:01:17.187Z","updated_at":"2025-05-14T16:04:46.079Z","avatar_url":"https://github.com/nickjj.png","language":"Python","readme":"# 🐳 An example Django + Docker app\n\nYou could use this example app as a base for your new project or as a guide to\nDockerize your existing Django app.\n\nThe example app is minimal but it wires up a number of things you might use in\na real world Django app, but at the same time it's not loaded up with a million\npersonal opinions.\n\nFor the Docker bits, everything included is an accumulation of [Docker best\npractices](https://nickjanetakis.com/blog/best-practices-around-production-ready-web-apps-with-docker-compose)\nbased on building and deploying dozens of assorted Dockerized web apps since\nlate 2014.\n\n**This app is using Django 5.2.1 and Python 3.13.3**. The screenshot shows\n`X.X.X` since they get updated regularly:\n\n[![Screenshot](.github/docs/screenshot.jpg)](https://github.com/nickjj/docker-django-example/blob/main/.github/docs/screenshot.jpg?raw=true)\n\n## 🧾 Table of contents\n\n- [Tech stack](#tech-stack)\n- [Notable opinions and extensions](#notable-opinions-and-extensions)\n- [Running this app](#running-this-app)\n- [Files of interest](#files-of-interest)\n  - [`.env`](#env)\n  - [`run`](#run)\n- [Running a script to automate renaming the project](#running-a-script-to-automate-renaming-the-project)\n- [Updating dependencies](#updating-dependencies)\n- [See a way to improve something?](#see-a-way-to-improve-something)\n- [Additional resources](#additional-resources)\n  - [Learn more about Docker and Django](#learn-more-about-docker-and-django)\n  - [Deploy to production](#deploy-to-production)\n- [About the author](#about-the-author)\n\n## 🧬 Tech stack\n\nIf you don't like some of these choices that's no problem, you can swap them\nout for something else on your own.\n\n### Back-end\n\n- [PostgreSQL](https://www.postgresql.org/)\n- [Redis](https://redis.io/)\n- [Celery](https://github.com/celery/celery)\n\n### Front-end\n\n- [esbuild](https://esbuild.github.io/)\n- [TailwindCSS](https://tailwindcss.com/)\n- [Heroicons](https://heroicons.com/)\n\n#### But what about JavaScript?!\n\nPicking a JS library is a very app specific decision because it depends on\nwhich library you like and it also depends on if your app is going to be\nmostly Django templates with sprinkles of JS or an API back-end.\n\nThis isn't an exhaustive list but here's a few reasonable choices depending on\nhow you're building your app:\n\n- \u003chttps://hotwired.dev/\u003e\n- \u003chttps://htmx.org/\u003e\n- \u003chttps://github.com/alpinejs/alpine\u003e\n- \u003chttps://vuejs.org/\u003e\n- \u003chttps://reactjs.org/\u003e\n- \u003chttps://jquery.com/\u003e\n\nOn the bright side with esbuild being set up you can use any (or none) of these\nsolutions very easily. You could follow a specific library's installation\nguides to get up and running in no time.\n\nPersonally I'm going to be using Hotwire Turbo + Stimulus in most newer\nprojects.\n\n## 🍣 Notable opinions and extensions\n\nDjango is an opinionated framework and I've added a few extra opinions based on\nhaving Dockerized and deployed a number of Django projects. Here's a few (but\nnot all) note worthy additions and changes.\n\n- **Packages and extensions**:\n    - *[gunicorn](https://gunicorn.org/)* for an app server in both development and production\n    - *[whitenoise](https://github.com/evansd/whitenoise)* for serving static files\n    - *[django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar)* for displaying info about a request\n- **Linting and formatting**:\n    - *[ruff](https://github.com/astral-sh/ruff)* is used to lint and format the code base\n- **Django apps**:\n    - Add `pages` app to render a home page\n    - Add `up` app to provide a few health check pages\n- **Config**:\n    - Log to STDOUT so that Docker can consume and deal with log output\n    - Extract a bunch of configuration settings into environment variables\n    - Rename project directory from its custom name to `config/`\n    - `src/config/settings.py` and the `.env` file handles configuration in all environments\n- **Front-end assets**:\n    - `assets/` contains all your CSS, JS, images, fonts, etc. and is managed by esbuild\n    - Custom `502.html` and `maintenance.html` pages\n    - Generate favicons using modern best practices\n- **Django defaults that are changed**:\n    - Use Redis as the default Cache back-end\n    - Use signed cookies as the session back-end\n    - `public/` is the static directory where Django will serve static files from\n    - `public_collected/` is where `collectstatic` will write its files to\n\nBesides the Django app itself:\n\n- [uv](https://github.com/astral-sh/uv) is used for package management instead of `pip3` (builds on my machine are ~10x faster!)\n- Docker support has been added which would be any files having `*docker*` in\n  its name\n- GitHub Actions have been set up\n\n## 🚀 Running this app\n\nYou'll need to have [Docker installed](https://docs.docker.com/get-docker/).\nIt's available on Windows, macOS and most distros of Linux. If you're new to\nDocker and want to learn it in detail check out the [additional resources\nlinks](#learn-more-about-docker-and-django) near the bottom of this README.\n\nYou'll also need to enable Docker Compose v2 support if you're using Docker\nDesktop. On native Linux without Docker Desktop you can [install it as a plugin\nto Docker](https://docs.docker.com/compose/install/linux/). It's been generally\navailable for a while now and is stable. This project uses specific [Docker\nCompose v2\nfeatures](https://nickjanetakis.com/blog/optional-depends-on-with-docker-compose-v2-20-2)\nthat only work with Docker Compose v2 2.20.2+.\n\nIf you're using Windows, it will be expected that you're following along inside\nof [WSL or WSL\n2](https://nickjanetakis.com/blog/a-linux-dev-environment-on-windows-with-wsl-2-docker-desktop-and-more).\nThat's because we're going to be running shell commands. You can always modify\nthese commands for PowerShell if you want.\n\n#### Clone this repo anywhere you want and move into the directory:\n\n```sh\ngit clone https://github.com/nickjj/docker-django-example hellodjango\ncd hellodjango\n\n# Optionally checkout a specific tag, such as: git checkout 0.11.0\n```\n\n#### Copy an example .env file because the real one is git ignored:\n\n```sh\ncp .env.example .env\n```\n\n#### Build everything:\n\n*The first time you run this it's going to take 5-10 minutes depending on your\ninternet connection speed and computer's hardware specs. That's because it's\ngoing to download a few Docker images and build the Python + Yarn dependencies.*\n\n```sh\ndocker compose up --build\n```\n\nNow that everything is built and running we can treat it like any other Django\napp.\n\nDid you receive a `depends_on` \"Additional property required is not allowed\"\nerror? Please update to at least Docker Compose v2.20.2+ or Docker Desktop\n4.22.0+.\n\nDid you receive an error about a port being in use? Chances are it's because\nsomething on your machine is already running on port 8000. Check out the docs\nin the `.env` file for the `DOCKER_WEB_PORT_FORWARD` variable to fix this.\n\nDid you receive a permission denied error? Chances are you're running native\nLinux and your `uid:gid` aren't `1000:1000` (you can verify this by running\n`id`). Check out the docs in the `.env` file to customize the `UID` and `GID`\nvariables to fix this.\n\n#### Setup the initial database:\n\n```sh\n# You can run this from a 2nd terminal.\n./run manage migrate\n```\n\n*We'll go over that `./run` script in a bit!*\n\n#### Check it out in a browser:\n\nVisit \u003chttp://localhost:8000\u003e in your favorite browser.\n\n#### Linting the code base:\n\n```sh\n# You should get no output (that means everything is operational).\n./run lint\n```\n\n#### Formatting the code base:\n\n```sh\n# You should see that everything is unchanged (it's all already formatted).\n./run format\n```\n\n*There's also a `./run quality` command to run the above commands together.*\n\n#### Running the test suite:\n\n```sh\n# You should see all passing tests. Warnings are typically ok.\n./run manage test\n```\n\n#### Stopping everything:\n\n```sh\n# Stop the containers and remove a few Docker related resources associated to this project.\ndocker compose down\n```\n\nYou can start things up again with `docker compose up` and unlike the first\ntime it should only take seconds.\n\n## 🔍 Files of interest\n\nI recommend checking out most files and searching the code base for `TODO:`,\nbut please review the `.env` and `run` files before diving into the rest of the\ncode and customizing it. Also, you should hold off on changing anything until\nwe cover how to customize this example app's name with an automated script\n(coming up next in the docs).\n\n### `.env`\n\nThis file is ignored from version control so it will never be commit. There's a\nnumber of environment variables defined here that control certain options and\nbehavior of the application. Everything is documented there.\n\nFeel free to add new variables as needed. This is where you should put all of\nyour secrets as well as configuration that might change depending on your\nenvironment (specific dev boxes, CI, production, etc.).\n\n### `run`\n\nYou can run `./run` to get a list of commands and each command has\ndocumentation in the `run` file itself.\n\nIt's a shell script that has a number of functions defined to help you interact\nwith this project. It's basically a `Makefile` except with [less\nlimitations](https://nickjanetakis.com/blog/replacing-make-with-a-shell-script-for-running-your-projects-tasks).\nFor example as a shell script it allows us to pass any arguments to another\nprogram.\n\nThis comes in handy to run various Docker commands because sometimes these\ncommands can be a bit long to type. Feel free to add as many convenience\nfunctions as you want. This file's purpose is to make your experience better!\n\n*If you get tired of typing `./run` you can always create a shell alias with\n`alias run=./run` in your `~/.bash_aliases` or equivalent file. Then you'll be\nable to run `run` instead of `./run`.*\n\n## ✨ Running a script to automate renaming the project\n\nThe app is named `hello` right now but chances are your app will be a different\nname. Since the app is already created we'll need to do a find / replace on a\nfew variants of the string \"hello\" and update a few Docker related resources.\n\nAnd by we I mean I created a zero dependency shell script that does all of the\nheavy lifting for you. All you have to do is run the script below.\n\n#### Run the rename-project script included in this repo:\n\n```sh\n# The script takes 2 arguments.\n#\n# The first one is the lower case version of your app's name, such as myapp or\n# my_app depending on your preference.\n#\n# The second one is used for your app's module name. For example if you used\n# myapp or my_app for the first argument you would want to use MyApp here.\nbin/rename-project myapp MyApp\n```\n\nThe [bin/rename-project\nscript](https://github.com/nickjj/docker-django-example/blob/main/bin/rename-project)\nis going to:\n\n- Remove any Docker resources for your current project\n- Perform a number of find / replace actions\n- Optionally initialize a new git repo for you\n\n*Afterwards you can delete this script because its only purpose is to assist in\nhelping you change this project's name without depending on any complicated\nproject generator tools or 3rd party dependencies.*\n\nIf you're not comfy running the script or it doesn't work for whatever reasons\nyou can [check it\nout](https://github.com/nickjj/docker-django-example/blob/main/bin/rename-project)\nand perform the actions manually. It's mostly running a find / replace across\nfiles and then renaming a few directories and files.\n\n#### Start and setup the project:\n\nThis won't take as long as before because Docker can re-use most things. We'll\nalso need to setup our database since a new one will be created for us by\nDocker.\n\n```sh\ndocker compose up --build\n\n# Then in a 2nd terminal once it's up and ready.\n./run manage migrate\n```\n\n#### Sanity check to make sure the tests still pass:\n\nIt's always a good idea to make sure things are in a working state before\nadding custom changes.\n\n```sh\n# You can run this from the same terminal as before.\n./run quality\n./run manage test\n```\n\nIf everything passes now you can optionally `git add -A \u0026\u0026 git commit -m\n\"Initial commit\"` and start customizing your app. Alternatively you can wait\nuntil you develop more of your app before committing anything. It's up to you!\n\n#### Tying up a few loose ends:\n\nYou'll probably want to create a fresh `CHANGELOG.md` file for your project. I\nlike following the style guide at \u003chttps://keepachangelog.com/\u003e but feel free\nto use whichever style you prefer.\n\nSince this project is MIT licensed you should keep my name and email address in\nthe `LICENSE` file to adhere to that license's agreement, but you can also add\nyour name and email on a new line.\n\nIf you happen to base your app off this example app or write about any of the\ncode in this project it would be rad if you could credit this repo by linking\nto it. If you want to reference me directly please link to my site at\n\u003chttps://nickjanetakis.com\u003e. You don't have to do this, but it would be very\nmuch appreciated!\n\n## 🛠 Updating dependencies\n\nYou can run `./run uv:outdated` or `./run yarn:outdated` to get a list of\noutdated dependencies based on what you currently have installed. Once you've\nfigured out what you want to update, go make those updates in your\n`pyproject.toml` and / or `package.json` file.\n\nOr, let's say you've customized your app and it's time to add a new dependency,\neither for Python or Node.\n\n#### In development:\n\n##### Option 1\n\n1. Directly edit `pyproject.toml` or `assets/package.json` to add your package\n2. `./run deps:install` or `./run deps:install --no-build`\n    - The `--no-build` option will only write out a new lock file without re-building your image\n\n##### Option 2\n\n1. Run `./run uv add mypackage --no-sync` or `run yarn add mypackage --no-lockfile` which will update your `pyproject.toml` or `assets/package.json` with the latest version of that package but not install it\n2. The same step as step 2 from option 1\n\nEither option is fine, it's up to you based on what's more convenient at the\ntime. You can modify the above workflows for updating an existing package or\nremoving one as well.\n\nYou can also access `uv` and `yarn` in Docker with `./run uv` and `./run yarn`\nafter you've upped the project.\n\n#### In CI:\n\nYou'll want to run `docker compose build` since it will use any existing lock\nfiles if they exist. You can also check out the complete CI test pipeline in\nthe [run](https://github.com/nickjj/docker-django-example/blob/main/run) file\nunder the `ci:test` function.\n\n#### In production:\n\nThis is usually a non-issue since you'll be pulling down pre-built images from\na Docker registry but if you decide to build your Docker images directly on\nyour server you could run `docker compose build` as part of your deploy\npipeline which is similar to how it would work in CI.\n\n## 🤝 See a way to improve something?\n\nIf you see anything that could be improved please open an issue or start a PR.\nAny help is much appreciated!\n\n## 🌎 Additional resources\n\nNow that you have your app ready to go, it's time to build something cool! If\nyou want to learn more about Docker, Django and deploying a Django app here's a\ncouple of free and paid resources. There's Google too!\n\n### Learn more about Docker and Django\n\n#### Official documentation\n\n- \u003chttps://docs.docker.com/\u003e\n- \u003chttps://docs.djangoproject.com/en/5.2/\u003e\n\n#### Courses / books\n\n- [https://diveintodocker.com](https://diveintodocker.com?ref=docker-django-example)\n  is a course I created which goes over the Docker and Docker Compose\n  fundamentals\n- William Vincent has a bunch of [beginner and advanced Django\n  books](https://gumroad.com/a/139727987). He also co-hosts the [Django\n  Chat](https://djangochat.com/) podcast\n\n### Deploy to production\n\nI'm creating an in-depth course related to deploying Dockerized web apps. If\nyou want to get notified when it launches with a discount and potentially get\nfree videos while the course is being developed then [sign up here to get\nnotified](https://nickjanetakis.com/courses/deploy-to-production).\n\n## 👀 About the author\n\n- Nick Janetakis | \u003chttps://nickjanetakis.com\u003e | [@nickjanetakis](https://twitter.com/nickjanetakis)\n\nI'm a self taught developer and have been freelancing for the last ~20 years.\nYou can read about everything I've learned along the way on my site at\n[https://nickjanetakis.com](https://nickjanetakis.com/).\n\nThere's hundreds of [blog posts](https://nickjanetakis.com/) and a couple\nof [video courses](https://nickjanetakis.com/courses) on web development and\ndeployment topics. I also have a [podcast](https://runninginproduction.com)\nwhere I talk with folks about running web apps in production.\n","funding_links":["https://github.com/sponsors/nickjj","https://www.paypal.me/nickjanetakis"],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickjj%2Fdocker-django-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnickjj%2Fdocker-django-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnickjj%2Fdocker-django-example/lists"}