Jackson Freitas
09/15/2025, 7:06 PMMarvin
09/15/2025, 7:07 PMMarvin
09/15/2025, 7:22 PMlocal-pool
doesn’t exist yet.
- I also see angle brackets <...>
around URLs in your env vars — if those are literally present, they’ll break connections.
What to change
1) Remove angle brackets from URLs
- Use plain strings like postgresql+asyncpg://...
and http://...
, not <postgresql+asyncpg://...>
or <http://...>
.
2) Tell the UI the correct external API URL
- Keep the server binding on 0.0.0.0
for Docker, but set the API URL that the UI should use from your browser.
- Add PREFECT_API_URL: <http://localhost:4200/api>
to the prefect-server
service. This will make the UI talk to <http://localhost:4200/api>
instead of 0.0.0.0
.
3) Make the worker talk to the server over the compose network
- Keep PREFECT_API_URL: <http://prefect-server:4200/api>
in the worker (no angle brackets).
4) Ensure the worker starts after the API is ready and that a work pool exists
- Add a healthcheck to prefect-server
and make the worker depend on it being healthy.
- Create the work pool local-pool
with type process
once the API is up.
Here’s a tightened compose snippet you can try
services:
postgres:
image: postgres:14
environment:
POSTGRES_USER: prefect
POSTGRES_PASSWORD: prefect
POSTGRES_DB: prefect
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U prefect"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7
volumes:
- redis_data:/data
healthcheck:
test: ["CMD-SHELL", "redis-cli ping"]
interval: 5s
timeout: 5s
retries: 5
prefect-server:
image: prefecthq/prefect:3-latest
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: <postgresql+asyncpg://prefect:prefect@postgres:5432/prefect>
PREFECT_SERVER_API_HOST: 0.0.0.0
PREFECT_API_URL: <http://localhost:4200/api>
PREFECT_MESSAGING_BROKER: prefect_redis.messaging
PREFECT_MESSAGING_CACHE: prefect_redis.messaging
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_REDIS_MESSAGING_DB: 0
command: prefect server start --no-services
ports:
- "4200:4200"
healthcheck:
test: ["CMD", "curl", "-sf", "<http://localhost:4200/api/health>"]
interval: 5s
timeout: 5s
retries: 10
prefect-services:
image: prefecthq/prefect:3-latest
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
environment:
PREFECT_API_DATABASE_CONNECTION_URL: <postgresql+asyncpg://prefect:prefect@postgres:5432/prefect>
PREFECT_MESSAGING_BROKER: prefect_redis.messaging
PREFECT_MESSAGING_CACHE: prefect_redis.messaging
PREFECT_REDIS_MESSAGING_HOST: redis
PREFECT_REDIS_MESSAGING_PORT: 6379
PREFECT_REDIS_MESSAGING_DB: 0
command: prefect server services start
prefect-worker:
image: prefecthq/prefect:3-latest
depends_on:
prefect-server:
condition: service_healthy
environment:
PREFECT_API_URL: <http://prefect-server:4200/api>
command: prefect worker start --pool local-pool
restart: unless-stopped
volumes:
postgres_data:
redis_data:
Create the work pool (run once)
- After the API is healthy, create the pool the worker will poll:
docker compose exec prefect-server prefect work-pool create local-pool --type process
Quick checksMarvin
09/15/2025, 7:22 PMcurl -sf <http://localhost:4200/api/health>
should return healthy JSON.
- From the worker container: docker compose exec prefect-worker curl -sf <http://prefect-server:4200/api/health>
- Inside any container: prefect config view
should show PREFECT_API_URL
as you set it.
References
- Docker compose guide and self-hosted server notes: Prefect 3: Self-hosted with Docker Compose and Prefect 3: Server in Docker
If you try the above and still see the UI error, let me know:
- the exact URL you open in the browser
- the output of curl -sf <http://localhost:4200/api/health>
- the first 50 lines of logs from prefect-server
and prefect-worker
(docker compose logs --no-color --tail=50 <service>
)Jackson Freitas
09/16/2025, 2:37 PMFile "/usr/local/lib/python3.12/site-packages/prefect/client/orchestration/base.py", line 53, in request
return await self._client.send(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/prefect/client/base.py", line 348, in send
response = await self._send_with_retry(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/prefect/client/base.py", line 268, in _send_with_retry
response = await send(request, *send_args, **send_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 1629, in send
response = await self._send_handling_auth(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 1657, in _send_handling_auth
response = await self._send_handling_redirects(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 1694, in _send_handling_redirects
response = await self._send_single_request(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/httpx/_client.py", line 1730, in _send_single_request
response = await transport.handle_async_request(request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/httpx/_transports/default.py", line 393, in handle_async_request
with map_httpcore_exceptions():
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/contextlib.py", line 158, in __exit__
self.gen.throw(value)
File "/usr/local/lib/python3.12/site-packages/httpx/_transports/default.py", line 118, in map_httpcore_exceptions
raise mapped_exc(message) from exc
httpx.ConnectError: All connection attempts failed
I solved running prefect server update, see: docker compose exec prefect-server prefect server database upgrade
After the error on interface keep with message: Can't connect to Server API at http://0.0.0.0:4200/api. Check that it's accessible from your machine.
I entry inside prefect-container-deploy-prefect-worker-1 and executed the command prefect config view:
And I have:
🚀 you are connected to:
http://prefect-server:4200
PREFECT_PROFILE='ephemeral'
PREFECT_API_URL='http://prefect-server:4200/api' (from env)
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true' (from profile)
I made a curl command: curl http://prefect-server:4200/api/health inside prefect-container-deploy-prefect-worker-1 container and the response was "true".
After made docker compose up -d, all the containers be running, but the message error keep on interfaceMarvin
09/16/2025, 2:37 PMMarvin
09/16/2025, 2:40 PMcurl .../health
.
- The browser UI, though, is trying to talk to <http://0.0.0.0:4200/api>
, which is a bind address and not reachable from your machine. That value comes from the server’s UI settings.
Fix
You need to tell the Prefect UI which externally reachable API URL to use by setting PREFECT_UI_API_URL
on the server container to the exact URL you use in your browser (usually <http://localhost:4200/api>
on your dev machine, or your host/IP/domain in other setups).
Example docker-compose snippet
Update your prefect-server service to include these env vars (adjust host as needed):
services:
prefect-server:
image: prefecthq/prefect:3-latest
command: prefect server start
ports:
- "4200:4200"
environment:
# What the UI should use to reach the API from your browser
PREFECT_UI_API_URL: "<http://localhost:4200/api>"
# Optional but recommended for correct link generation in emails/UI
PREFECT_UI_URL: "<http://localhost:4200>"
Then restart:
docker compose up -d --force-recreate
Verify
- From your browser: open http://localhost:4200/ui-settings and check that api_url
matches <http://localhost:4200/api>
.
- From your machine: curl <http://localhost:4200/api/health>
should return true
.
- Hard refresh the UI (clear cache or Ctrl/Cmd+Shift+R).
Notes
- Inside Docker, your worker should keep using PREFECT_API_URL=<http://prefect-server:4200/api>
(the service name). The browser UI must use a host that your machine can reach (e.g., localhost
, your host IP, or a domain).
- If you’re accessing the UI from another machine or behind a reverse proxy, set PREFECT_UI_API_URL
to that external address (e.g., <http://your-host:4200/api>
or your proxy path like `https://example.com/prefect/api`).
If you can share your docker-compose.yml (the prefect-server
service, especially ports and environment), I can tailor the exact values.
References
- UI and security settings: Prefect 3 Security & UI settings
- Settings models reference (UI/API): Prefect 3 Settings models