AWS CLI で Amazon ECR に docker イメージを push する

Amazon Elastic Container Registry (ECR) に AWS CLI を使ってイメージを登録したときの作業手順をまとめました。

## Amazon ECR とは

AWS で使える docker コンテナレジストリです。
DockerHub でもよかったのですが、AWS の同一リージョン内であれば `docker pull` のデータ転送料が無料(※)で、且つ速くなるはず（推測）、というのが使用動機でした。

※ データ転送料が無料になる代わりにストレージ使用量がかかります。

## 必要なもの

 - AWS CLI
 - docker engine
 - 必要な docker イメージを pull できるだけのディスク容量

## 準備

上記必要なものがそろっていれば特に手段は問いません。参考までに、ここでは私の作業手順を記載します。

EC2 インスタンスを以下内容で 1 つ作成します。

 - AMI: Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type - ami-25615740
 - インスタンスタイプ：t2.micro
 - ストレージ：ボリュームタイプ EBS で 22GiB 追加し、「合わせて削除」にチェック

起動したインスタンスに SSH ログインし、以下コマンドで docker engine をインストールします。

```Bash
$ sudo yum install -y docker
$ sudo service docker start
Starting cgconfig service:                                 [  OK  ]
Starting docker:        .                                  [  OK  ]
```

このままでもいいですが、docker コマンドに sudo が必要ですので、sudo なしで動くようにします。

```Bash
$ sudo gpasswd -a $USER docker
$ sudo service docker restart
（一旦ログアウトして、再度ログイン）

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

Amazon Linux AMI の場合、AWS CLI はインストール済みですので、`aws configure` だけ行います。
手順はこちら [AWS CLI のインストールと設定](https://qiita.com/aokad/items/88fe9312eea1c12ba8a2)

## コマンド

### ログイン

まず、AWS ECR にログインします。

```Bash
$ aws ecr get-login --no-include-email
```

ここで、長いコマンドが返ってきますので、コピペして実行します。

```Bash
$ docker login -u AWS -p {省略} == https://${registryId}.dkr.ecr.${region}.amazonaws.com
```

`Login Succeeded` と帰ってくれば成功です。

### リポジトリを作成する

※ ここでは例としてリポジトリ名 `my-python` を使用します。必要な名称を適宜設定してください。

```Bash
$ aws ecr create-repository --repository-name my-python
{
    "repository": {
        "registryId": "123456789012",
        "repositoryName": "my-python",
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:123456789012:repository/my-python",
        "createdAt": 1522995148.0,
        "repositoryUri": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-python"
    }
}
```

ここで取得した repositoryUri がイメージを操作するときに必要になってきます。

### リポジトリ URI

AWS のリポジトリ URI は以下の構成になっています。

```Bash
"repositoryUri": ${registryId}.dkr.ecr.${region}.amazonaws.com/${image_name}:${image_tag}
```

実際に作業する上では必要ないと思いますが、この記事ではコピペ実行できるように環境変数にセットしておきます。

```Bash
$ export registryId={registryId}
$ export region={region}
```

`repositoryUri: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/my-python` の場合、{registryId} は `123456789012`, {region} は `ap-northeast-1` です。

### DockerHub から pull して AWS ECR に push する

必要なイメージを pull して、repositoryUri でタグ付けをして、push します。

```
$ docker pull python:3.6.5-alpine3.7
$ docker tag python:3.6.5-alpine3.7 ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:3.6.5-alpine3.7
$ docker push ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:3.6.5-alpine3.7
```

おしまい。
ちょっとイメージの名前が長くなりますが、コマンド自体は簡単です。

不要な image は消しておきます。

```
$ docker rmi ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:3.6.5-alpine3.7
$ docker rmi python:3.6.5-alpine3.7
```

### docker build してから push する

repositoryUri でタグ付けをして docker build します。
[サンプルの DockerFile はこちら](https://raw.githubusercontent.com/aokad/qiita_aws_batch/master/Dockerfile)

例えば、このようにします。

```
$ docker build -t ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-build .
$ docker push ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-build
```

不要な image は消しておきます。

```
$ docker rmi ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-build
```

### pull したイメージを加工してから push する

docker commit のとき、Amazon ECR の repositoryUri を設定します。
例えば、このようにします。

```
$ docker pull python:3.6.5-alpine3.7
$ docker run --name my-container python:3.6.5-alpine3.7 "ash" "-c" "pip install awscli"
$ docker commit my-container ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-container
$ docker push ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-container
```

不要な image は消しておきます。

```
$ docker rm my-container
$ docker rmi ${registryId}.dkr.ecr.${region}.amazonaws.com/my-python:my-container
```

## AWS ECR での確認

Web ブラウザで「AWS コンソール」を開いて、「Elastic Container Service」を選択し、「Amazon ECR リポジトリ」を選択します。

リポジトリ名をクリックして「イメージ」タブを表示します。
push したイメージが表示されていれば成功です。

## 使用料金

気になるお値段ですが、最新の情報は[公式](https://aws.amazon.com/jp/ecr/pricing/)でご確認ください。
以下は 2018 年 4 月執筆時点での情報です。

大きく分けて 3 つの料金がかかります。

 - ストレージ料金 ... 0.10 USD/GB/月
 - データ転送料金 "データ受信(イン)" ... もともと無料
 - データ転送料金 "データ受信(アウト)"  ... 同一リージョンの AWS EC2 で使用している限り無料

イメージサイズとして合計 10 Gbyte 使用すれば、一か月 1.00 USD (約 107 円) と計算できます。
別リージョンから pull しないように要注意です。

## 片付け

このままでは毎月課金されてしまいますので、片付けます。

まず、イメージを削除します。
「AWSコンソール」→「Elastic Container Service」→リポジトリ名を選択→削除したいイメージにチェック→「削除」

次にリポジトリを削除します。
「AWSコンソール」→「Elastic Container Service」→「リポジトリ」→該当するリポジトリにチェック→「リポジトリの削除」

AWS CLI の場合(タグ名は適宜設定してください)

```
$ export tag=3.6.5-alpine3.7
$ aws ecr batch-delete-image --repository-name my-python --image-ids imageTag=${tag}
$ aws ecr delete-repository --repository-name my-python
```

[準備](#準備)で EC2 インスタンスを立ち上げた場合は削除しておく事を忘れないようにしましょう。

以上です。