genuinetools/img

AWS ECR or GCR login

Guillermogsjc opened this issue · 4 comments

Hi,

how would you login into AWS ECR or GCR using img login ?

Are there any direct forms?

If there is not, maybe there is a bit of trouble at CICD, because you would need Docker with socket running in the machine were you want to run img instead, but does mean runing docker in docker in CICD pipes, and thats precisely one of the most important use cases of img: to avoid using docker-in-docker on CICD stage, especifically on Kubernetes.

Regards.

Hi @Guillermogsjc

I have just stumbled on the same issue recently (build/tag/push image to ECR on Kubernetes without dind as part of a CI pipeline).
I don't know for GCR, so i'll just answer for AWS.

ECR login is documented here: https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html

Here, we can replace docker for img as follows:

aws ecr get-login-password --region <region> | img login --username AWS --password-stdin <account_id>.dkr.ecr.<region>.amazonaws.com

For this to work, you have two solutions: aws-cli or docker-credential-ecr-login helper.

aws-cli

We need to have the awscli client to be present in the build container.
But, images published in r.j3ss.co/img (https://r.j3ss.co/repo/img/tags) are rootless.
Therefore, we can't install it at runtime using any privileged command (e.g. apk add, su).

A solution is to create a custom dockerfile FROM r.j3ss.co/img.
Dockerfile example installing awscli using pip:

FROM r.j3ss.co/img:v0.5.11

# switch from user to root
USER root
RUN apk --no-cache add \
    py3-pip
    && rm -rf /var/cache/apk/*
    && pip3 install awscli

# switch back to user
USER user

The drawback is that you have to host/maintain this custom image now.

docker-credential-ecr-login

Instead of the full awscli, we can install docker-credential-ecr-login written in Go. (https://github.com/awslabs/amazon-ecr-credential-helper)

Official documentation here: https://aws.amazon.com/blogs/compute/authenticating-amazon-ecr-repositories-for-docker-cli-with-credential-helper/

Building a custom image with docker-credential-ecr-login instead of awscli works but we can also have a runtime setup approach !

The trick is to download the pre-compiled release from Github (e.g. https://github.com/awslabs/amazon-ecr-credential-helper/releases/tag/v0.4.0).

For example, inside the r.j3ss.co/img container:

mkdir $HOME/bin \
  && wget -q -O $HOME/bin/docker-credential-ecr-login https://amazon-ecr-credential-helper-releases.s3.us-east-2.amazonaws.com/0.4.0/linux-amd64/docker-credential-ecr-login \
  && chmod u+x $HOME/bin/docker-credential-ecr-login \
  && export PATH=$PATH:$HOME/bin

mkdir $HOME/.docker \
  && cat > $HOME/.docker/config.json <<EOF
{
    "credsStore": "ecr-login"
}
EOF

Then, pulling or pushing from ECR works without explicit login:

img pull $ECR_URL/my_repo:latest

img push $ECR_URL/my_repo:latest

With this solution, there is no custom image to maintain, just some start script to execute before img build.

Finally, I don't know about GCR but I suppose something similar could be done.

Hope it helps !

HI @alefray,

thank you very much for you extense response.

Both exposed cases require docker to be installed for getting the login, if a did not misunderstood.

The whole point of the question is to avoid using docker in docker in CICD pipelines, because of the kubernetes deprecation of dockershim and security reasons. So docker in the required use case must not be installed or have an available running socket.

I mean, I have already this non-working (at the aws ecr login step) schema in a .gitlab-ci.yml:

test_img_from_alpine:
  image: alpine:3.12.3  
  stage: tests
  
  before_script:
    - export AWS_ACCESS_KEY_ID=${RH_AWS_DEV_ACCESS_KEY}
    - export AWS_SECRET_ACCESS_KEY=${RH_AWS_DEV_SECRET_KEY}
    - export AWS_DEFAULT_REGION=${RH_AWS_DEV_REGION}
    
  script:
      - apk add --update --no-cache --quiet py-pip img
      - img pull busybox
      - img ls
      - img build -t test_image .
      - img ls
      - pip install --upgrade awscli
      - $(aws ecr get-login --no-include-email)
      - ... 

The use case is to avoid using aws ecr get-login or any application that requires docker installed, so one could rely only on img for performing the pipe.

So the question, is, inside an alpine like the one on this YAML without docker being available, does img have any feature to reach logins?

Regards.

The answer is yes!

In both cases you don't need docker in the CI image, only img and one of the discussed aws login utility solution.

By the way, nice catch! I missed that img is available in alpine 3.12.
You nearly got this right. Could you try something like:

test_img_from_alpine:
  image: alpine:3.12.3  
  stage: tests

  variables:
    ECR: <account_id>.dkr.ecr.<region>.amazonaws.com 
    AWS_ACCESS_KEY_ID: ${RH_AWS_DEV_ACCESS_KEY} 
    AWS_SECRET_ACCESS_KEY: ${RH_AWS_DEV_SECRET_KEY}
    AWS_DEFAULT_REGION: ${RH_AWS_DEV_REGION}

  script:
    - apk add --update --no-cache --quiet py-pip img
    - img pull busybox
    - img ls
    - img build -t test_image:latest .
    - img ls
    - pip install --upgrade awscli
    - aws ecr get-login-password | img login --username AWS --password-stdin $ECR
    - img tag test_image:latest $ECR/test_image:latest
    - img push $ECR/test_image:latest

Hi @alefray ,

yes! that works. It was my blind desire of using aws ecr get-login (that requires docker ) instead the light token getter aws ecr get-login-password.

Thank you very much.