Mike B
08/08/2025, 11:34 PMMarvin
08/08/2025, 11:34 PMexplore_module_offerings
📊 Tools used:
• explore_module_offerings
(7x)
• get_latest_prefect_release_notes
(2x)
• research_prefect_topic
(2x)
• review_common_3x_gotchas
(2x)
• search_prefect_3x_docs
(6x)Marvin
08/08/2025, 11:36 PMMarvin
08/08/2025, 11:44 PMprefect work-pool get-default-base-job-template --type docker -f docker-pool.json
Edit docker-pool.json. Add your compose network and (if needed) explicit DNS settings. Example:
{
"job_configuration": {
"image": "{{ image }}",
"command": "{{ command }}",
"env": "{{ env }}",
"name": "{{ name }}",
"labels": "{{ labels }}",
"registry_credentials": "{{ registry_credentials }}",
"image_pull_policy": "{{ image_pull_policy }}",
"networks": ["prefect_net"], // <- your docker-compose network name
"network_mode": null, // usually leave null if you're using 'networks'
"volumes": "{{ volumes }}",
"auto_remove": true,
"stream_output": true,
"container_create_kwargs": {
"dns": ["10.0.0.2","10.0.0.3"], // corporate DNS servers
"dns_search": ["corp.local"], // your search domain(s)
"extra_hosts": ["sql-alias:10.0.0.100"] // optional host-to-IP pinning
}
},
"variables": { … }
}
Then apply it:
prefect work-pool update "YOUR_DOCKER_POOL" --base-job-template docker-pool.json
Notes:
- Prefer “networks” over “network_mode” when you want the container to join a user-defined network created by docker-compose. “network_mode” is more for “bridge/host/none/container:<id>”.
- You can also set these per-deployment instead of at the pool, via `job_variables`:
from prefect import flow
@flow
def my_flow():
...
my_flow.from_source(
source="<https://github.com/owner/repo>",
entrypoint="path/to/flow_file.py:my_flow"
).deploy(
name="dev",
work_pool_name="YOUR_DOCKER_POOL",
job_variables={
"networks": ["prefect_net"],
"container_create_kwargs": {
"dns": ["10.0.0.2","10.0.0.3"],
"dns_search": ["corp.local"],
"extra_hosts": ["sqlserver.corp.local:10.0.0.50"]
}
}
)
WSL2/Docker Desktop DNS gotchas (the cheery part)
- Docker’s embedded resolver (127.0.0.11) inside containers doesn’t always pick up Windows/WSL2/VPN DNS/search settings the way you expect. Explicitly setting dns
and dns_search
for the container is often the most reliable fix.
- If you prefer a global fix, set engine-wide DNS/search in Docker Desktop (Settings -> Docker Engine). Example:
{
"dns": [
"10.0.0.2",
"10.0.0.3"
],
"dns-search": [
"corp.local"
]
}
Be sure those DNS servers are reachable from WSL2/Docker (especially on VPN).
- Use FQDNs where possible (sqlserver.corp.local vs short names). Short-name resolution depends on search domains being present in the container’s resolv.conf.
About building images (docker-git style) and networking
- Runtime networking (the above) is separate from build-time networking. Docker build supports a limited set for --network
(default/none/host). You cannot attach a build to your compose network.
- If you need special build networking, pass it via Prefect’s DockerImage build kwargs:
```
from prefect.docker import DockerImage
image = DockerImage(
name="repo/your-image",
tag="dev",
dockerfile="Dockerfile",
build_kwargs={
"network_mode": "host" // or "default"
// ... buildargs, shmsize, etc.
}
)Marvin
08/08/2025, 11:44 PM- Build-time DNS is controlled by the daemon. If the build needs to resolve private hosts, set engine-level DNS (Docker Desktop) to your corporate DNS servers.
Quick diagnostic to prove it’s DNS
Create a tiny flow that runs in your Docker pool and checks resolution from inside a worker-launched container:
from prefect import flow
@flow
def dns_probe():
import socket, subprocess, os
print("resolv.conf:")
print(subprocess.check_output(["cat", "/etc/resolv.conf"]).decode())
for name in ["sqlserver.corp.local", "www.google.com"]:
try:
print(name, "->", socket.gethostbyname(name))
except Exception as e:
print(name, "failed:", e)
if name == "__main__":
dns_probe()
```
Deploy/run that against your Docker pool; if sqlserver.corp.local
fails but google works, your corporate DNS/search settings aren’t being applied to the flow’s container.
Docs you may actually want to open
- Workers and work pools
- Running flows with Docker workers
If you can share:
- Prefect version (2.x vs 3.x)
- Your pool name and compose network name
- The DNS servers/search suffix you expect
…I can sketch the exact JSON you should paste into your pool’s base job template. Yes, I know, thrilling.Mike B
08/12/2025, 8:54 PMMarvin
08/12/2025, 8:54 PMMarvin
08/12/2025, 8:57 PMprefect work-pool create/update
before starting the worker.
Note: I’m assuming “10.0.02” was meant to be “10.0.0.2”. If not, do say so before DNS gets… creative.
1) Create a base job template JSON (example: docker-pool.json)
This pins your compose network and DNS settings at the pool level so all flow containers launched by this pool inherit them.
{
"job_configuration": {
"command": "{{ command }}",
"env": "{{ env }}",
"labels": "{{ labels }}",
"name": "{{ name }}",
"image": "{{ image }}",
"registry_credentials": "{{ registry_credentials }}",
"image_pull_policy": "{{ image_pull_policy }}",
"auto_remove": "{{ auto_remove }}",
"volumes": "{{ volumes }}",
"stream_output": "{{ stream_output }}",
"mem_limit": "{{ mem_limit }}",
"memswap_limit": "{{ memswap_limit }}",
"privileged": "{{ privileged }}",
"networks": ["data_sync_default"],
"network_mode": null,
"container_create_kwargs": {
"dns": ["10.0.0.1", "10.0.0.2"],
"dns_search": ["DOMAIN1.local"]
}
},
"variables": {} // you can keep the default variables block from `prefect work-pool get-default-base-job-template --type docker` if you prefer
}
Tip: If you want to start from the full default and edit it, run:
prefect work-pool get-default-base-job-template --type docker --file docker-default.json
2) Wire it into docker-compose
Mount the JSON and update the pool at container start, then start the worker.
services:
prefect-worker:
image: prefecthq/prefect:3-latest
environment:
# Set these appropriately for Prefect Cloud or your server
PREFECT_API_URL: ${PREFECT_API_URL}
PREFECT_API_KEY: ${PREFECT_API_KEY}
volumes:
- ./docker-pool.json:/templates/docker-pool.json:ro
command: >
sh -c "
prefect work-pool create 'docker-pool' --type docker --base-job-template /templates/docker-pool.json --overwrite
|| prefect work-pool update 'docker-pool' --base-job-template /templates/docker-pool.json;
prefect worker start -p 'docker-pool'
"
# optional: also attach the worker itself to the compose network
networks:
- data_sync_default
networks:
data_sync_default:
external: true
Notes and gotchas:
- The Docker worker honors networks
, network_mode
, and container_create_kwargs
(which includes dns
and dns_search
) from the pool’s base job template.
- The network must exist on the Docker host where the worker runs. Marking the network as external: true
ensures the worker container can attach to your compose-created data_sync_default
.
- You can also pre-create/update the pool once outside of compose:
prefect work-pool create "docker-pool" --type docker --base-job-template docker-pool.json --overwrite
and then keep your worker’s command to just:
prefect worker start -p docker-pool
- If any deployments explicitly set their own job variables (e.g., networks), those will override the pool defaults.
If you want me to generate the full default template with your values spliced in, say the word and I’ll hand it back ready to mount.Mike B
08/12/2025, 9:01 PMMike B
08/12/2025, 9:01 PMMarvin
08/12/2025, 9:01 PMMarvin
08/12/2025, 9:02 PMprefect deploy --format yaml
)?
- A Python deployment snippet with flow.from_source(...).deploy(...)
?
- A worker job template (e.g., Docker/Kubernetes job_variables)?
- Something else entirely?
If it’s a Prefect 3.x deployment, send the values you want spliced in (or confirm you want me to infer sane defaults) for:
- deployment name
- flow entrypoint (repo_path/subdirmodule.pyflow_name)
- source repo URL and revision (branch/commit)
- work pool name
- job variables (e.g., image, env, cpu/mem, labels)
- parameters (dict)
- schedule (interval/cron/rrule)
- tags, description, version (optional)
You can paste them like this and I’ll generate the full template for you:
{
"name": "my-deployment",
"entrypoint": "flows/etl.py:etl_flow",
"source": {
"repo": "<https://github.com/acme/data-pipelines>",
"revision": "main" // or a commit SHA
},
"work_pool": {
"name": "docker-pool",
"job_variables": {
"image": "<http://ghcr.io/acme/etl:latest|ghcr.io/acme/etl:latest>",
"env": {"PREFECT_LOGGING_LEVEL": "INFO"},
"labels": ["prod"],
"cpu": "1",
"memory": "2Gi"
}
},
"parameters": {"start_date": "2025-01-01"},
"schedule": {
"cron": "0 * * * *", // or use {"interval": 3600}, or rrule
"timezone": "UTC"
},
"tags": ["etl", "prod"],
"description": "ETL deployment"
}
Tell me which template you want and drop in your values; I’ll spit out the full thing with everything wired up.Mike B
08/12/2025, 9:14 PMMarvin
08/12/2025, 9:15 PMMarvin
08/12/2025, 9:15 PMpath/to/file.py:flow_func
)
- source repo URL and revision (branch or commit)
- work pool name
- job variables (image, env, cpu/mem, labels, etc.)
- parameters (dict)
- schedule (cron/interval/rrule + timezone)
- tags, description, version (optional)
Reply with this JSON and I’ll generate the full template (YAML and Python) ready to deploy:
{
"name": "my-deployment",
"entrypoint": "flows/etl.py:etl_flow",
"source": {
"repo": "<https://github.com/acme/data-pipelines>",
"revision": "main"
},
"work_pool": {
"name": "docker-pool",
"job_variables": {
"image": "<http://ghcr.io/acme/etl:latest|ghcr.io/acme/etl:latest>",
"env": {
"PREFECT_LOGGING_LEVEL": "INFO"
},
"labels": [
"prod"
],
"cpu": "1",
"memory": "2Gi"
}
},
"parameters": {
"start_date": "2025-01-01"
},
"schedule": {
"cron": "0 * * * *",
"timezone": "UTC"
},
"tags": [
"etl",
"prod"
],
"description": "ETL deployment",
"version": "1.0.0"
}
If any deployment-level job_variables
are set, they will override the work pool defaults — yes, including things like networks
. Grimly consistent, at least.