|
| 1 | +# Docker example |
| 2 | + |
| 3 | +#### Work pool |
| 4 | + |
| 5 | +Prefect is able to run flows inside ephemeral docker containers. |
| 6 | +This requires that a Prefect work pool be created with the `docker` type: |
| 7 | + |
| 8 | +```shell |
| 9 | +prefect work-pool create --type docker my-pool |
| 10 | +``` |
| 11 | + |
| 12 | +Start a worker that consumes work from this newly-created pool |
| 13 | + |
| 14 | +??? note "Install prefect-docker" |
| 15 | + |
| 16 | + In order to start a Prefect worker that executes flow runs in docker containers, you need to have the |
| 17 | + [prefect-docker](https://pypi.org/project/prefect-docker/) package installed. |
| 18 | + |
| 19 | + Add it with: |
| 20 | + |
| 21 | + === "uv" |
| 22 | + |
| 23 | + ```shell |
| 24 | + uv add prefect-docker |
| 25 | + ``` |
| 26 | + |
| 27 | + === "pip" |
| 28 | + |
| 29 | + ```shell |
| 30 | + pip install prefect-docker |
| 31 | + ``` |
| 32 | + |
| 33 | +```shell |
| 34 | +prefect worker start --pool my-pool |
| 35 | +``` |
| 36 | + |
| 37 | +#### Flow deployment |
| 38 | + |
| 39 | +Write your processing flow, for example: |
| 40 | + |
| 41 | +```python |
| 42 | +from prefect import flow, task |
| 43 | + |
| 44 | + |
| 45 | +@flow(log_prints=True) |
| 46 | +def simple_flow( |
| 47 | + processor_id: str, |
| 48 | + pygeoapi_job_id: str, # noqa, this is used for naming flow_runs |
| 49 | + inputs: dict, |
| 50 | + outputs: dict | None = None, |
| 51 | +) -> None: |
| 52 | + print(f"Hi from simple_flow locals: {locals()}") |
| 53 | + generate_greeting(name=inputs["name"], message=inputs.get("message")) |
| 54 | + |
| 55 | + |
| 56 | +@task( |
| 57 | + persist_result=True, |
| 58 | + result_storage_key="{parameters[pygeoapi_job_id]}.pickle", |
| 59 | + log_prints=True, |
| 60 | +) |
| 61 | +def generate_greeting(name: str, message: str | None = None) -> str: |
| 62 | + result = f"Hi {name}!" |
| 63 | + if message: |
| 64 | + result += f" {message}" |
| 65 | + return result |
| 66 | + |
| 67 | + |
| 68 | +if __name__ == "__main__": |
| 69 | + simple_flow.deploy( |
| 70 | + name="first-deployment", |
| 71 | + work_pool_name="my-pool", |
| 72 | + image="pygeoapi-prefect/flows/simple-flow", |
| 73 | + push=False |
| 74 | + ) |
| 75 | +``` |
| 76 | + |
| 77 | +Deploy it: |
| 78 | + |
| 79 | +```shell |
| 80 | +python simple_flow.py |
| 81 | +``` |
| 82 | + |
| 83 | +This creates a docker image named `pygeoapi-prefect/flows/simple-flow:{date}` with the flow contents and registers |
| 84 | +a deployment named `simple-flow/first-deployment` with the Prefect server. Because our `simple_flow.deploy()` call |
| 85 | +includes `push=False`, this docker image lives in the local filesystem only. |
| 86 | + |
| 87 | +You can check the Prefect server UI in order to verify that your deployment is now registered. You can also used the |
| 88 | +Prefect API: |
| 89 | + |
| 90 | +```shell |
| 91 | +prefect deployment ls |
| 92 | +``` |
| 93 | + |
| 94 | + |
| 95 | +#### Pygeoapi processor configuration |
| 96 | + |
| 97 | +Configure pygeoapi with this newly deployed flow: |
| 98 | + |
| 99 | +```yaml |
| 100 | +# snippet of pygeoapi configuration file |
| 101 | +# (the rest of the configuration has been omitted for brevity) |
| 102 | +resources: |
| 103 | + simple-flow: |
| 104 | + type: process |
| 105 | + processor: |
| 106 | + prefect: |
| 107 | + deployment: |
| 108 | + name: simple-flow/first-deployment |
| 109 | + result_storage_key_template: "{parameters[pygeoapi_job_id]}.pickle" |
| 110 | + metadata: |
| 111 | + version: 0.0.1 |
| 112 | + title: Hi world prefect example |
| 113 | + description: > |
| 114 | + An example processor that is powered by a Prefect deployment. |
| 115 | + inputs: |
| 116 | + name: |
| 117 | + description: Some name you think is cool. It will be used to greet you |
| 118 | + schema: |
| 119 | + type: string |
| 120 | + message: |
| 121 | + title: My message |
| 122 | + description: An optional additional message to be echoed |
| 123 | + schema: |
| 124 | + type: string |
| 125 | + minOccurs: 0 |
| 126 | + outputs: |
| 127 | + result: |
| 128 | + schema: |
| 129 | + type: string |
| 130 | + contentMediaType: text/plain |
| 131 | + example: |
| 132 | + inputs: |
| 133 | + name: Joe |
| 134 | +``` |
| 135 | +
|
| 136 | +Finally, start pygeoapi: |
| 137 | +
|
| 138 | +```shell |
| 139 | +pygeoapi serve |
| 140 | +``` |
| 141 | + |
| 142 | + |
| 143 | +#### Process execution via pygeoapi |
| 144 | + |
| 145 | +Check that pygeoapi recognizes our Prefect flow: |
| 146 | + |
| 147 | +```shell |
| 148 | +http localhost:5000/processes/simple-flow |
| 149 | +``` |
| 150 | + |
| 151 | +The response should include the description of the `simple-flow` processor and also a link for executing it. Execution |
| 152 | +can be requested with: |
| 153 | + |
| 154 | +```shell |
| 155 | +curl \ |
| 156 | + -sSi \ |
| 157 | + -X POST "http://localhost:5000/processes/simple-flow/execution" \ |
| 158 | + -H "Content-Type: application/json" \ |
| 159 | + -d '{"inputs": {"name": "Joe"}}' |
| 160 | +``` |
| 161 | + |
| 162 | +The response: |
| 163 | + |
| 164 | +```shell |
| 165 | +HTTP/1.1 201 CREATED |
| 166 | +Content-Type: None |
| 167 | +Content-Language: en-US |
| 168 | +Preference-Applied: respond-async |
| 169 | +Location: http://localhost:5000/jobs/af101d53-7dcc-4882-a15b-a85fd4381153 |
| 170 | + |
| 171 | +{"jobID":"af101d53-7dcc-4882-a15b-a85fd4381153","type":"process","status":"accepted"} |
| 172 | +``` |
0 commit comments