David Martin Calalang
08/07/2025, 7:22 PMopt/prefect/home
. However, when I run the deployment, I get an [Errno 2] No such file or directory: '/opt/prefect/home'
for the set_working_directory
step in deployments. What could be some reasons this is happening?Marvin
08/07/2025, 7:22 PMNate
08/07/2025, 7:22 PMNate
08/07/2025, 7:22 PMNate
08/07/2025, 7:22 PMDavid Martin Calalang
08/07/2025, 7:23 PMMarvin
08/07/2025, 7:25 PMDavid Martin Calalang
08/07/2025, 7:32 PM# build section allows you to manage and build docker images
build:
- prefect_docker.deployments.steps.build_docker_image:
id: build_image
requires: prefect-docker>=0.3.1
image_name: {ecr_repository}
tag: latest
dockerfile: ./Dockerfile
# push section allows you to manage if and how this project is uploaded to remote locations
push:
- prefect_docker.deployments.steps.push_docker_image:
requires: prefect-docker>=0.3.1
image_name: '{{ build_image.image_name }}'
tag: '{{ build_image.tag }}'
# pull section allows you to provide instructions for cloning this project in remote locations
pull:
- prefect.deployments.steps.set_working_directory:
directory: /opt/prefect/home
Dockerfile:
FROM {private_repository}
COPY requirements.txt /opt/prefect/home/requirements.txt
RUN python -m pip install -r /opt/prefect/home/requirements.txt
COPY . /opt/prefect/home
WORKDIR /opt/prefect/home
And within the work pool itself, I don't explicitly set an image to pull from.Marvin
08/07/2025, 7:33 PMMarvin
08/07/2025, 7:34 PMDavid Martin Calalang
08/07/2025, 7:37 PMNate
08/07/2025, 7:38 PMNate
08/07/2025, 7:38 PMDavid Martin Calalang
08/07/2025, 7:38 PMDavid Martin Calalang
08/07/2025, 7:38 PMMarvin
08/07/2025, 7:38 PMNate
08/07/2025, 7:39 PMMarvin
08/07/2025, 7:39 PMyaml
# prefect.yaml
name: your-project
# prefect-version: ">=3.0.0" # optional
deployments:
- name: your-deployment
entrypoint: path/to/flow.py:flow # update to your flow
work_pool:
name: your-ecs-pool
job_variables:
# Use the image built and pushed below
image: "{{ build_image.image_name }}:{{ build_image.tag }}"
# You can also set ECS-specific job variables here if needed
# e.g., task_definition_overrides, env, cpu, memory, etc.
build:
- prefect_docker.deployments.steps.build_docker_image:
id: build_image
requires: "prefect-docker>=0.3.1"
image_name: "<http://your-account.dkr.ecr.your-region.amazonaws.com/your-repo|your-account.dkr.ecr.your-region.amazonaws.com/your-repo>"
tag: "2025-08-07-1" # avoid 'latest' if you value your sanity
dockerfile: "./Dockerfile"
push:
- prefect_docker.deployments.steps.push_docker_image:
requires: "prefect-docker>=0.3.1"
image_name: "{{ build_image.image_name }}"
tag: "{{ build_image.tag }}"
pull:
- prefect.deployments.steps.set_working_directory:
directory: /opt/prefect/home
Alternative: rely on WORKDIR and skip set_working_directory
yaml
# prefect.yaml
name: your-project
deployments:
- name: your-deployment
entrypoint: path/to/flow.py:flow
work_pool:
name: your-ecs-pool
job_variables:
image: "{{ build_image.image_name }}:{{ build_image.tag }}"
build:
- prefect_docker.deployments.steps.build_docker_image:
id: build_image
requires: "prefect-docker>=0.3.1"
image_name: "<http://your-account.dkr.ecr.your-region.amazonaws.com/your-repo|your-account.dkr.ecr.your-region.amazonaws.com/your-repo>"
tag: "2025-08-07-1"
dockerfile: "./Dockerfile"
push:
- prefect_docker.deployments.steps.push_docker_image:
requires: "prefect-docker>=0.3.1"
image_name: "{{ build_image.image_name }}"
tag: "{{ build_image.tag }}"
# no pull steps needed if WORKDIR is correct
A robust Dockerfile pattern
dockerfile
# Use your private base or Prefect's; just make sure the final image
# actually contains /opt/prefect/home and sets the correct WORKDIR.
FROM prefecthq/prefect:3.1.0-python3.11
# If you must use a private base image, swap the FROM line above:
# FROM {private_repository}
USER root
# Create the directory and ensure permissions
RUN mkdir -p /opt/prefect/home && chown -R prefect:prefect /opt/prefect
# Install dependencies first to leverage Docker layer caching
COPY requirements.txt /opt/prefect/home/requirements.txt
RUN python -m pip install --no-cache-dir -r /opt/prefect/home/requirements.txt
# Copy your code
COPY . /opt/prefect/home
# Set working directory
WORKDIR /opt/prefect/home
# Drop privileges (Prefect images use 'prefect' user)
USER prefect
Other quick checks
- Tag discipline: Build with unique tags and reference that exact tag in job_variables.image. latest means “not what you think.”
- Multi-stage Dockerfiles: If you use them, ensure the final stage contains /opt/prefect/home.
- Absolute paths: Use COPY . /opt/prefect/home (note the leading slash).
- If you insist on creating the directory at runtime, add a shell step before set_working_directory to mkdir -p the path—but it’s better to bake it into the image.
Docs (so you don’t have to guess)
- ECS guide: https://docs-3.prefect.io/integrations/prefect-aws/ecs_guideMarvin
08/07/2025, 7:39 PMDavid Martin Calalang
08/07/2025, 7:40 PMNate
08/07/2025, 7:40 PMNate
08/07/2025, 7:40 PMNate
08/07/2025, 7:54 PMDavid Martin Calalang
08/07/2025, 8:42 PMDavid Martin Calalang
08/07/2025, 8:43 PMNate
08/07/2025, 8:43 PMNate
08/07/2025, 8:44 PMDavid Martin Calalang
08/07/2025, 8:51 PMMarvin
08/07/2025, 8:56 PMMarvin
08/07/2025, 8:58 PMprefect deployment inspect "your-flow/your-deployment"
- Look for work_pool -> job_variables -> image.
- Prefect CLI: work pool defaults
- If you didn’t set an image on the deployment, it may inherit from the work pool’s base job template:
prefect work-pool inspect "your-ecs-pool"
- Look for the base job template JSON and any default image.
- Prefect CLI: the specific flow run
- Good for seeing the resolved run-level configuration:
prefect flow-run inspect <flow-run-id>
- Look for job_variables or infrastructure details that include image.
- Prefect UI
- Flow Runs -> select the run -> Run details. Check the Infrastructure/Work pool card; it shows the job variables, including image if set.
Worker logs (helpful, but not authoritative if ECS changes something)
- Start your ECS worker with debug logging so it prints the job variables it’s submitting:
- Set env var on the worker: PREFECT_LOGGING_LEVEL=DEBUG
- You should see a log that includes the image it’s sending to ECS for the task.
AWS ECS (source of truth)
- ECS Console (clicky path)
- ECS -> Clusters -> your cluster -> Tasks -> pick the task from your flow run
- Task -> Containers section shows the image string (repo:tag or repo@sha256:digest)
- Click the Task definition link -> Container definitions -> image also shown there
- AWS CLI
- Get the task details:
aws ecs describe-tasks --cluster YOUR_CLUSTER --tasks YOUR_TASK_ARN
- This returns the taskDefinitionArn and can include the container image on the task.
- Then fetch the task definition to see the exact image used:
aws ecs describe-task-definition --task-definition YOUR_TASK_DEFINITION_ARN
- Look under containerDefinitions[].image
- ECR (to verify the digest)
- Match what ECS ran to what’s in ECR:
aws ecr describe-images --repository-name your-repo --image-ids imageTag=your-tag
- Compare the imageDigest with the digest shown in ECS (or pull by digest: repo@sha256:...).
Tips that save you from déjà vu
- Avoid :latest; tag each build uniquely and point the deployment/job_variables.image to that exact tag.
- If your deployment doesn’t specify an image, the work pool’s base job template may be used instead—inspect both.
- ECS can cache; checking the digest in ECS/ECR removes doubt about which “latest” you actually got.
Docs, for when curiosity strikes
- Prefect ECS guide: https://docs-3.prefect.io/integrations/prefect-aws/ecs_guide
- Deployments in 3.x: https://docs-3.prefect.io/v3/concepts/deployments
If you share a flow run ID and cluster name, I can give you the exact AWS CLI commands with your values filled in. I know, the excitement is palpable.