Hit the ground running! From zero to production-ready Docker image in just 2-3 hours

Packaging your Python application for production is very different than using Docker in a development environment:

  • Run your image as root, or miss the security implications of build caching, and you’ll deploy insecure images that put customer data at risk.
  • With image builds happening in CI, slow builds become a bottleneck for all of your team’s work.
  • 2GB images may be fine on your laptop, but you don’t want deployments to involve massive downloads.

Docker is not some magic pill that will allow you to package your application for production with no work: you will need to implement a whole new set of best practices. Implementing Docker packaging the right way can take multiple days of development and debugging.

There are no elegant abstractions when it comes to packaging—it’s just detail after detail after detail that you need to get right. Wouldn’t it better if your team could free up all those days to implement features that directly impact your customers?

(Ready to buy the template? Skip ahead.)

Save time—a lot of time

You want to serve your customers, helping them achieve their goals.

So you want your team to have the time—and infrastructure—to focus on deploying new features faster. And when you deploy a new image, you want the confidence that you’re following operational best practices, confidence that it’s built right, confidence that it’s secure.

To help you get there, and get there fast, I’ve created a best-practices template for Docker packaging of your Python application: small, secure, and fast.

Watch me Dockerize a Python application in just 3 minutes

How much time can you save Dockerizing your applications with this template?

The first time you go through the onboarding tutorial, I would expect a simple WSGI application to take as little as 30 minutes, and I’ve seen a new user get a complex application going in just 2-3 hours.

Of course, if you have multiple images to package, the later images will go even faster. For an admittedly simple case, a WSGI app with no special system packages, I was able to package a Python application in just 3 minutes.

And at the end of the video you’ll also notice that later builds take full advantage of Docker’s caching, running much faster. Not only will your team gain more time from fast setup and fast builds, you’ll also be deploying best-practices images: small and secure.




Ready to get started?

  • Configured for production use: small images, secure defaults.
  • Fast setup and fast builds, saving you days of ops and developer time.
  • Extensively tested with the latest version of Docker CE (19.03).
  • Use for an unlimited number of images in your company’s private repositories.
One time purchase Annual subscription
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 6 months of bugfix updates.
  • 100% money-back guarantee.
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 12 months of feature and bugfix updates.
  • Automatically renews so you keep getting updates.
  • 100% money-back guarantee.
One time purchase Annual subscription

What best practices does the template implement?

  • Specifically designed for Python applications, with automatic support for most Python packaging setups (requirements.txt, setup.py, pipenv, poetry, and flit).
  • Installs dependencies separately from application code when possible, for faster builds.
  • Pre-configured with fast multi-stage builds, to help you build smaller images.
  • Secure by default, running your code as a non-root user, shipping the minimal files needed, and setting up best practices like automatic image rebuilds.
  • Implements and documents the processes you need to keep dependencies up-to-date.
  • Pre-configured for CircleCI and GitLab CI, so you can get started even faster.
  • Encourages and documents best practices like smoke tests and health checks.
  • Heavily documented and annotated with references so you can learn more about why and how it’s implemented.

How do you use the template?

The template comes with files you copy and then check in to your repository: a Dockerfile, build scripts, and configuration files. In order to make things as simple and easy as possible, and get you started quickly, the template comes with highly detailed step-by-step tutorial, covering three steps:

  1. Building the image.
  2. CI/CD integration.
  3. Advanced configuration.

Because the template works out-of-the-box for the common use case of WSGI applications, including Flask and Django, in many cases you’ll only be editing one particular configuration file, implemented in Python to give you maximal flexibility:




Why a template?

The problem with packaging is that it’s a messy, nitpicky process that’s all about the details. Tools try to build abstractions, and abstractions don’t work when the use cases vary sufficiently.

As a result packaging tools often end up with one of two failure modes:

  1. Either the tool can’t support a whole bunch of totally reasonable use cases.
  2. Or the tool is so general purpose it’s hard to use right;a tool like docker build and Dockerfiles, for example.

A template, in contrast, can be built to do the right thing for 90% of the time—and in the remaining 10% you can still make it work. Because all the code in a template is designed to be customized, you can still handle the remaining edge cases yourself.

Ready to build production-ready containers?

  • Configured for production use: small images, secure defaults.
  • Fast setup and fast builds, saving you days of ops and developer time.
  • Extensively tested with the latest version of Docker CE (19.03).
  • Use for an unlimited number of images in your company’s private repositories.
One time purchase Annual subscription
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 6 months of bugfix updates.
  • 100% money-back guarantee.
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 12 months of feature and bugfix updates.
  • Automatically renews so you keep getting updates.
  • 100% money-back guarantee.
One time purchase Annual subscription

Is implementing Docker packaging best practices really that tricky?

Unfortunately, while the information you need is out there on the Internet, actually discovering and implementing best practices is slow, tricky work.

You’ll need to filter out the ignorant, broken, and confused advice from people who don’t really know what they’re doing. Do a quick search on Google or DuckDuckGo, and you’ll find Dockerfiles that:

  • Result in super-slow rebuilds, since the author didn’t understand the Docker image caching model.
  • Recommend using Alpine as a base image. Alpine uses the alternative musl libc, which among other problems has a small default thread stack size that can cause Python to crash—see issue 32307 in the Python bug tracker.
  • Have you run your container as root, even though that’s insecure.

And that’s just a subset of the bad advice you’ll encounter.

You’ll also need to filter out all the obsolete and out-of-date advice. Docker has gone through many changes, and 3-year-old best practices may no longer be relevant. For example, the multi-stage build support added in Docker 17.05 obsoletes much of the previous advice on creating small images.

You’ll need to find the various places—obscure blog posts, half-baked documentation, slides from conference talks—where actual best practices are covered. There is no one place that covers everything you need to know.

If you go elsewhere on this site you’ll find many articles I wrote to help you get started—but there’s still all the work of integrating and debugging the result. So why not just take advantage of my work and get going immediately?

Up-to-date and extensively tested

Most build scripts are hacked-together shell scripts: “it worked once, let’s ship it!” But you need to trust the software that’s deploying and building your images for production use; a hacky shell script isn’t good enough.

The Production-Ready Python Containers template is tested with up-to-date versions of Docker CE (most recently 19.03) and Python. In particular, it has an extensive automated test suite to ensure all its features work correctly, as well as automated builds on CircleCI and Gitlab CI to ensure the integration works.

Here’s a recent run of the end-to-end tests:

test_image_builds_smoke_test_runs[python:3.7-slim-buster] PASSED
test_image_builds_smoke_test_runs[python:3.6-slim-buster] PASSED
test_image_builds_smoke_test_runs[python:3.8-slim-buster] PASSED
test_no_requirements_txt PASSED
test_run_in_place_with_setup_py PASSED
test_run_in_place_without_setup_py PASSED
test_pipenv PASSED
test_pyproject_toml PASSED
test_poetry PASSED
test_poetry_in_place PASSED
test_ubuntu_1804 PASSED
test_centos_8 PASSED
test_rhel_8 PASSED
test_image_metadata PASSED
test_custom_run_tags PASSED
test_environment_vars PASSED
test_no_cache PASSED
test_env_variable_change_invalidates_cache PASSED
test_dry_run PASSED
test_total_caching PASSED
test_source_code_changed_caching PASSED
test_alternative_command_line PASSED
test_custom_dependency_install PASSED
test_custom_application_build PASSED
test_custom_application_install PASSED
test_image_size_enforcement PASSED
================ 26 passed in 1614.98 seconds ===================

Ready to build production-ready containers?

  • Configured for production use: small images, secure defaults.
  • Fast setup and fast builds, saving you days of ops and developer time.
  • Extensively tested with the latest version of Docker CE (19.03).
  • Use for an unlimited number of images in your company’s private repositories.
One time purchase Annual subscription
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 6 months of bugfix updates.
  • 100% money-back guarantee.
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 12 months of feature and bugfix updates.
  • Automatically renews so you keep getting updates.
  • 100% money-back guarantee.
One time purchase Annual subscription

Is this template for you?

Designed for production, not development environments

Some developers use Docker for development environments, or to run data science batch jobs locally, or other local use cases. This template is designed for running services on production servers.

Prerequisite knowledge

In order to use this template successfully, developers are expected to understand:

  • Basic Docker usage, including docker run/build/ps/... commands and the Dockerfile format.
  • Python packaging, e.g. specifying dependencies in a requirements.txt file.
  • Linux command-line usage.
  • The details of your CI system.

Won’t magically solve all your operational problems

This template is far better than what most developers can do on their own without a significant and costly time investment.

However, Docker packaging is just one part of your operational and deployment infrastructure, and it can’t fix problems in your code. So even if you use this template you might still have security breaches, crashes, or other problems.

Some industries I prefer not to do business with

If your team will be using the template for software for military use, prisons, oil & gas extraction, surveillance, national security, or the like:

  1. Please don’t buy this template.
  2. I encourage you to find a different job, and then buy the template for your new job if it’s relevant there.

Not for hobbyists

If you’re just working on a personal project, I wouldn’t suggest paying for this template. This template is for organizations running software in production, where downtime and slowness cost real money.

Want to build production-ready containers?

  • Configured for production use: small images, secure defaults.
  • Fast setup and fast builds, saving you days of ops and developer time.
  • Extensively tested with the latest version of Docker CE (19.03).
  • Use for an unlimited number of images in your company’s private repositories.
One time purchase Annual subscription
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 6 months of bugfix updates.
  • 100% money-back guarantee.
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 12 months of feature and bugfix updates.
  • Automatically renews so you keep getting updates.
  • 100% money-back guarantee.
One time purchase Annual subscription

Licensing terms

You can use the template for an unlimited number of images, forever. What you can’t do is redistribute the template itself.

That means:

  1. You won’t be able to distribute images based on the template outside your organization, if they include the template’s code.
  2. You won’t be able to distribute the template as part of the source code of your project, if you send source code to customers.
  3. You won’t be able use it to package an open source project.

If you have questions, or would like a custom licensing agreement to address these limitations, get in touch at sales@pythonspeed.com.

You can read the specific license terms here.

Changelog

1.0.7 (January 2020)

  • Fix for self-hosted GitLab CI runners when used with Docker 19.03.
  • Fix for intermittent problem where the secrets image failed to delete, causing image builds to spuriously fail.

1.0.6 (December 2019)

  • Added support for CentOS 8 and RHEL 8; previously only Debian and Ubuntu were supported.

1.0.5 (November 2019)

This release focused on making it easier to get started with the template:

  • Reorganized the documentation structure so it’s clearer you can get started with less work.
  • The smoke test is now disabled by default.
  • The entry point gives a much nicer error message if gunicorn is missing.

1.0.4 (September 2019)

  • Increased the default max image size from 200MB to 250MB, since 200MB was too low.
  • Documented Docker Compose usage.

1.0.3 (July 2019)

  • The newly released Docker CE 19.03 is now tested and supported.
  • With the release of Debian “Buster” 10, switched to python:3.7-slim-buster as the default image from an image based on Debian “Stretch” 9.

Detailed feature list and supported tools

Easy to use

  • Designed to work out of the box for many common situations with just changes to the config file.
  • Powerful and customizable enough to support more complex use cases.
  • Re-usable so you can apply best practices to all your Python applications.
  • Includes diagnostic and debugging tools, and explanations on how to test and debug your image when you’re first applying the template.

Build images fast

  • Step-by-step builds allow caching, so changes to your code don’t require re-installing all dependencies.
  • Enables caching even though it uses multi-stage builds.

Good operational setup

  • Correct signal handling to ensure fast shutdown of your application.
  • Ensures your application shows Python tracebacks on segfaults, for easier debugging.
  • Pre-configured gunicorn for WSGI applications.
  • Documents surrounding best practices (package pinning, health checks).
  • Multi-stage builds are used to make smaller images.

Security

  • Runs as non-root user.
  • Supports passing in secrets in a way that doesn’t leak them into the image.
  • Documents necessary processes for keeping dependencies up-to-date.
  • Mechanism for including SSH host public keys (GitHub is pre-populated).

Supported technologies

  • Python 3.6, 3.7, and 3.8.
  • Docker CE Stable (19.03).
  • Package installation using requirements.txt, setup.py, pipenv, poetry, and flit.
  • Debian, Ubuntu, RHEL 8, and CentOS 8 distributions supported out of the box.
  • Gitlab CI and CircleCI configurations included out of the box, as well as generic instructions for other CI/build systems.

Additional base images and CI systems can easily be added, and might be included in future updates.

Conda is not supported at this time.

Ready to build production-ready containers?

  • Configured for production use: small images, secure defaults.
  • Fast setup and fast builds, saving you days of ops and developer time.
  • Extensively tested with the latest version of Docker CE (19.03).
  • Use for an unlimited number of images in your company’s private repositories.
One time purchase Annual subscription
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 6 months of bugfix updates.
  • 100% money-back guarantee.
  • Latest release (v1.0.7, released Jan 8, 2020—see the changelog).
  • Use the template forever.
  • 12 months of feature and bugfix updates.
  • Automatically renews so you keep getting updates.
  • 100% money-back guarantee.
One time purchase Annual subscription

About me

Hi, I’m Itamar Turner-Trauring.

I’ve been writing Python since 1999, and I first started using Docker in 2014, when I was part of a team that wrote one of the first distributed storage backends for Docker.

I’ve since built Telepresence, a remote development tool for Kubernetes that was adopted as a Cloud Native Computing Foundation sandbox project and has more than 2000 stars on GitHub. I’ve also deployed a number of production Python applications as Docker images.

The patterns embedded in the Production-Ready Python Containers are based on this experience, as well as extensive additional research; this template is far better than any of my previous hand-built images.