Madushan Pathirana
08/01/2025, 7:13 AMMarvin
08/01/2025, 7:13 AMMarvin
08/01/2025, 7:14 AMprefect.yaml
file in Prefect 3.x. Instead, you'll handle deployment configuration in Python. Create a deployment.py
file in your src
directory:
python
# src/deployment.py
from prefect import serve
from flow.test_flow import cat_fact_flow
if __name__ == "__main__":
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest"
)
2. Update your `docker-compose.yml`:
yaml
version: '3.8'
services:
prefect_server:
build:
context: .
dockerfile: Dockerfile.prefect_server
ports:
- "4200:4200"
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_SERVER_API_PORT=4200
prefect_worker:
build:
context: .
dockerfile: Dockerfile.prefect_worker
environment:
- PREFECT_API_URL=<http://prefect_server:4200/api>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- prefect_server
3. Update `Dockerfile.prefect_worker`:
dockerfile
FROM prefecthq/prefect:2-python3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# Add httpx to requirements.txt or install it here
RUN pip install httpx
CMD ["prefect", "worker", "start", "--pool", "cat-facts-pool", "--type", "docker"]
4. Create a Dockerfile for your flow (let's call it Dockerfile.flow
):
dockerfile
FROM prefecthq/prefect:2-python3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
RUN pip install httpx
COPY flow/ /app/flow/
CMD ["python", "flow/test_flow.py"]
5. Update your `requirements.txt`:
prefect>=3.0.0
httpx
To deploy and run your flow:
1. First, create a Docker work pool:
bash
prefect work-pool create cat-facts-pool --type docker
2. Start the services:
bash
docker-compose up -d
3. Build the flow image:
bash
docker build -t cat-facts-image:latest -f Dockerfile.flow .
4. Deploy your flow:
bash
python deployment.py
5. To run the deployment:
bash
prefect deployment run cat-fact-flow/cat-fact-deployment
Key differences from the previous 2.x version:
- No prefect.yaml
needed
- Deployment configuration is handled in Python
- Work pools are typed (we're using a Docker work pool)
- The worker needs access to Docker socket to spawn containers
- Flow deployment is handled through the .deploy()
method
The worker will pull the specified image and run the flow in a container when triggered.
Let me know if you need any clarification or have questions about this updated 3.x setup!Madushan Pathirana
08/01/2025, 7:19 AMMarvin
08/01/2025, 7:19 AMMarvin
08/01/2025, 7:20 AMdeployments.py
file that manages all your deployments:
python
# src/deployments.py
from prefect import serve
from flow.test_flow import cat_fact_flow
# Import other flows
from flow.other_flow import other_flow
from flow.another_flow import another_flow
def deploy_all():
# Cat Facts Deployment
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest",
schedule={"interval": "1 hour"} # Optional: Add schedule
)
# Other Flow Deployment
other_flow.deploy(
name="other-deployment",
work_pool_name="other-pool",
image="other-image:latest",
schedule={"cron": "0 0 * * *"} # Optional: Add schedule
)
# Another Flow Deployment
another_flow.deploy(
name="another-deployment",
work_pool_name="another-pool",
image="another-image:latest"
)
if __name__ == "__main__":
deploy_all()
2. Multiple Files Approach (More Modular)
Create a deployments
directory:
src/
├── deployments/
│ ├── __init__.py
│ ├── cat_facts.py
│ ├── other_flow.py
│ └── another_flow.py
├── flow/
│ ├── test_flow.py
│ ├── other_flow.py
│ └── another_flow.py
└── deploy_all.py
Individual deployment files:
python
# src/deployments/cat_facts.py
from prefect import serve
from flow.test_flow import cat_fact_flow
def deploy():
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest"
)
if __name__ == "__main__":
deploy()
python
# src/deployments/other_flow.py
from prefect import serve
from flow.other_flow import other_flow
def deploy():
other_flow.deploy(
name="other-deployment",
work_pool_name="other-pool",
image="other-image:latest"
)
if __name__ == "__main__":
deploy()
Main deployment script:
python
# src/deploy_all.py
from deployments import cat_facts, other_flow, another_flow
if __name__ == "__main__":
cat_facts.deploy()
other_flow.deploy()
another_flow.deploy()
Update your Dockerfile structure to handle multiple flows:
dockerfile
# Dockerfile.flow
FROM prefecthq/prefect:2-python3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy all flow directories
COPY flow/ /app/flow/
# The specific flow to run will be determined by the deployment
Update your docker-compose.yml
to handle multiple work pools:
yaml
version: '3.8'
services:
prefect_server:
build:
context: .
dockerfile: Dockerfile.prefect_server
ports:
- "4200:4200"
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_SERVER_API_PORT=4200
cat_facts_worker:
build:
context: .
dockerfile: Dockerfile.prefect_worker
environment:
- PREFECT_API_URL=<http://prefect_server:4200/api>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: ["prefect", "worker", "start", "--pool", "cat-facts-pool", "--type", "docker"]
depends_on:
- prefect_server
other_worker:
build:
context: .
dockerfile: Dockerfile.prefect_worker
environment:
- PREFECT_API_URL=<http://prefect_server:4200/api>
volumes:
- /var/run/docker.sock:/var/run/docker.sock
command: ["prefect", "worker", "start", "--pool", "other-pool", "--type", "docker"]
depends_on:
- prefect_server
To deploy and run:
1. Create the work pools:
bash
prefect work-pool create cat-facts-pool --type docker
prefect work-pool create other-pool --type docker
2. Build your images:
bash
docker build -t cat-facts-image:latest -f Dockerfile.flow .
docker build -t other-image:latest -f Dockerfile.flow .
3. Deploy all flows:
bash
python deploy_all.py
Marvin
08/01/2025, 7:20 AMbash
python deployments/cat_facts.py
python deployments/other_flow.py
4. Start the infrastructure:
bash
docker-compose up -d
5. Run specific deployments:
bash
prefect deployment run 'cat-fact-flow/cat-fact-deployment'
prefect deployment run 'other-flow/other-deployment'
Key benefits of this structure:
- Modular deployment files make it easier to maintain and update individual deployments
- Each flow can have its own work pool and worker
- You can deploy all flows at once or individually
- Easy to add new flows and deployments
- Clear separation of concerns between flow code and deployment configuration
Remember to:
- Keep your requirements.txt updated with all dependencies needed by all flows
- Use different work pools if flows have different resource requirements
- Consider using different schedules for different deployments
- Use meaningful names for your deployments to easily identify them
Let me know if you need any clarification or have questions about this setup!Madushan Pathirana
08/01/2025, 8:23 AMMarvin
08/01/2025, 8:23 AMMarvin
08/01/2025, 8:23 AMMadushan Pathirana
08/01/2025, 8:24 AMMarvin
08/01/2025, 8:24 AMMarvin
08/01/2025, 8:24 AMyaml
version: '3.8'
services:
prefect_server:
build:
context: .
dockerfile: Dockerfile.prefect_server
ports:
- "4200:4200"
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_SERVER_API_PORT=4200
prefect_worker:
build:
context: .
dockerfile: Dockerfile.prefect_worker
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Give Docker access to worker
- ./:/app # Mount your code
environment:
- PREFECT_API_URL=<http://prefect_server:4200/api>
depends_on:
- prefect_server
2. Create a deployment script (deployment.py
) in your project root:
python
from prefect import flow
from flow.test_flow import cat_fact_flow
if __name__ == "__main__":
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest"
)
3. Update your Dockerfile.flow
(create if it doesn't exist):
dockerfile
FROM prefecthq/prefect:2-python3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
RUN pip install httpx
COPY flow/ /app/flow/
CMD ["python", "flow/test_flow.py"]
Now, follow these steps to deploy:
1. First, make sure you're not inside any container. From your host machine, create the work pool:
bash
prefect work-pool create cat-facts-pool --type docker
2. Build the flow image:
bash
docker build -t cat-facts-image:latest -f Dockerfile.flow .
3. Start your services:
bash
docker-compose up -d
4. Deploy your flow (from your host machine, not inside the container):
bash
python deployment.py
5. Run your deployment:
bash
prefect deployment run 'Cat Fact Flow/cat-fact-deployment'
If you need to run commands inside the containers for debugging, you can do:
bash
# To access the worker container
docker-compose exec prefect_worker bash
# To access the server container
docker-compose exec prefect_server bash
The key points to remember:
- Deployments should typically be created from your host machine, not from inside containers
- The worker container needs access to the Docker socket (/var/run/docker.sock
)
- Make sure your Docker daemon is running on the host machine
- The worker needs to be able to pull/build images, so it needs Docker access
Let me know if you still encounter any issues!Madushan Pathirana
08/01/2025, 8:28 AMMarvin
08/01/2025, 8:28 AMMarvin
08/01/2025, 8:29 AMDockerfile.prefect_server
to include deployment capabilities:
dockerfile
FROM prefecthq/prefect:2-python3.10
WORKDIR /app
# Install Docker CLI (needed for building images)
RUN apt-get update && apt-get install -y \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release \
&& curl -fsSL <https://download.docker.com/linux/debian/gpg> | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
&& echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] <https://download.docker.com/linux/debian> $(lsb_release -cs) stable" > /etc/apt/sources.list.d/docker.list \
&& apt-get update \
&& apt-get install -y docker-ce-cli
# Copy your application files
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy your application code
COPY . .
# Start the Prefect server
CMD ["prefect", "server", "start"]
2. Update your `docker-compose.yml`:
yaml
version: '3.8'
services:
prefect_server:
build:
context: .
dockerfile: Dockerfile.prefect_server
ports:
- "4200:4200"
volumes:
- /var/run/docker.sock:/var/run/docker.sock # Give Docker access
- .:/app # Mount your code
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_SERVER_API_PORT=4200
prefect_worker:
build:
context: .
dockerfile: Dockerfile.prefect_worker
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- .:/app
environment:
- PREFECT_API_URL=<http://prefect_server:4200/api>
depends_on:
- prefect_server
3. Create a deployment script (src/deployment.py
):
python
from prefect import flow
from flow.test_flow import cat_fact_flow
import subprocess
def build_and_push_image():
"""Build and push the Docker image"""
subprocess.run(["docker", "build", "-t", "cat-facts-image:latest", "-f", "Dockerfile.flow", "."], check=True)
# If using a registry, you would push here
# subprocess.run(["docker", "push", "your-registry/cat-facts-image:latest"], check=True)
def deploy_flow():
"""Deploy the flow"""
# Build the image first
build_and_push_image()
# Deploy the flow
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest",
build=None # We're handling the build separately
)
if __name__ == "__main__":
deploy_flow()
4. Create a script to handle the entire deployment process (src/deploy_all.sh
):
bash
#!/bin/bash
set -e
# Create work pool if it doesn't exist
prefect work-pool create cat-facts-pool --type docker || true
# Run the deployment
python deployment.py
Make it executable:
bash
chmod +x deploy_all.sh
5. For CI/CD, here's an example GitHub Actions workflow (.github/workflows/deploy.yml
):
yaml
name: Deploy Prefect Flows
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Build and start services
run: |
docker-compose up -d
# Wait for services to be ready
sleep 30
- name: Deploy flows
run: |
docker-compose exec -T prefect_server ./deploy_all.sh
6. For local development and testing, you can deploy using:
bash
# Start the services
docker-compose up -d
# Execute deployment inside the container
docker-compose exec prefect_server ./deploy_all.sh
Key points for CI/CD:
1. Environment Variables: For production, you'll want to add appropriate environment variables for authentication:
```yaml
# In docker-compose.yml
services:
prefect_server:
environment:
- PREFECT_API_KEY=${PREFECT_API_KEY}Marvin
08/01/2025, 8:29 AM2. *Registry Authentication*: If using a private registry:
```python
# In deployment.py
import os
def build_and_push_image():
registry = os.getenv("DOCKER_REGISTRY", "your-registry")
image_name = f"{registry}/cat-facts-image:latest"
# Login to registry (in CI/CD, this would be handled by GitHub Actions)
subprocess.run(["docker", "login", registry,
"-u", os.getenv("DOCKER_USERNAME"),
"-p", os.getenv("DOCKER_PASSWORD")],
check=True)
# Build and push
subprocess.run(["docker", "build", "-t", image_name, "-f", "Dockerfile.flow", "."], check=True)
subprocess.run(["docker", "push", image_name], check=True)
3. Error Handling: Add proper error handling and logging:
python
# In deployment.py
import logging
logging.basicConfig(level=<http://logging.INFO|logging.INFO>)
logger = logging.getLogger(__name__)
def deploy_flow():
try:
build_and_push_image()
<http://logger.info|logger.info>("Successfully built and pushed image")
cat_fact_flow.deploy(
name="cat-fact-deployment",
work_pool_name="cat-facts-pool",
image="cat-facts-image:latest"
)
<http://logger.info|logger.info>("Successfully deployed flow")
except Exception as e:
logger.error(f"Deployment failed: {str(e)}")
raise
This setup allows you to:
- Deploy flows from within containers
- Integrate with CI/CD pipelines
- Handle image building and pushing
- Manage work pools and deployments automatically
- Handle errors and logging appropriately
Let me know if you need any clarification or have questions about specific parts of this setup!