docker / docker-py

A Python library for the Docker Engine API
https://docker-py.readthedocs.io/
Apache License 2.0
6.82k stars 1.67k forks source link

Cannot find contexts if Docker config file is not present #2622

Open Forinil opened 4 years ago

Forinil commented 4 years ago

Docker client version: 19.03.3 Docker daemon version: 19.03.12 Python version: 3.8.3 Docker SDK version: 4.2.2 docker-compose version: 1.26.0 OS: Windows 10 OS Version: 2004, build 19041.329

Issue: docker-py does not see configured contexts if config.json is not present

Explanation: I have installed Docker client and Docker Python SDK on my Windows 10 laptop to interact with Docker daemon installed on remove server running Ubuntu 18.04. I have created two contexts - one to connect to the daemon via SSH ('docker-ssh') and another to connect via TCP ('docker-tcp').

I verified that both contexts work using Docker CLI and that they are present in directory %USERPROFILE%\.docker\contexts.

Following that I attempted to start a simple service using docker-compose. I received error that given context was not found. I investigated this and realised that docker-compose loads contexts using ContextAPI.get_context(name) from docker-py, which eventually calls find_config_file() and then tries to locate contexts relative to Docker config file.

The problem is that there was no config.json or .dockercfg on my system. This causes docker-py to fail to locate my contexts and return an error.

I tested this by running the folowing code in Python REPL:

from docker.context import ContextAPI
ContextAPI.contexts()

and sure enough the response I got was:

[<Context: 'default'>]

Then I proceeded to create file %USERPROFILE%\.docker\config.json and reran ContextAPI.contexts() (without restarting REPL) and got:

[<Context: 'default'>, <Context: 'docker-tcp'>, <Context: 'docker-ssh'>]

I think method get_context_dir() from docker/context/config.py should be rewritten to return %USERPROFILE%\.docker\contexts on Windows, $HOME/.docker/contexts on Linux and $DOCKER_CONFIG/contexts if variable DOCKER_CONFIG is set.

pichlermarc commented 4 years ago

This just happened to me as well. I wrote a Dockerfile that contains all steps to reproduce it:

FROM docker:19.03.12-dind
RUN apk add python3 py-pip
RUN pip install docker==4.2.2
RUN docker context create example-context --docker "host=tcp://docker:2375"
RUN printf "import docker.context \nprint(docker.context.api.ContextAPI.contexts())" > example.py
CMD python3 example.py

It happens if docker context use has never been used before AND if no one created a config.json in the other locations that are used in find_config_file(). In this case find_config_file() will return None and the bug occurs.

As a workaround, I now check if docker.utils.config.find_config_file() returns None, and if true, then I create an empty one. This could definitely catch people off-guard though.