Project: Prefect (Orchestration & Management / Scheduling & Orchestration)
File: docker.md

description: Learn how to store your flow code in a Docker image and serve your flow on any docker-compatible infrastructure. tags: Docker containers orchestration infrastructure deployments images Kubernetes search: boost: 2 The tutorial served a flow that enabled scheduling or creating flow runs through the Prefect API. With a Python script, you can build a Docker image for that script, allowing you to serve your flow in various remote environments. This guide uses Kubernetes, but you can use any Docker-compatible infrastructure. This guide covers how to: Write a Dockerfile to build an image that stores your Prefect flow code. Build a Docker image for your flow. Deploy and run your Docker image on a Kubernetes cluster. Look at the Prefect-maintained Docker images and discuss options for use. In this guide you will create a Dockerfile from scratch. Alternatively, Prefect makes it convenient to build a Docker image as part of deployment creation. You can even include environment variables and specify additional Python packages to install at runtime. If creating a deployment with a `prefect.yaml` file, the build step makes it easy to customize your Docker image and push it to the registry of your choice. See an . Deployment creation with a Python script that includes `flow.deploy` similarly allows you to customize your Docker image with keyword arguments as shown below. ```python ... if name == "main": hello_world.deploy( name="my-first-deployment", workpoolname="above-ground", image='myregistry/helloworld:demo', jobvariables={"env": { "EXTRAPIP_PACKAGES": "boto3" } } ) ``` A Python script that defines and serves a flow. This guide uses the flow script and deployment from the tutorial. Access to a running Prefect API server. You can sign up for a forever free or run a Prefect API server locally with `prefect server start`. installed on your machine. Make a clean directory to work from, called `prefect-docker-guide`. ```bash mkdir prefect-docker-guide cd prefect-docker-guide ``` In this directory, create a sub-directory named `flows` and put your flow script from the tutorial in it. ```bash mkdir flows cd flows touch prefect-docker-guide-flow.py ``` Here's the flow code for reference: ```python title="prefect-docker-guide-flow.py" import httpx from prefect import flow @flow(log_prints=True) def getrepoinfo(repo_name: str = "PrefectHQ/prefect"): url = f"https://api.github.com/repos/{repo_name}" response = httpx.get(url) response.raiseforstatus() repo = response.json() print(f"{repo_name} repository statistics :") print(f"Stars : {repo['stargazers_count']}") print(f"Forks : {repo['forks_count']}") if name == "main": getrepoinfo.serve(name="prefect-docker-guide") ``` The next file to add to the `prefect-docker-guide` directory is a `requirements.txt`. Include all dependencies required for your `prefect-docker-guide-flow.py` script in the Docker image you will build. ```bash touch requirements.txt ``` Here's what you will put in your `requirements.txt` file: ```txt title="requirements.txt" prefect>=2.12.0 httpx ``` Create a `Dockerfile` to create a Docker image that will also store the flow code. ```bash touch Dockerfile ``` Add the following content to your `Dockerfile`: ```dockerfile title="Dockerfile" FROM prefecthq/prefect:2-python3.10 COPY requirements.txt . RUN pip install -r requirements.txt --trusted-host pypi.python.org --no-cache-dir COPY flows /opt/prefect/flows CMD ["python", "flows/prefect-docker-guide-flow.py"] ``` Now that you have a Dockerfile, you can build your image by running: ```bash docker build -t prefect-docker-guide-image . ``` Check that your build worked by running a container from your new

=== "Cloud" Your container needs an API URL and an API key to communicate with Prefect Cloud. You can get an API key from the section of the user settings in the Prefect UI. You can get your API URL by running `prefect config view` and copying the `PREFECTAPIURL` value. Provide both these values to your container by passing them as environment variables with the `-e` flag. ```bash docker run -e PREFECTAPIURL=YOURPREFECTAPIURL -e PREFECTAPIKEY=YOURAPI_KEY prefect-docker-guide-image ``` After running the above command, the container should start up and serve the flow within the container. === "Self-hosted" Your container needs an API URL and network access to communicate with the Prefect API. For this guide, assume the Prefect API is running on the same machine that you will run your container on and the Prefect API was started with `prefect server start`. If you're running a different setup, check out the for information on how to connect to your Prefect API instance. To ensure that your flow container can communicate with the Prefect API, set your `PREFECTAPIURL` to `http://host.docker.internal:4200/api`. If you're running Linux, set your `PREFECTAPIURL` to `http://localhost:4200/api` and use the `--network="host"` option instead. ```bash docker run --network="host" -e PREFECTAPIURL=http://host.docker.internal:4200/api prefect-docker-guide-image ``` After running the above command, the container should start up and serve the flow within the container. Now that you have a Docker image with your flow code embedded, you can deploy it to a remote environment. This guide simulates a remote environment by using Kubernetes locally with Docker Desktop. Use the instructions provided by Docker to To ensure the process serving your flow is always running, create a . If your flow's container ever crashes, Kubernetes will automatically restart it, ensuring that you don't miss any scheduled runs. First, create a `deployment-manifest.yaml` file in your `prefect-docker-guide` directory: ```bash touch deployment-manifest.yaml ``` Add the following content to your `deployment-manifest.yaml` file: === "Cloud" ```yaml title="deployment-manifest.yaml" apiVersion: apps/v1 kind: Deployment metadata: name: prefect-docker-guide spec: replicas: 1 selector: matchLabels: flow: get-repo-info template: metadata: labels: flow: get-repo-info spec: containers: name: flow-container image: prefect-docker-guide-image:latest env: name: PREFECTAPIURL value: YOURPREFECTAPI_URL name: PREFECTAPIKEY value: YOURAPIKEY imagePullPolicy: Never ``` !!!tip "Keep your API key secret" In the above manifest, you are passing in the Prefect API URL and API key as environment variables. This approach is simple, but it is not secure. If you are deploying your flow to a remote cluster, you should use a to store your API key. === "Self-hosted" ```yaml title="deployment-manifest.yaml" apiVersion: apps/v1 kind: Deployment metadata: name: prefect-docker-guide spec: replicas: 1 selector: matchLabels: flow: get-repo-info template: metadata: labels: flow: get-repo-info spec: containers: name: flow-container image: prefect-docker-guide-image:latest env: name: PREFECTAPIURL value: <http://host.docker.internal:4200/api> imagePullPolicy: Never ``` !!!tip "Linux users" If you're running Linux, set your `PREFECTAPIURL` to use the IP address of your machine instead of `host.docker.internal`. This manifest defines how your image will run when deployed in your Kubernetes cluster. Note that you will run a single replica of your flow

If you want to run multiple replicas of your flow container to keep up with an active schedule, or because your flow is resource-intensive, you can increase the `replicas` value. Now that you have a deployment manifest, you can deploy your flow to the cluster by running: ```bash kubectl apply -f deployment-manifest.yaml ``` Monitor the status of your Kubernetes deployment by running: ```bash kubectl get deployments ``` Once the deployment has successfully started, you can check the logs of your flow container by running the following: ```bash kubectl logs -l flow=get-repo-info ``` Now that you're serving your flow in your cluster, you can trigger a flow run by running: ```bash prefect deployment run get-repo-info/prefect-docker-guide ``` Navigate to the URL provided by the `prefect deployment run` command and follow the flow run through the logs in the Prefect UI. Every release of Prefect results in several new Docker images. These images are all named and their tags identify their differences. When a release is published, images are built for all of Prefect's supported Python versions. These images are tagged to identify the combination of Prefect and Python versions contained. Additionally, we have "convenience" tags which are updated with each release to facilitate automatic updates. For example, when release `2.11.5` is published: Images with the release packaged are built for each supported Python version (3.8, 3.9, 3.10, 3.11) with both standard Python and Conda. These images are tagged with the full description. For example, `prefect:2.1.1-python3.10` and `prefect:2.1.1-python3.10-conda`. For users that want more specific pins, these images are also tagged with the SHA of the git commit of the release. For example, `sha-88a7ff17a3435ec33c95c0323b8f05d7b9f3f6d2-python3.10`. For users that want to be on the latest `2.1.x` release and receiving patch updates, we update a tag without the patch version to this release. For example, `prefect.2.1-python3.10`. For users that want to be on the latest `2.x.y` release and receiving minor version updates, we update a tag without the minor or patch version to this release. For example, `prefect.2-python3.10`. For users who want the latest `2.x.y` release without specifying a Python version, we update `2-latest` to the image for our highest supported Python version, which in this case is equivalent to `prefect:2.1.1-python3.10`. !!! tip "Choose image versions carefully" It's a good practice to use Docker images with specific Prefect versions in production. Use care when employing images that automatically update to new versions (such as `prefecthq/prefect:2-python3.11` or `prefecthq/prefect:3-latest`). Standard Python images are based on the official Python `slim` images, such as `python:3.10-slim`. | Tag | Prefect Version | Python Version | | | :-: | -: | | 3-latest | most recent v2 PyPi version | 3.10 | | 3-python3.12 | most recent v2 PyPi version | 3.12 | | 3-python3.11 | most recent v2 PyPi version | 3.11 | | 3-python3.10 | most recent v2 PyPi version | 3.10 | | 3-python3.9 | most recent v2 PyPi version | 3.9 | | 3.X-python3.12 | 2.X | 3.12 | | 3.X-python3.11 | 2.X | 3.11 | | 3.X-python3.10 | 2.X | 3.10 | | 3.X-python3.9 | 2.X | 3.9 | | sha-&lt;hash&gt;-python3.12 | &lt;hash&gt; | 3.12 | |

| &lt;hash&gt; | 3.11 | | sha-&lt;hash&gt;-python3.10 | &lt;hash&gt; | 3.10 | | sha-&lt;hash&gt;-python3.9 | &lt;hash&gt; | 3.9 | Conda flavored images are based on `continuumio/miniconda3`. Prefect is installed into a conda environment named `prefect`. | Tag | Prefect Version | Python Version | | | :-: | -: | | 3-latest-conda | most recent v3 PyPi version | 3.10 | | 3-python3.12-conda | most recent v3 PyPi version | 3.12 | | 3-python3.11-conda | most recent v3 PyPi version | 3.11 | | 3-python3.10-conda | most recent v3 PyPi version | 3.10 | | 3-python3.9-conda | most recent v3 PyPi version | 3.9 | | 3.X-python3.12-conda | 3.X | 3.12 | | 3.X-python3.11-conda | 3.X | 3.11 | | 3.X-python3.10-conda | 3.X | 3.10 | | 3.X-python3.9-conda | 3.X | 3.9 | | sha-&lt;hash&gt;-python3.12-conda | &lt;hash&gt; | 3.12 | | sha-&lt;hash&gt;-python3.11-conda | &lt;hash&gt; | 3.11 | | sha-&lt;hash&gt;-python3.10-conda | &lt;hash&gt; | 3.10 | | sha-&lt;hash&gt;-python3.9-conda | &lt;hash&gt; | 3.9 | If your flow relies on dependencies not found in the default `prefecthq/prefect` images, you may want to build your own image. You can either base it off of one of the provided `prefecthq/prefect` images, or build your own image. See the to build custom images with dependencies specified in a `requirements.txt` file. By default, Prefect that use containers refer to the `3-latest` image. You can specify another image at work pool creation. You can override the work pool image choice in individual deployments. Here is an example `Dockerfile` for building an image based on `prefecthq/prefect:2-latest`, but with `scikit-learn` installed: ```dockerfile FROM prefecthq/prefect:3-latest RUN pip install scikit-learn ``` The options described above have different complexity and performance characteristics. We recommend the following when choosing a strategy: If your flow only makes use of tasks defined in the same file as the flow, or tasks that are part of `prefect` itself, you can rely on the default provided `prefecthq/prefect` image. If your flow requires a few extra dependencies found on PyPI, you can use the default `prefecthq/prefect` image and set `prefect.deployments.steps.pipinstallrequirements:` in the `pull`step to install these dependencies at runtime. If the installation process requires compiling code or other expensive operations, you should consider building a custom image instead. If your flow (or flows) require extra dependencies or shared libraries, we recommend building a shared custom image with all the extra dependencies and shared task definitions you need. Your flows can then all rely on the same image, but have their source stored externally. This option can ease development, as the shared image only needs to be rebuilt when dependencies change, not when the flow source changes. We only served a single flow in this guide, but you can extend this setup to serve multiple flows in a single Docker image by updating your Python script to use `flow.to_deployment` and `serve` to . To learn more about deploying flows, check out the concept doc. For advanced infrastructure requirements, such as executing each flow run within its own dedicated Docker container, learn more in the .