前回の Dockerfile の代わりに Packer を使って Docker に再々入門してみている - えいのうにっき の続き。今後いくつかのコンテナイメージを作っていくにあたって「ヒミツにしておきたい情報を含んだコンテナ」を作ることもありそうなので、そんなイメージの登録はプライベートなレジストリにしたい・それなら Amazon ECR はどうだろう。というのが経緯。
Amazon ECR(EC2 Container Registry)を試す
まずは料金周りの確認。以下は東京リージョンのもの(2017-03-20 現在)。
- ストレージ
- 0.10 USD/GB/月(一律)
- 無料利用枠として、月 500 MB 分のストレージが1年間は無料。
- データ転送
- データ受信(イン)
- すべてのデータ受信:$0.000 / GB
- データ送信(アウト)
- 最初の 1 GB/月:$0.000 / GB
- 10 TB まで/月:$0.140 / GB
- 無料利用枠の一環として、1ヶ月につき 15 GB のデータ送信が1 年間無料。
- ただしこれは、すべての AWS の各種サービスを総合して15GB。
- データ受信(イン)
- 参考:料金 - Amazon EC2 Container Registry | AWS
こんなかんじ。個人利用目的であれば、お小遣いの範囲内で十分利用できそう。ってことで、早速利用を開始してみる。
基本的にはこちらのページ AWS ECS編~EC2 Container Registry を試してみる~ | ナレコムAWSレシピ に沿って作業を実施した。ってか、「ECR」っていう独立した AWS サービスがあるのかと思ってたけど、ECS(Amazon EC2 Container Service)のうちの一機能、って感じだったんだね。誤解してた。
AWSコンソール上での ECR リポジトリの作成自体は一瞬で完了。あとはここにイメージを push してみたいわけだけど、ECR への Docker イメージの push には AWS CLI が必要で、僕はまだインストールしていなかったので、まずは以下のコマンドで AWS CLI をインストール。
$ curl -kL https://bootstrap.pypa.io/get-pip.py | sudo python $ sudo pip install awscli --upgrade --ignore-installed six (中略) $ aws --version aws-cli/1.11.63 Python/2.7.10 Darwin/15.6.0 botocore/1.5.26
ただ pip install awscli
とやっただけだと Operation not permitted: '/tmp/pip-saoiMq-uninstall/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/six-1.4.1-py2.7.egg-info'
エラーが出たので、OS X EI Caption(10.11.1)でAWS CLIのインストールエラー を参考にこれを回避。
その後、aws configure
コマンドで認証情報をセット。そして下記コマンドを実行してみると、
$ aws ecr get-login --region ap-northeast-1
docker login -u AWS -p ...
という出力がどばっと出る。これを実行しろということのようなので実行してみると Login succeeded
と出る。これで手元の docker コマンドが ECR リポジトリにもアクセスできるようになった、というイメージかな。よさそう。
続いて、前回のエントリで作成したイメージにタグを付けてみる。
$ docker tag a-know/a-know-server-base-container:0.1.0 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container:0.1.0 $ docker images REPOSITORY TAG IMAGE ID CREATED SIZE 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container 0.1.0 9c7a8703ae10 3 days ago 754 MB a-know/a-know-server-base-container 0.1.0 9c7a8703ae10 3 days ago 754 MB centos centos7 67591570dd29 3 months ago 192 MB
なるほど。そのままこれを push してみる。
$ docker push 1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container:0.1.0 The push refers to a repository [1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container] a85bce3bb1dd: Pushed 0.1.0: digest: sha256:7c97bb06c8324fd9a0ab4df839b3db8a90fd12c0d9b2c49b87796ee53d24c30d size: 529
754MBもあるのでそこそこ時間がかかってしまった。。AWS コンソールの方も確認してみる。
okok。
...あれ、サイズが小さいぞ...? と思ったら、 イメージの表示サイズは、圧縮されている可能性があります
とのこと。
Packer と ECR を連携させる
連携させる、というほど大げさなものではないんだけど、
- ECR に上げたイメージをベースに別のイメージのビルドを実行する
- ビルドの結果できたイメージをそのまま ECR に上げる
といったことをしてみる。毎回手作業で ECR に push するのもアレだしね。
1.については単純で、 builders
の image
の指定を先ほど push した "image": "1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container:0.1.0"
にすればいい。docker が ECR のプライベートリポジトリからイメージを pull するためには、上述の docker login
が行われてある必要がある。さらにこれは一定時間経つと失効してしまうので、その点は頭の片隅に置いておく必要がある(失効してしまっていたら aws ecr get-login --region ap-northeast-1
をもう一度実行し docker login
コマンドを再度取得・ログインしなおす)。
2.は、Packer の post-processors
の type
に指定できる docker-push
が Amazon ECR にも対応しているということなので、こちらの記事 Packer + Ansible + ECRを使ったDcokerコンテナイメージ作成の自動化 | DevelopersIO を多いに参考にさせていただきつつ、公式ページや Packer の GitHub issue なども確認しながら、結果的に以下のような Packer json を作成することで Packer と ECR との連携を行なうことができた。
{ "variables": { "ecr_repo": "{{env `APP_CONTAINER_ECR_REPO`}}", "ecr_url": "{{env `ECR_URL`}}", "aws_access_key": "{{env `AWS_ACCESS_KEY`}}", "aws_secret_key": "{{env `AWS_SECRET_KEY`}}", "tag": "0.0.1" }, "builders":[ { "type": "docker", "image": "1234567890.dkr.ecr.ap-northeast-1.amazonaws.com/a-know-server-container:0.1.0", "export_path": "image.tar" } ], "provisioners":[ { "type": "shell", "inline": [ "mkdir -p /var/www/a-know-home/current", "git clone https://github.com/a-know/a-know-home-rails.git /var/www/a-know-home/current" ] } ], "post-processors": [ [ { "type": "docker-import", "repository": "a-know/a-know-server-container-app", "tag": "{{user `tag`}}" }, { "type": "docker-tag", "repository": "{{user `ecr_repo`}}", "tag": "{{user `tag`}}" }, { "type": "docker-push", "ecr_login": true, "aws_access_key": "{{user `aws_access_key`}}", "aws_secret_key": "{{user `aws_secret_key`}}", "login_server": "{{user `ecr_url`}}" } ] ] }
この json の内容について、自分がハマってしまったところも含め、細かい注意事項を以下にまとめておく。
variables
post-processors
docker-tag
により ECR のためのタグを付け、docker-push
で ECR にアップロードする。docker-push
による ECR へのアップロード周りに Packer 側でのアップデートが入っているので、古い記述の仕方だとエラーになる。post-processors
に複数ステップを指定する場合はArray<Array<Hash>>
みたいな感じになるっぽいので、これも注意が必要。
この内容の json で packer build
を実行すると、
- ECR に上がっている自分用のベースイメージを pull して、
- ディレクトリを掘り、アプリケーションコードを
git clone
し、 - タグを付け、
- ECR に push する
...といったことが行われる。
ok!
まとめ
意図せずして二部構成になってしまったけど、今回いろいろと試してみたことによって、Docker に関するツールの僕の中での選択肢を
- Docker Hub か Amazon ECR か
- Dockerfile か Packer か
- Dockerfile で書くのがつらい場合・ベースイメージを作り上げる過程では Packer で、
- Packer で作ったベースを元にちょっと手を加える用途では Dockerfile で十分できそう
- ...という感じかなというのが今のところの感触
というかんじで広げられたので、よかった。
あとこれはまぁ実際にここまでやってみて思ったことなんだけど、今回自分で作ったベースのイメージも単に Ruby が入っていればよかっただけなので、そういうイメージを探してそれをベースとして使えば Packer を使うまでもなかったのかもしれないなぁ、と。
今後は
- docker だけインストールした EC2 インスタンスを用意する
docker-machine
を使って用意するかどうかは考え中
- fluentd・nginx・mackerel-agent などのコンテナ(多分これらは自分で用意するのではなく公式のものを使う感じになるんだと思う)を docker-compose で利用し、そのインスタンス上で実行することで全体としてちゃんと動作するかどうかを確認する
といったところまでやってみたいなーと思う!