sous-chefs / docker

Development repository for the docker cookbook
https://supermarket.chef.io/cookbooks/docker
Apache License 2.0
1.35k stars 795 forks source link

docker_registry needs support for Amazon ECR and Google GCR #826

Open someara opened 7 years ago

someara commented 7 years ago

Right now docker_registry only supports "vanilla" docker registries. The "big two" cloud providers have unique quirks that need support.

Collapsing these two tickets into one https://github.com/chef-cookbooks/docker/issues/806 https://github.com/chef-cookbooks/docker/issues/814

rashidmahmood commented 7 years ago

Here is a workaround for this issue.

  1. Setup your access keys to your node.
  2. Add this to your recipe. It will simply login to ECR.
    cmd = "aws ecr get-login --region us-east-1" value = #{cmd} list = value.split(" ")

docker_registry 'AWS ECR registry' do serveraddress 'https://xyz.ecr.us-east-1.amazonaws.com' username 'AWS' password "#{list[5]}" email 'none' end

et304383 commented 7 years ago

@rashidmahmood it's not a permissions issue. It's an issue with the actual request headers. This is what anyone is already doing to login to ecr using the docker_registry resource.

et304383 commented 7 years ago

Any progress @someara ? We're still having to resort to bash resource calls rather than properly using the resources available in this cookbook in order to login to ECR, pull containers down, and run them.

dannygu commented 6 years ago

any chances of this getting fixed any time soon ? just like @et304383 we are forced to use bash calls or find other tools....

bflad commented 6 years ago

Docker has credential helpers that should help in this situation. Has anyone tried https://github.com/awslabs/amazon-ecr-credential-helper ? I haven't used it in this context with Chef, but theoretically should allow skipping docker_registry with ECR as docker pull just works.

davidcaste commented 6 years ago

I'm sorry but credentials helpers only works if you use the docker client. This cookbooks uses the chef gem, and if I'm not mistaken, it uses the Docker API instead.

dannygu commented 6 years ago

@davidcaste you are indeed correct, the problem isn't the login part

thebrianlopez commented 6 years ago

+1

ziprick commented 6 years ago

Another workaround that has the advantage of being 'pure ruby', instead of resorting to shell / aws cli, it uses the aws-sdk gem (which I believe is now standard in the ChefDK) to make the AWS API call directly.

Assuming you keep your AWS access keys in a chef data bag:

chef_gem 'aws-sdk'

ruby_block 'grab_ecr_login_password' do
  block do
    require 'aws-sdk'
    require 'base64'
    aws_creds = data_bag_item('aws','creds')
    client = Aws::ECR::Client.new(access_key_id: aws_creds[:aws_access_key],
                                  secret_access_key: aws_creds[:aws_secret_access_key],
                                  region: 'us-east-1')
    resp = client.get_authorization_token
    token = resp.authorization_data.first.authorization_token
    user, pass = Base64.decode64(token).split(':')
    node.run_state['aws_ecr_user'] = user
    node.run_state['aws_ecr_pass'] = pass
  end
end

docker_registry 'AWS ECR' do
  serveraddress 'https://0123456789.dkr.ecr.region.amazonaws.com' # your AWS ECR URL
  username lazy { node.run_state['aws_ecr_user'] }
  password lazy { node.run_state['aws_ecr_pass'] }
end

In the case of running on an EC2 instance, I believe one can instantiate Aws::ECR::Client directly (without parameters) and it will use instance metadata / IAM role to authenticate.

It uses node.run_state to temporarily store ECR login credentials between the ruby_block and docker_registry resources, which is automatically cleared at the end of a Chef run.

Note that the use of lazy {}is necessary on the docker_registry properties, as the values in node.run_state['...'] will not be populated until the convergence phase.

ls-brentsmith commented 6 years ago

I initially had some issues with GCR login / pull as well, but it does indeed work

# login to gcr
credentials = data_bag_item('credentials' ,'gcr')
docker_registry 'https://gcr.io/' do
  username '_json_key'
  password credentials['service_account'].to_json
  action :login
end

# Pull tagged image
docker_image 'something' do
  repo 'gcr.io/your-repo'
  tag 'latest'
  action :pull
end

note: I had some issues with storing the json key inside of json databags, so I chose to nest the plain json under a keyspace 'service_account' and then turn use #to_json for the password. Alternatively, you can stringify the json key in your databag directly.

Another issue I ran into was a weird docker state after several failed attempts at getting the login and pull to work. When running docker login gcr.io and docker pull <my_image> from the terminal, I started receiving the following error:

docker: open /var/lib/docker/tmp/GetImageBlob549217035: no such file or directory.

After restarting the docker daemon, I was again able to pull my images correctly with both the CLI and this cookbook.

When in doubt, start from scratch in test-kitchen.