docker / docker-py

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

Legacy config file format #1930

Open c4tz opened 6 years ago

c4tz commented 6 years ago

Hey there,

I recently noticed a bad/wrong behaviour of this library when using docker-compose pull.

docker-compose.yml:

version: '2'
services:

  test:
    image: eu.gcr.io/some/private/image:latest

If I authenticate myself using gcloud docker login && gcloud docker -a, I cannot pull the image with docker-compose. When I log in with docker login -u _token -p $(gcloud auth print-access-token) eu.gcr.io, it works.

Furthermore, I can pull the exact same image doing docker pull eu.gcr.io/some/private/image:latest after logging in with gcloud docker login && gcloud docker -a. (This is why I post here instead of creating an issue in google-cloud-sdk)

I looked at the source code of docker, gcloud and docker-py and found out the following:

  1. Docker itself is fully backwards compatible and CAN read from ~/.dockercfg, but will always write new data to ~/.docker/config.json
  2. Gcloud will write to ~/.dockercfg using the old file format (plain config object) IF there is no ~/.docker/config.json. ELSE it will write to ~/.docker/config.json using the new file format (auths object inside config object).
  3. docker-py will read from either ~/.dockercfg or ~/.docker/config.json, but only uses the new format (see: https://github.com/docker/docker-py/blob/master/docker/auth.py#L104)

So, if there is no ~/.docker/config.json and one does gcloud docker login && gcloud docker -a, ~/.dockercfg is created in the old format, which docker-py won't read. Thus, it cannot find the auth credentials and docker-compose pull fails.

IMO, docker-py should use the old format for the old file and the new format for the new file, as both docker and Gcloud do.

I worked around this by using docker login -u _token -p $(gcloud auth print-access-token) eu.gcr.io for now, but others might run into the same problem.

shin- commented 6 years ago

Can you post an example of the config format that seems to be causing the issue? Our auth parsing supports at least 3 different versions of the file, but maybe we missed something.

c4tz commented 6 years ago

Thank you for the fast response! :)

cat ~/.dockercfg

{
  "https://eu.gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  },
  "https://staging-k8s.gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  },
  "https://gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  },
  "https://us.gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  },
  "https://k8s.gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  },
  "https://asia.gcr.io": {
    "email": "not@val.id",
    "auth": "XYZ"
  }
}

docker-compose pull

Pulling test (eu.gcr.io/some/private/image:latest)...
ERROR: pull access denied for eu.gcr.io/some/private/image, repository does not exist or may require 'docker login'

Again, this will only happen, if there is no ~/.docker/config.json created before by any other process (like docker itself, e.g.)

chanseokoh commented 5 years ago

This may be unrelated to the issue, but I must leave a comment so that people stop using gcloud docker.

gcloud docker is deprecated and should not be used. It places those credentials for GCR whose email is not@val.id in the auths block in ~/.docker/config.json, and they are very short-lived and will stop working very soon.