0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

RubyでDockerイメージをビルドしてECRにプッシュする

Last updated at Posted at 2019-06-11

背景

あるシステムをkubernetesで動かすために、ローカル環境にあるDockerイメージをECRにプッシュする必要があって、aws-clidockerコマンドでのやり方は理解していたが、他のメンバーにaws-cli入れてもらうのとかシェルのスクリプト書くのもなんだかなーと思っていた。

そこで、そのシステムがRailsで動いているのでRubyでローカルでDockerイメージをビルドして、ECRにプッシュできないかなと考えていた。

概要

docker-apiでDockerイメージのビルドはできそうだったので、あとはaws-sdk-ecrAws::ECR::Clientput_imagedocker-apiDocker::ImagepushでECRへのイメージのプッシュができそうだった。

aws-sdk-ecrAws::ECR::Clientput_imageの必須オプションでimage_manifestがあったのだけど、今まで扱ったことないし、docker-apiでも取得できなそうだった。

Dockerのドキュメント見たら、docker manifest関連のコマンド自体がexperimental(実験的)っぽいので、Aws::ECR::Clientput_imageを使う方法は断念。

Docker::Imagepushの方法は、Docker.authenticate!通せるかが肝になる。

aws ecr get-login --region region --no-include-emaildocker login -u AWS -p password https://aws_account_id.dkr.ecr.us-east-1.amazonaws.comdockerECRにログインできる情報が取得できるので、Aws::ECR::Clientでなんとかその情報取れれば良さそう。

Aws::ECR::Clientget_authorization_tokenのドキュメント見るとレスポンスの中のauthorizationToken

A base64-encoded string that contains authorization data for the specified Amazon ECR registry. When the string is decoded, it is presented in the format user:password for private registry authentication using docker login .

docker loginで使えるuser:passwordbase64でエンコードされたものと書いてある。
要はbase64デコードするとAWS:[docker loginで使えるパスワード]が取得できる。

これで、Docker.authenticate!通せそう。

コード

push_image_to_ecr.rb
require 'docker'
require 'aws-sdk'

aws_access_key_id, aws_secret_access_key = [何らかの方法で取得(環境によると思うので省略)]
Aws.config.update(credentials: Aws::Credentials.new(aws_access_key_id, aws_secret_access_key))

tag = '0.0.1' # 実際はYAMLに書くかコマンド引数にすべきだかここでは一旦変数で持つ

ecr_client = Aws::ECR::Client.new

# 既にECRにプッシュされたものがないか確認
list_images_response = ecr_client.list_images(repository_name: 'hoge')
pushed_image = list_images_response.image_ids.detect { |image_id| image_id.image_tag == tag }

if pushed_image
  puts 'Pushed image is found. Nothing to do.'
  return
end

# Docker.authenticate!に必要な情報だけでなくendpointもget_authorization_tokenで取得できる
authorization_token_response = ecr_client.get_authorization_token
authorization_token = authorization_token_response.authorization_data[0].authorization_token
proxy_endpoint = authorization_token_response.authorization_data[0].proxy_endpoint

full_repository_name = proxy_endpoint.sub(Regexp.escape('https://'), '') + '/hoge'

# 既にローカルにビルドされたイメージがあれば取得
builded_image = Docker::Image.all.detect { |image| image.info['RepoTags'].first == "#{full_repository_name}:#{tag}" }

unless builded_image
  # ビルドしてタグ付け
  puts 'Building image'
  builded_image = Docker::Image.build_from_dir('.')
  builded_image.tag('repo' => full_repository_name, 'tag' => tag)
end

# docker loginで使えるユーザー名とパスワードの取得
username, password = Base64.decode64(authorization_token).split(':')
options = {'username' => username, 'password' => password, 'serveraddress' => proxy_endpoint, 'email' => 'none'}
Docker.authenticate!(options)

# ECRにプッシュ
builded_image.push

実行

あとはDockerfikeと同じディレクトリにpush_image_to_ecr.rbを配置して、bundle exec rails r push_image_to_ecr.rbするだけ(aws_access_key_id, aws_secret_access_keyの取得方法によってはruby push_image_to_ecr.rbでも)。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?