Jonathan Sakkos
03/23/2025, 6:39 AMMarvin
03/23/2025, 6:40 AMdocker-compose.yaml
file to run Prefect 3 in a Docker container:
yaml
version: '3.8'
services:
prefect:
image: prefecthq/prefect:3.0.0rc2-python3.12
environment:
PREFECT_HOME: /data
command: prefect server start --host 0.0.0.0
ports:
- "4200:4200"
volumes:
- prefect-data:/data
- .:/app
volumes:
prefect-data: {}
To use this setup, you can run the following commands:
1. Start the Prefect service:
bash
docker compose up -d
2. Stream the logs if needed:
bash
docker compose logs -f
3. Stop the service:
bash
docker compose down
Make sure you replace any necessary configuration details with your own, especially if you are using Prefect Cloud. You may need to set the PREFECT_API_URL
and PREFECT_API_KEY
environment variables accordingly.
For further information, you can refer to the Prefect Docker Compose Example.Jonathan Sakkos
03/23/2025, 6:41 AMMarvin
03/23/2025, 6:42 AMdocker-compose.yaml
file will expose the Prefect server on port 4200. By binding to 0.0.0.0
, the server is accessible from any network interface on the host machine, including your local network.
Just ensure that your network settings and firewall rules allow traffic on port 4200. If everything is configured correctly, you should be able to access the Prefect server from other devices on your local network by navigating to http://<host_machine_ip>:4200
in a web browser.Jonathan Sakkos
03/23/2025, 6:44 AMMarvin
03/23/2025, 6:44 AMprefect
hostname is not resolvable on your local machine because it's internal to the Docker network.
To resolve this issue, you can update the Prefect server configuration to use the IP address of the host machine instead of prefect
. Here's what you can do:
1. Update the docker-compose.yaml
file: Modify the command to include the --host
flag with 0.0.0.0
to ensure it's accessible from outside the container.
yaml
services:
prefect:
image: prefecthq/prefect:3.0.0rc2-python3.12
environment:
PREFECT_HOME: /data
command: prefect server start --host 0.0.0.0
ports:
- "4200:4200"
volumes:
- prefect-data:/data
- .:/app
2. Access the Prefect UI using the host's IP address: When accessing the Prefect UI, use the IP address of the host machine instead of prefect
. For example, if your host's IP address is 192.168.1.10
, navigate to <http://192.168.1.10:4200>
in your browser.
3. Check Docker Network Configuration: Ensure that the Docker network is properly configured to allow connections from your local network.
By ensuring the server is bound to 0.0.0.0
and accessing it via the host machine's IP address, you should be able to resolve the connection issue.Jonathan Sakkos
03/23/2025, 6:47 AM# Use the official Python image with uv pre-installed
FROM <http://ghcr.io/astral-sh/uv:python3.12-bookworm-slim|ghcr.io/astral-sh/uv:python3.12-bookworm-slim>
# Set the working directory
WORKDIR /app
# Set environment variables
ENV UV_SYSTEM_PYTHON=1
ENV PATH="/root/.local/bin:$PATH"
# Copy only the requirements file first to leverage Docker cache
COPY requirements-prefect.txt .
# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install -r requirements-prefect.txt
# Copy the rest of the application code
COPY . .
# Install curl for health checks
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Set the entrypoint
ENTRYPOINT ["/bin/bash", "src/deployments/start_prefect.sh"]
docker-compose
services:
prefect:
build:
context: .
dockerfile: Dockerfile.prefect
ports:
- "4200:4200"
volumes:
- prefect_data:/root/.prefect
- ./src:/app/src
- ./data:/app/data # Mount data directory for SQLite database
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_UI_URL=<http://prefect:4200/api>
- PREFECT_API_URL=<http://prefect:4200/api>
restart: always
volumes:
prefect_data:
start_prefect.sh
#!/bin/bash
set -e
echo "Starting Prefect server..."
# Start Prefect server in the background
prefect server start &
SERVER_PID=$!
# Wait for Prefect server to be ready
echo "Waiting for Prefect server to be ready..."
until curl --silent --fail <http://localhost:4200/api/health> &>/dev/null; do
echo "Waiting for Prefect server to be ready..."
sleep 5
done
echo "Prefect server is ready. Creating work pool..."
# Create the 'process' work pool
prefect work-pool create "my-pool" --type process --overwrite
echo "Work pool created. Starting worker..."
# Start the worker in the background
prefect worker start --pool "my-pool" &
WORKER_PID=$!
echo "Worker started. Waiting for worker to connect..."
sleep 10
echo "Deploying flows..."
# Deploy flows
cd /app && python src/deployments/deploy_flows.py
echo "Flows deployed. Keeping container running..."
# Monitor processes
while true; do
if ! kill -0 $SERVER_PID 2>/dev/null; then
echo "Prefect server process died, restarting..."
prefect server start &
SERVER_PID=$!
fi
if ! kill -0 $WORKER_PID 2>/dev/null; then
echo "Worker process died, restarting..."
prefect worker start --pool "my-pool" &
WORKER_PID=$!
fi
sleep 30
done
Marvin
03/23/2025, 6:47 AMJonathan Sakkos
03/23/2025, 6:47 AM# Use the official Python image with uv pre-installed
FROM <http://ghcr.io/astral-sh/uv:python3.12-bookworm-slim|ghcr.io/astral-sh/uv:python3.12-bookworm-slim>
# Set the working directory
WORKDIR /app
# Set environment variables
ENV UV_SYSTEM_PYTHON=1
ENV PATH="/root/.local/bin:$PATH"
# Copy only the requirements file first to leverage Docker cache
COPY requirements-prefect.txt .
# Install dependencies
RUN --mount=type=cache,target=/root/.cache/uv \
uv pip install -r requirements-prefect.txt
# Copy the rest of the application code
COPY . .
# Install curl for health checks
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
# Set the entrypoint
ENTRYPOINT ["/bin/bash", "src/deployments/start_prefect.sh"]
docker-compose
services:
prefect:
build:
context: .
dockerfile: Dockerfile.prefect
ports:
- "4200:4200"
volumes:
- prefect_data:/root/.prefect
- ./src:/app/src
- ./data:/app/data # Mount data directory for SQLite database
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_UI_URL=<http://prefect:4200/api>
- PREFECT_API_URL=<http://prefect:4200/api>
restart: always
volumes:
prefect_data:
Marvin
03/23/2025, 6:47 AMPREFECT_UI_URL
and PREFECT_API_URL
being set to <http://prefect:4200/api>
, which is not resolvable from outside the Docker network. Here are some adjustments you can make:
1. Update the Environment Variables: Change the PREFECT_UI_URL
and PREFECT_API_URL
to use 0.0.0.0
or the host machine's IP address instead of prefect
. This ensures they are accessible from your local network.
2. Ensure Proper Entrypoint Configuration: Verify that the start_prefect.sh
script correctly starts the Prefect server with the necessary host configuration. It should include a command like prefect server start --host 0.0.0.0
.
3. Access the Prefect UI: Use the host machine's IP address in your browser to access the Prefect UI, such as http://<host_machine_ip>:4200
.
Here's a revised snippet of your `docker-compose.yaml`:
yaml
services:
prefect:
build:
context: .
dockerfile: Dockerfile.prefect
ports:
- "4200:4200"
volumes:
- prefect_data:/root/.prefect
- ./src:/app/src
- ./data:/app/data
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_UI_URL=<http://0.0.0.0:4200/api>
- PREFECT_API_URL=<http://0.0.0.0:4200/api>
restart: always
volumes:
prefect_data:
Make sure that your start_prefect.sh
script aligns with these settings and that any hardcoded references to prefect
are adjusted to use 0.0.0.0
or the host IP. This should help resolve the connectivity issue.Jonathan Sakkos
03/23/2025, 6:49 AM#!/bin/bash
set -e
echo "Starting Prefect server..."
# Start Prefect server in the background
prefect server start &
SERVER_PID=$!
# Wait for Prefect server to be ready
echo "Waiting for Prefect server to be ready..."
until curl --silent --fail <http://localhost:4200/api/health> &>/dev/null; do
echo "Waiting for Prefect server to be ready..."
sleep 5
done
echo "Prefect server is ready. Creating work pool..."
# Create the 'process' work pool
prefect work-pool create "my-pool" --type process --overwrite
echo "Work pool created. Starting worker..."
# Start the worker in the background
prefect worker start --pool "my-pool" &
WORKER_PID=$!
echo "Worker started. Waiting for worker to connect..."
sleep 10
echo "Deploying flows..."
# Deploy flows
cd /app && python src/deployments/deploy_flows.py
echo "Flows deployed. Keeping container running..."
# Monitor processes
while true; do
if ! kill -0 $SERVER_PID 2>/dev/null; then
echo "Prefect server process died, restarting..."
prefect server start &
SERVER_PID=$!
fi
if ! kill -0 $WORKER_PID 2>/dev/null; then
echo "Worker process died, restarting..."
prefect worker start --pool "my-pool" &
WORKER_PID=$!
fi
sleep 30
done
Marvin
03/23/2025, 6:49 AMstart_prefect.sh
script seems generally well-structured, but there are a few adjustments you can make to ensure the Prefect server is accessible from outside the container:
1. Use 0.0.0.0
for Binding: Ensure that the Prefect server is started with the --host 0.0.0.0
option. This will allow connections from any network interface.
2. Correct the curl
Command: When checking for the server's readiness, use <http://localhost:4200/api/health>
inside the container. However, ensure that the server is bound to 0.0.0.0
so it can also be accessed externally.
Here's a revised version of your script with these considerations:
bash
#!/bin/bash
set -e
echo "Starting Prefect server..."
# Start Prefect server in the background
prefect server start --host 0.0.0.0 &
SERVER_PID=$!
# Wait for Prefect server to be ready
echo "Waiting for Prefect server to be ready..."
until curl --silent --fail <http://localhost:4200/api/health> &>/dev/null; do
echo "Waiting for Prefect server to be ready..."
sleep 5
done
echo "Prefect server is ready. Creating work pool..."
# Create the 'process' work pool
prefect work-pool create "my-pool" --type process --overwrite
echo "Work pool created. Starting worker..."
# Start the worker in the background
prefect worker start --pool "my-pool" &
WORKER_PID=$!
echo "Worker started. Waiting for worker to connect..."
sleep 10
echo "Deploying flows..."
# Deploy flows
cd /app && python src/deployments/deploy_flows.py
echo "Flows deployed. Keeping container running..."
# Monitor processes
while true; do
if ! kill -0 $SERVER_PID 2>/dev/null; then
echo "Prefect server process died, restarting..."
prefect server start --host 0.0.0.0 &
SERVER_PID=$!
fi
if ! kill -0 $WORKER_PID 2>/dev/null; then
echo "Worker process died, restarting..."
prefect worker start --pool "my-pool" &
WORKER_PID=$!
fi
sleep 30
done
By binding the server to 0.0.0.0
and ensuring the health check uses localhost
, you should be able to access the Prefect server from outside the Docker container on your local network.Jonathan Sakkos
03/23/2025, 6:52 AMMarvin
03/23/2025, 6:52 AMdocker-compose.yaml
file, the environment variables PREFECT_SERVER_API_HOST
, PREFECT_UI_URL
, and PREFECT_API_URL
are not strictly necessary if you're specifying the host binding directly in your start_prefect.sh
script with --host 0.0.0.0
.
However, if you intend to use these environment variables for other parts of your setup or scripts, you might want to keep them. Here's when they are useful:
1. PREFECT_SERVER_API_HOST
: If you want to programmatically set the API host address within the container, though it seems redundant with the --host
option being used.
2. PREFECT_UI_URL
and PREFECT_API_URL
: These are typically used to inform other services or scripts within the container of the Prefect server's address. If your application or scripts rely on these variables to determine where to connect to the Prefect API, they should be set correctly.
If your scripts or application logic do not reference these environment variables, you can safely omit them. Otherwise, ensure they are set to values that reflect your actual network configuration.Jonathan Sakkos
03/23/2025, 7:04 AMPREFECT_UI_URL
can I set the IP of the machine instead of the container name for external access?Marvin
03/23/2025, 7:04 AMPREFECT_UI_URL
to the IP address of the host machine to facilitate external access. This will ensure that any part of your application or scripts that rely on this environment variable will use the correct address to reach the Prefect UI from outside the Docker network.
Here's how you can set it in your docker-compose.yaml
file:
yaml
services:
prefect:
build:
context: .
dockerfile: Dockerfile.prefect
ports:
- "4200:4200"
volumes:
- prefect_data:/root/.prefect
- ./src:/app/src
- ./data:/app/data
environment:
- PREFECT_SERVER_API_HOST=0.0.0.0
- PREFECT_UI_URL=http://<host_machine_ip>:4200/api
- PREFECT_API_URL=http://<host_machine_ip>:4200/api
restart: always
volumes:
prefect_data:
Replace <host_machine_ip>
with the actual IP address of your host machine. This will allow external clients to access the Prefect UI using this IP address.