https://prefect.io logo
Title
j

Jawaad Mahmood

12/22/2021, 7:08 PM
Hello! I'm stuck on something that should be simple, but can't find answer in channel history or docs! I am using prefect.storage.Docker for flow storage inside Docker image. I would like to push this image up to Dockerhub. When I try that using the code below, I get "InterruptedError: unauthorized: authentication required" error. I am able to successfully login to Dockerhub using Docker SDK, but not sure how to pass this authenticated client to prefect.storage.Docker. And I am not sure how I authenticate within prefect.storage.Docker. As suggested by the docs, I am running the Docker daemon locally, and logged into docker in the terminal both of which are configured to push up to the repository. How can I fix? Thanks!
from prefect import task, Flow
from prefect.executors import LocalExecutor
from prefect.run_configs import DockerRun
from prefect.storage import Docker
import docker

with Flow("some_flow") as flow:
    do_something

    docker_client = docker.DockerClient()
    docker_client.login(username=<env_user>,password=<env_pass>)

    flow.storage = Docker(
        registry_url='<http://registry.hub.docker.com/repository/docker/<user>/<repo>|registry.hub.docker.com/repository/docker/<user>/<repo>>'
        ,image_name='<some_flow>'
        ,files={
            <origin path>:<dest path>
        }
        ,python_dependencies = ['pandas','numpy','prefect']
        ,env_vars={
            "PYTHONPATH": "$PYTHONPATH:assets/:root/:data/:image"
        }
        ,base_image='python:3.7.3'
    )

    flow.run_config = DockerRun(labels=['my-label']
                                )
    flow.executor = LocalExecutor()
    flow.register(project_name="some_project")
a

Anna Geller

12/22/2021, 7:36 PM
There are a couple of issues here: 1. Did you authenticate with your registry before you tried to register your flow? Usually you should do something like “docker login -u username -p password” in the terminal rather than doing it within your flow 2. Starting from storage your indentation seems to be off - you can either do one of those:
with Flow("some_flow") as flow:
    do_something

    docker_client = docker.DockerClient()
    docker_client.login(username=<env_user>,password=<env_pass>)

flow.storage = Docker(
    registry_url='<http://registry.hub.docker.com/repository/docker/<user>/<repo>|registry.hub.docker.com/repository/docker/<user>/<repo>>'
    ,image_name='<some_flow>'
    ,files={
           <origin path>:<dest path>
}
,python_dependencies = ['pandas','numpy','prefect']
,env_vars={
              "PYTHONPATH": "$PYTHONPATH:assets/:root/:data/:image"
          }
,base_image='python:3.7.3'
)

flow.run_config = DockerRun(labels=['my-label']
                            )
flow.executor = LocalExecutor()
flow.register(project_name="some_project")
or:
with Flow(
    "some_flow",
    run_config=DockerRun(labels=["my-label"]),
    storage=Docker(
        registry_url="<http://registry.hub.docker.com/repository/docker/<user>/<repo>|registry.hub.docker.com/repository/docker/<user>/<repo>>",
        image_name="<some_flow>",
        python_dependencies=["pandas", "numpy", "prefect"],
        env_vars={"PYTHONPATH": "$PYTHONPATH:assets/:root/:data/:image"},
        base_image="python:3.7.3",
    ),
) as flow:
    pass
3. Lastly, within your Flow constructor, you can only construct a DAG, i.e. you can’t have any non-task code. Within the “with Flow” block you should only be calling tasks, so you can remove the lines below from your Flow block and replace that with login via terminal in the same terminal session in which you register your flow:
docker_client = docker.DockerClient()
   docker_client.login(username=<env_user>,password=<env_pass>)
j

Jawaad Mahmood

12/22/2021, 8:11 PM
Anna, Thanks for the quick reply. Here's what I know: 1. Yes, I authenticated with my registry with "docker login -u <user> -p <password>" before running "python flow.py" in the same terminal. I received a "Login Succeeded" after authenticating. 2. My sincere apologies, this was my error in copying/pasting while sanitizing the code 3. Same here, I had the docker_client lines commented out in my actual code (was just testing to see if it would log in) Tried "docker login" again to doublecheck, but still getting the "authentication required" 😕
a

Anna Geller

12/22/2021, 8:16 PM
can you try to build and push the image to registry without Prefect and check whether this works?
👀 1
j

Jawaad Mahmood

12/23/2021, 1:06 AM
Thanks for that suggestion -- it sent me down a rabbit hole, but ultimately realized that it worked if I used the repository name as "image_name" and the image name as "image_tag"; working code looks as follows (and fixed the mistakes you highlighted above):
from prefect import task, Flow
from prefect.executors import LocalExecutor
from prefect.run_configs import DockerRun
from prefect.storage import Docker
import docker

with Flow("some_flow") as flow:
    do_something

flow.storage = Docker(
        registry_url='<user>'
        ,image_name='<repo>'
        ,image_tag='<some_flow>'
        ,files={
            <origin path>:<dest path>
        }
        ,python_dependencies = ['pandas','numpy','prefect']
        ,env_vars={
            "PYTHONPATH": "$PYTHONPATH:assets/:root/:data/:image"
        }
        ,base_image='python:3.7.3'
    )

    flow.run_config = DockerRun(labels=['my-label']
                                )
    flow.executor = LocalExecutor()
    flow.register(project_name="some_project")
a

Anna Geller

12/23/2021, 10:46 AM
nice!