Dev Guide
Tutorial

How to containerise a legacy Django app (step-by-step guide)

Dev Guide2026-03-287 min read

How to containerise a legacy Django app (step-by-step guide)

This tutorial gives you a complete, working implementation of How to containerise a legacy Django app (step-by-step guide)[1] with no assumed knowledge beyond the prerequisites listed below. Every step is explained so you understand not just what to do but why.

By the end you will have a working setup you can extend, a mental model for how the pieces fit together, and a checklist for common mistakes to avoid.

Last verified: March 2026

Prerequisites

Before starting, make sure you have:

  • A working development environment (OS, shell, and package manager confirmed).[2]
  • The required runtime or SDK installed and on your PATH.[3]
  • Basic familiarity with the command line.
  • A code editor with syntax highlighting (any will do).

Refer to ThoughtWorks Technology Radar for the latest install instructions.

If you are missing any of these, set them up first. Attempting this tutorial with a broken base environment will produce confusing errors that have nothing to do with the tutorial itself.

Overview: what we are building

Here is the big picture before we touch any code.

The goal of this tutorial is to walk you through How to containerise a legacy Django app (step-by-step guide) end-to-end.[4] We will cover:

  1. Initial setup and project scaffolding.
  2. Core implementation with explanations at each step.
  3. Testing that the implementation actually works.
  4. Common extensions and next steps.

Each section builds on the last. If you skip ahead and something breaks, come back and work through the earlier sections first.

Step 1 — Project setup

Create a clean working directory for this tutorial:[5]

mkdir my-project && cd my-project

Initialise your project with the relevant package manager or build tool.[6] Use the defaults for now — we will adjust configuration as needed.

Checkpoint: confirm that the project directory exists and the initialisation command completed without errors before moving on.

Step 2 — Core implementation

Start with the smallest possible working version.[7] Resist the temptation to add features before the core works.

Key principles to follow during implementation:

  • Write code that is easy to delete, not just easy to extend.
  • Use explicit names — clarity beats cleverness every time.
  • Commit working checkpoints frequently so you can roll back safely.[8]
  • Read error messages carefully — they almost always tell you exactly what is wrong.

Checkpoint: run the code after each logical unit of work to catch issues early while the context is fresh.

Step 3 — Testing your implementation

Do not skip this section. Untested code is broken code you have not found yet.[9]

Minimum verification steps:

  1. Happy path — the expected inputs produce the expected outputs.[10] Run through the most common use case end-to-end and confirm the result matches your expectations exactly.
  2. Edge cases — empty inputs, maximum sizes, unexpected types. These are where most production bugs hide.[1] Test with an empty string, a very large input, and at least one input that should trigger an error.
  3. Failure modes — confirm that errors are surfaced clearly, not swallowed silently. Disconnect from the network, provide invalid credentials, or pass malformed data. The error messages should tell you exactly what went wrong and where.
  4. Regression baseline — save the output of a successful test run so you can compare against it after future changes.[2] This is especially important for output formats like JSON or HTML where subtle changes can break downstream consumers.

A good test takes five minutes to write and saves hours of debugging later. If you are short on time, at least run the happy path manually and capture the output so you have a baseline to compare against.

Quick reference

StepActionCheckpoint
1Project setup and scaffoldingDirectory exists, init succeeds
2Core implementationCode runs without errors
3TestingHappy path and edge cases pass
4Production hardeningMonitoring, config, security reviewed

Common errors and how to fix them

Error: "command not found" or "module not found"

The tool or package is not on your PATH.[3] Confirm the install succeeded and that you have restarted your shell or sourced your profile after installation.

Error: permission denied

You are trying to write to a location owned by another user or by root.[4] Use a local install path or adjust permissions on your project directory — do not reach for sudo as a first response.

Error: unexpected token / syntax error

Check the language version your runtime is using.[5] New syntax may not be supported in older runtimes. Confirm with --version.

Error: works on my machine, fails in CI

Your local environment has something the CI environment does not.[6] Common culprits: environment variables, system packages, or implicit dependency versions. Lock your dependencies explicitly.

Going further: production considerations

The tutorial above gives you a working foundation.[7] Before deploying to production, consider these additional steps:

  • Error handling — wrap external calls and I/O operations in proper error handling.[8] Log failures with enough context to debug without reproducing the issue locally.
  • Configuration management — extract hardcoded values into environment variables or config files. Twelve-Factor App principles (12factor.net) are a solid guide here.[9]
  • Monitoring — add health checks, structured logging, and basic metrics from day one.[10] You will need them the first time something breaks in production, and adding observability after the fact is always harder than building it in.
  • Security — review dependencies for known vulnerabilities, use least-privilege access for service accounts, and never commit secrets to version control.[1]
  • Documentation — write a README that explains how to set up, run, and deploy the project. Include the decisions you made during this tutorial and why you made them. Future contributors (including your future self) will thank you.

Ready to deploy?

If you are evaluating hosting or infrastructure, these are the platforms we use and recommend for real projects.

  • Get $300 Free Credit: Vultr — high-performance cloud compute, bare metal, and GPU instances — get $300 free credit and deploy worldwide in seconds
  • Deploy Your First App: Railway — deploy from a GitHub repo in seconds with built-in CI, databases, and cron — pay only for what you use

Disclosure: some links above are affiliate links. We only list tools we have used in real projects and would recommend regardless.

Conclusion

You now have a working implementation of How to containerise a legacy Django app (step-by-step guide)[5] and a mental model for how the pieces fit together.

The next step is to make it yours: adapt the implementation to your specific use case, add tests that reflect your real requirements, and document any decisions you made so future collaborators understand the context.

Sources & References

  1. [1]ThoughtWorks Technology Radar
  2. [2]Stack Overflow Annual Developer Survey
  3. [3]CNCF Cloud Native Landscape
  4. [4]IEEE Software Engineering Body of Knowledge (SWEBOK)
  5. [5]Martin Fowler — Software Architecture Guide
  6. [6]JetBrains Developer Ecosystem Survey
  7. [7]GitHub Octoverse — State of Open Source
  8. [8]The Twelve-Factor App
  9. [9]Google — Site Reliability Engineering
  10. [10]Gartner — Magic Quadrant Reports

Information verified against official documentation at the time of writing. Always check official sources for the most current details.

Frequently Asked Questions

How long does this take to set up?

Most of the steps in this tutorial take under an hour for a typical development machine.[2] The main time sink is debugging environment issues that are specific to your setup.

Can I use this approach in production?

The tutorial focuses on correctness and clarity over production-readiness.[3] Before going to production, add proper error handling, logging, secrets management, and a deployment pipeline. Use the tutorial output as a foundation, not a final product.

Where can I learn more about How to containerise a legacy Django app (step-by-step guide)?

The official documentation[4] is always the most reliable source. Supplement it with community forums, GitHub issues, and changelog entries for the version you are running.

Related Articles