11 Running tasks in containers
This chapter explains how running tasks in containers can simplify Airflow deployments that otherwise rely on many specialized operators and sprawling, conflicting dependencies. It motivates a move toward a generic, container-based execution model where each task runs inside an isolated image, giving a uniform interface for orchestration while reducing the cognitive load of learning multiple operator APIs. The chapter introduces containers and their lightweight isolation compared to virtual machines, then shows how Airflow can execute containerized tasks via Docker or Kubernetes to improve reliability, portability, and maintainability.
With Docker, the chapter walks through the lifecycle: building images that package task code and dependencies, running containers with commands and arguments, and persisting outputs using mounted volumes or networked storage. It demonstrates converting task logic into small CLI-style scripts, assembling minimal images, and invoking them from the DockerOperator, emphasizing a consistent pattern for inputs, outputs, and logging. A recommended workflow separates image development from DAG authoring: images are built and pushed (often via CI/CD), then referenced in DAGs, enabling better testability, safer dependency boundaries, and easier reuse across tasks.
For scalability and cluster scheduling, the chapter transitions to Kubernetes, outlining core concepts (control plane, nodes, pods) and resources for storage and services. It shows how to adapt the same tasks to the KubernetesPodOperator, including mounting persistent volumes, setting namespaces, and controlling image pull policies, as well as diagnosing stuck or pending pods using kubectl commands and events. Key differences from the Docker-only approach include task execution on separate cluster nodes, storage provisioned through Kubernetes primitives, and richer resource management. The result is a consistent, container-first pattern that scales from a single host to a cluster while preserving clean dependency isolation and a uniform task interface.
Illustration of our movie recommender DAG. The DAG fetches movie recommendations, uses them to rank movies, and stores the result in a database. Each of these steps involves a different operator, thus adding complexity to the development and maintenance of the DAG.
Complex and conflicting dependencies between Airflow tasks or DAGs. Running many DAGs in a single environment can lead to conflicts when DAGs depend on different versions of the same (or related) packages. Python in particular does not support installing different versions of the same package in the same environment. This means that any conflicts in packages (right) would need to be resolved by rewriting the DAGs (or their dependencies) to use the same package versions.
Comparison between virtual machines (VMs) and containers. Note that containers are much more lightweight as they don’t require running a full guest OS for each application.
Example output from the wttr-example container for Amsterdam
Docker version of the recommender DAG from figure 11.1
Managing dependencies across different tasks using containers
Illustration of what happens when a task is executed using the DockerOperator. The image registry stores a collection of Docker images This can be a private registry (containing our own images), or a public registry like DockerHub (which is used by default when fetching images). Images are cached locally when fetched so that you only have to do it once (barring any updates to the image).
The Docker-based DAG in the Airflow UI
Common workflow for working with Docker images in Airflow
High-level overview of Kubernetes
Several successful runs of the recommender DAG based on the KubernetesPodOperator
Workflow for building DAGs using the KubernetesPodOperator
Summary
- Airflow deployments can be difficult to manage if they involve many different operators, as this requires knowledge of the different APIs and complicates debugging and dependency management.
- One way of tackling this issue is to use container technologies such as Docker to encapsulate your tasks inside container images and run these images from within Airflow.
- This containerized approach has several advantages, including easier dependency management, a more uniform interface for running tasks, and improved testability of tasks.
- Data can be shared between containers using volume mounts.
- Using the DockerOperator, you can run tasks in container images directly using Docker, similar to the docker run CLI command.
- You can use the KubernetesPodOperator to run containerized tasks in pods on a Kubernetes cluster.
- Kubernetes allows you to scale your containerized tasks across a compute cluster, which provides (among other things) greater scalability and more flexibility in terms of computing resources.
Data Pipelines with Apache Airflow, Second Edition ebook for free