<@ULVA73B9P> I have a workflow with 12 `flows`, fe...
# ask-marvin
t
@Marvin I have a workflow with 12
flows
, few of them run as python script, few are
containers (docker)
. The docker I run with
local image.
But this causes issue when I deploy the flow
flow.serve()
is there any way to deploy the flow with local images? or better to pull them from dockerhub. My docker images are model specific and few are 2-3Gb, thus I don't push them to remote docker hub. What would be best-practice now for the deployment
m
thought for 901.7 seconds
Short answer: yes, you can deploy Prefect 3.x flows that use local Docker images — you just need to target a Docker work pool and tell Prefect not to pull/push. Best practice is to run a Docker worker on the same host(s) where those large images are already present, and configure your deployment to use that image with an appropriate pull policy. A few key points - In Prefect 3.x, containerized runs should target a Docker work pool (with a running Docker worker).
flow.serve()
by itself won’t magically run your flow in a container — you need to bind the flow to Docker infra or use
flow.deploy(...)
with a Docker pool. - For local images, the image must exist on the machine(s) where your Docker worker(s) run. If the worker is remote, either preload the image there or use a private/nearby registry. - Use the Docker worker’s job variables to set
image
and
image_pull_policy
to control pulling behavior. Recommended setup 1) Create a Docker work pool and start a worker on the host that has your large images:
Copy code
prefect work-pool create my-docker-pool --type docker
prefect worker start --pool my-docker-pool
- Install extras if needed:
pip install "prefect[docker]"
2) Build/load your large image(s) on that host and give them a specific tag (e.g.
my-local/model-a:2025-09
). 3) Deploy your flow to the Docker pool, pointing at the local image and disabling build/push:
Copy code
python
from prefect import flow

@flow
def my_flow():
    ...

my_flow.deploy(
    name="model-a",
    work_pool_name="my-docker-pool",
    # We’re not asking Prefect to build/push anything
    build=False,
    push=False,
    # Tell the Docker worker to use the preloaded image and not re-pull it
    job_variables={
        "image": "my-local/model-a:2025-09",
        "image_pull_policy": "IfNotPresent",  # or "Never" to never attempt a pull
        # optional: volumes/env/memory/etc
        # "volumes": ["/models/model-a:/models:ro"],
        # "mem_limit": "12g",
    },
)
If you prefer to keep using serve() You can bind your flow to the Docker work pool first, then call `serve()`:
Copy code
python
from prefect import flow
from prefect.flows import bind_flow_to_infrastructure
from prefect_docker.worker import DockerWorker

@flow
def my_flow():
    ...

bound = bind_flow_to_infrastructure(
    my_flow,
    work_pool="my-docker-pool",
    worker_cls=DockerWorker,
    job_variables={
        "image": "my-local/model-a:2025-09",
        "image_pull_policy": "Never",
    },
)

bound.serve(name="model-a")
This creates a deployment that targets your Docker pool, while still using
serve()
to register and watch it. When local images won’t work - If your Docker worker runs on a different machine from where you built the image, it won’t see your local image. Options: - Preload the image on each worker host (e.g., distribute tarballs and
docker load
), and set
image_pull_policy: Never/IfNotPresent
. - Run a private/nearby registry and configure credentials via a DockerRegistryCredentials block in job variables (
registry_credentials
) for fast pulls. - You can retrieve the default Docker job template to see all supported fields:
Copy code
prefect work-pool get-default-base-job-template --type docker
Best practices for large (2–3GB) model images - Prefer preloading or a private registry close to workers over Docker Hub to avoid slow/expensive pulls. - Keep the image slim: put large model artifacts on a shared volume and mount them at runtime instead of baking into the image: -
job_variables["volumes"] = ["/mnt/models/model-a:/models:ro"]
- Pin image tags per model/version and use
image_pull_policy: IfNotPresent
to use host cache. - Use one “family” base image for multiple flows to benefit from shared layers. Docs - Docker work pool and deployment configuration: Docker work pools with Prefect
- Creating deployments: Create deployments - Storing/packaging flow code: Store flow code Questions to help me tailor this - Are your Docker workers running on the same hosts where the images are built and stored? - Do you want to completely avoid any registry, or would a private/ephemeral registry be acceptable? - What exact error are you seeing when using
flow.serve()
with your local images? If you paste it here, I can pinpoint the fix.