<@ULVA73B9P> I have been testing locally through s...
# marvin-in-the-wild
v
@Marvin I have been testing locally through serve() which spins up a docker container for one of my tasks, and all of that works successfully. However now I want to do the same through a deployment, and prefect managed work pool. I think this means using docker host block, so I can connect to the server, and then fire up a docker container. How do I do this? And one additional concern: I don't want to connect directly and open up a port. I'd rather do this through a VPN like tailscale for security reasons
m
Got it. To create a deployment that uses Docker and connect through a Prefect managed work pool, you'll need to: 1. Create a DockerBlock to specify your Docker configuration. 2. Define your deployment to use this DockerBlock. 3. Ensure your setup is secure, using something like Tailscale for VPN connections. ### Step-by-Step Instructions: #### 1. Create a DockerBlock First, you need to define your DockerBlock. This will have your Docker configuration.
Copy code
python
from prefect.infrastructure.docker import DockerContainer

docker_block = DockerContainer(
    image="your-docker-image",
    auto_remove=True,
    stream_output=True
).save("my-docker-block")
Replace
"your-docker-image"
with the appropriate image name. #### 2. Define Your Deployment Next, define your deployment with the DockerBlock and deploy it. Here's an example:
Copy code
python
from prefect.deployments import Deployment
from prefect.infrastructure.docker import DockerContainer

docker_block = DockerContainer.load("my-docker-block")

deployment = Deployment.build_from_flow(
    flow=my_flow,
    name="my-docker-deployment",
    infrastructure=docker_block,
)

deployment.apply()
Replace
my_flow
with your flow. #### 3. Use Tailscale for Secure Connections For secure connections, use Tailscale or any VPN solution that you prefer. Here’s a basic outline: 1. Install Tailscale on your machine and the server where the Docker containers will be run. 2. Authenticate Tailscale on both ends and ensure they are connected via Tailscale. 3. Configure Docker to use the Tailscale IP addresses instead of exposing ports directly. #### Tailscale Setup On your server and local machine: - Install Tailscale: Follow Tailscale's installation guide. - Authenticate and Connect: Use
tailscale up
to authenticate and connect. #### Example run command with Tailscale IP If your Tailscale IP is
100.x.x.x
, ensure your Docker configuration and Prefect Block are set to this IP without opening ports publicly. #### Links for More Information: Here are some useful links for deep dive into the setup steps: - Prefect Documentation on Docker Infrastructure - Tailscale Documentation Let's fetch some more specific Prefect documentation and example code for the DockerBlock setup to ensure you have the latest and accurate information. ### Resources and Example Code #### 1. Docker Block and Deployment You can create a DockerBlock to manage credentials for interacting with a Docker registry as shown in this documentation. Here is an example to setup DockerBlock and using it in a deployment: ##### Docker Block Setup:
Copy code
python
from prefect.infrastructure.docker import DockerContainer

docker_block = DockerContainer(
    image="your-docker-image",
    auto_remove=True,
    stream_output=True
).save("my-docker-block")
You may also need to include registry credentials as shown below:
Copy code
python
from prefect_docker import DockerHost, DockerRegistryCredentials

docker_host = DockerHost()
docker_registry_credentials = DockerRegistryCredentials(
    username="my_username",
    password="my_password",
    registry_url="<http://registry.hub.docker.com|registry.hub.docker.com>",
)
with docker_host.get_client() as client:
    docker_registry_credentials.login(client)
#### 2. Creating Deployment: Use the DockerBlock in a deployment:
Copy code
python
from prefect.deployments import Deployment
from prefect.infrastructure.docker import DockerContainer

docker_block = DockerContainer.load("my-docker-block")

deployment = Deployment.build_from_flow(
    flow=my_flow,
    name="my-docker-deployment",
    infrastructure=docker_block,
)

deployment.apply()
For detailed instructions on deploying, refer to Prefect Deployment Guide. ### 3. Using Tailscale for Secure Connections - Install Tailscale: Follow Tailscale's installation guide. - Authenticate and Connect: Use
tailscale up
to authenticate and connect. You'll need to set up your Docker connections to use Tailscale's IP addresses ensuring that you're not exposing ports publicly. ### Additional Information: - Example flow with deployment using Docker infrastructure can be referenced from this example. For those who want to dive deeper, please explore the links provided in each section for the most detailed and up-to-date information. Happy securing and deploying!
v
@Marvin I'm getting a long error when trying to launch a countainer from my local worker I have this pseudo code: import ast from prefect import flow, task from prefect.infrastructure.container import DockerContainer # from prefect_docker.containers import get_docker_container_logs, remove_docker_container from prefect.artifacts import create_markdown_artifact from prefect.runner.storage import GitRepository from prefect.blocks.system import Secret @flow(name="Jora Job ETL Flow") def start_flow(): run_job_parser() # run_sentence_splitter() test_task() @task(name="Parse Jora Jobs", retries=0, log_prints=True) def run_job_parser(): docker_container_block = DockerContainer.load("mediariot-docker-parser") container_result = docker_container_block.run() return {} @task(name="Parse Jobs Next", retries=0) def test_task(): print("This is a test task") if name == "__main__": start_flow.from_source( source=GitRepository( url="https://github.com/rubinghv/jobify.git", branch="dev", credentials={ "access_token": Secret.load("github-access-token") } ), entrypoint="flows/job_etl.py:start_flow" ).deploy( name="mediariot-deployment", work_pool_name="mediariot-docker-pool", ) Then a service running a worker on my own server: [Unit] Description=Prefect docker worker [Service] User=vcr WorkingDirectory=/home # based on "which prefect" command in terminal ExecStart=/usr/local/bin/prefect worker start --pool mediariot-docker-pool Restart=always [Install] WantedBy=multi-user.target This all works fine. However I get this error when I try to run the deployment: Encountered exception during execution: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 789, in urlopen response = self._make_request( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 495, in _make_request conn.request( File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 398, in request self.endheaders() File "/usr/local/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/local/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/usr/local/lib/python3.10/http/client.py", line 976, in send self.connect() File "/usr/local/lib/python3.10/site-packages/docker/transport/unixconn.py", line 26, in connect sock.connect(self.unix_socket) FileNotFoundError: [Errno 2] No such file or directory During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 667, in send resp = conn.urlopen( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 843, in urlopen retries = retries.increment( File "/usr/local/lib/python3.10/site-packages/urllib3/util/retry.py", line 474, in increment raise reraise(type(error), error, _stacktrace) File "/usr/local/lib/python3.10/site-packages/urllib3/util/util.py", line 38, in reraise raise value.with_traceback(tb) File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 789, in urlopen response = self._make_request( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 495, in _make_request conn.request( File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 398, in request self.endheaders() File "/usr/local/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/local/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/usr/local/lib/python3.10/http/client.py", line 976, in send self.connect() File "/usr/local/lib/python3.10/site-packages/docker/transport/unixconn.py", line 26, in connect sock.connect(self.unix_socket) urllib3.exceptions.ProtocolError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 223, in _retrieve_server_version return self.version(api_version=False)["ApiVersion"] File "/usr/local/lib/python3.10/site-packages/docker/api/daemon.py", line 181, in version return self._result(self._get(url), json=True) File "/usr/local/lib/python3.10/site-packages/docker/utils/decorators.py", line 44, in inner return f(self, *args, **kwargs) File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 246, in _get return self.get(url, **self._set_request_timeout(kwargs)) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 602, in get return self.request("GET", url, **kwargs) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 589, in request resp = self.send(prep, **send_kwargs) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 703, in send r = adapter.send(request, **kwargs) File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 682, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 738, in _get_client docker_client = docker.from_env() File "/usr/local/lib/python3.10/site-packages/docker/client.py", line 94, in from_env return cls( File "/usr/local/lib/python3.10/site-packages/docker/client.py", line 45, in init self.api = APIClient(*args, **kwargs) File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 207, in init self._version = self._retrieve_server_version() File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 230, in _retrieve_server_version raise DockerException( docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/prefect/engine.py", line 2146, in orchestrate_task_run result = await call.aresult() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 327, in aresult return await asyncio.wrap_future(self.future) File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 352, in _run_sync result = self.fn(*self.args, **self.kwargs) File "/opt/prefect/jobify-dev/flows/job_etl.py", line 19, in run_job_parser container_result = docker_container_block.run() File "/usr/local/lib/python3.10/site-packages/prefect/events/instrument.py", line 77, in inner raise exc File "/usr/local/lib/python3.10/site-packages/prefect/events/instrument.py", line 74, in inner return function(self, *args, **kwargs) File "/usr/local/lib/python3.10/site-packages/prefect/utilities/asyncutils.py", line 311, in coroutine_wrapper return call() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 432, in call return self.result() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 318, in result return self.future.result(timeout=timeout) File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 179, in result return self.__get_result() File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result raise self._exception File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 389, in _run_async result = await coro File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 359, in run container = await run_sync_in_worker_thread(self._create_and_start_container) File "/usr/local/lib/python3.10/site-packages/prefect/utilities/asyncutils.py", line 138, in run_sync_in_worker_thread return await anyio.to_thread.run_sync( File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync return await get_async_backend().run_sync_in_worker_thread( File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2177, in run_sync_in_worker_thread return await future File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 859, in run result = context.run(func, *args) File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 513, in _create_and_start_container docker_client = self._get_client() File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 741, in _get_client raise RuntimeError("Could not connect to Docker.") from exc RuntimeError: Could not connect to Docker. 034024 PM Parse Jora Jobs-0 prefect.task_runs Finished in state Failed('Task run encountered an exception RuntimeError: Could not connect to Docker.')
m
Your message was too long by 2167 tokens - please shorten it and try again. For reference, here's your message at the allowed limit:
I'm getting a long error when trying to launch a countainer from my local worker
I have this pseudo code: import ast from prefect import flow, task from prefect.infrastructure.container import DockerContainer # from prefect_docker.containers import get_docker_container_logs, remove_docker_container from prefect.artifacts import create_markdown_artifact from prefect.runner.storage import GitRepository from prefect.blocks.system import Secret @flow(name="Jora Job ETL Flow") def start_flow(): run_job_parser() # run_sentence_splitter() test_task() @task(name="Parse Jora Jobs", retries=0, log_prints=True) def run_job_parser(): docker_container_block = DockerContainer.load("mediariot-docker-parser") container_result = docker_container_block.run() return {} @task(name="Parse Jobs Next", retries=0) def test_task(): print("This is a test task") if name == "__main__": start_flow.from_source( source=GitRepository( url="https://github.com/rubinghv/jobify.git", branch="dev", credentials={ "access_token": Secret.load("github-access-token") } ), entrypoint="flows/job_etl.py:start_flow" ).deploy( name="mediariot-deployment", work_pool_name="mediariot-docker-pool", ) Then a service running a worker on my own server
v
@Marvin this error: Encountered exception during execution: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 789, in urlopen response = self._make_request( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 495, in _make_request conn.request( File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 398, in request self.endheaders() File "/usr/local/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/local/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/usr/local/lib/python3.10/http/client.py", line 976, in send self.connect() File "/usr/local/lib/python3.10/site-packages/docker/transport/unixconn.py", line 26, in connect sock.connect(self.unix_socket) FileNotFoundError: [Errno 2] No such file or directory During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 667, in send resp = conn.urlopen( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 843, in urlopen retries = retries.increment( File "/usr/local/lib/python3.10/site-packages/urllib3/util/retry.py", line 474, in increment raise reraise(type(error), error, _stacktrace) File "/usr/local/lib/python3.10/site-packages/urllib3/util/util.py", line 38, in reraise raise value.with_traceback(tb) File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 789, in urlopen response = self._make_request( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 495, in _make_request conn.request( File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 398, in request self.endheaders() File "/usr/local/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/local/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/usr/local/lib/python3.10/http/client.py", line 976, in send self.connect() File "/usr/local/lib/python3.10/site-packages/docker/transport/unixconn.py", line 26, in connect sock.connect(self.unix_socket) urllib3.exceptions.ProtocolError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 223, in _retrieve_server_version return self.version(api_version=False)["ApiVersion"] File "/usr/local/lib/python3.10/site-packages/docker/api/daemon.py", line 181, in version return self._result(self._get(url), json=True) File "/usr/local/lib/python3.10/site-packages/docker/utils/decorators.py", line 44, in inner return f(self, *args, **kwargs) File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 246, in _get return self.get(url, **self._set_request_timeout(kwargs)) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 602, in get return self.request("GET", url, **kwargs) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 589, in request resp = self.send(prep, **send_kwargs) File "/usr/local/lib/python3.10/site-packages/requests/sessions.py", line 703, in send r = adapter.send(request, **kwargs) File "/usr/local/lib/python3.10/site-packages/requests/adapters.py", line 682, in send raise ConnectionError(err, request=request) requests.exceptions.ConnectionError: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 738, in _get_client docker_client = docker.from_env() File "/usr/local/lib/python3.10/site-packages/docker/client.py", line 94, in from_env return cls( File "/usr/local/lib/python3.10/site-packages/docker/client.py", line 45, in init self.api = APIClient(*args, **kwargs) File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 207, in init self._version = self._retrieve_server_version() File "/usr/local/lib/python3.10/site-packages/docker/api/client.py", line 230, in _retrieve_server_version raise DockerException( docker.errors.DockerException: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory')) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/prefect/engine.py", line 2146, in orchestrate_task_run result = await call.aresult() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 327, in aresult return await asyncio.wrap_future(self.future) File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 352, in _run_sync result = self.fn(*self.args, **self.kwargs) File "/opt/prefect/jobify-dev/flows/job_etl.py", line 19, in run_job_parser container_result = docker_container_block.run() File "/usr/local/lib/python3.10/site-packages/prefect/events/instrument.py", line 77, in inner raise exc File "/usr/local/lib/python3.10/site-packages/prefect/events/instrument.py", line 74, in inner return function(self, *args, **kwargs) File "/usr/local/lib/python3.10/site-packages/prefect/utilities/asyncutils.py", line 311, in coroutine_wrapper return call() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 432, in call return self.result() File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 318, in result return self.future.result(timeout=timeout) File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 179, in result return self.__get_result() File "/usr/local/lib/python3.10/concurrent/futures/_base.py", line 403, in __get_result raise self._exception File "/usr/local/lib/python3.10/site-packages/prefect/_internal/concurrency/calls.py", line 389, in _run_async result = await coro File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 359, in run container = await run_sync_in_worker_thread(self._create_and_start_container) File "/usr/local/lib/python3.10/site-packages/prefect/utilities/asyncutils.py", line 138, in run_sync_in_worker_thread return await anyio.to_thread.run_sync( File "/usr/local/lib/python3.10/site-packages/anyio/to_thread.py", line 56, in run_sync return await get_async_backend().run_sync_in_worker_thread( File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 2177, in run_sync_in_worker_thread return await future File "/usr/local/lib/python3.10/site-packages/anyio/_backends/_asyncio.py", line 859, in run result = context.run(func, *args) File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 513, in _create_and_start_container docker_client = self._get_client() File "/usr/local/lib/python3.10/site-packages/prefect/infrastructure/container.py", line 741, in _get_client raise RuntimeError("Could not connect to Docker.") from exc RuntimeError: Could not connect to Docker.
m
Your message was too long by 1746 tokens - please shorten it and try again. For reference, here's your message at the allowed limit:
this error: Encountered exception during execution:
Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 789, in urlopen response = self._make_request( File "/usr/local/lib/python3.10/site-packages/urllib3/connectionpool.py", line 495, in _make_request conn.request( File "/usr/local/lib/python3.10/site-packages/urllib3/connection.py", line 398, in request self.endheaders() File "/usr/local/lib/python3.10/http/client.py", line 1278, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/usr/local/lib/python3.10/http/client.py", line 1038, in _send_output self.send(msg) File "/usr/local/lib/python3.10/http/client.py", line 976, in send self.connect() File "/usr/local/lib/python3.10/site-packages/docker/transport/unixconn.py", line 26, in connect sock.connect(self.unix_socket) FileNotFoundError: [Errno 2] No such file or directory During handling of the above exception, another exception occurred: Traceback (most recent call last): File "/usr/local/lib/python3.10/site-packages/requests