AWS ECR学習記録

# はじめに
　AWS初心者の自分がAWSのサービスを利用してインフラの構築を行う機会があったので、そのとき得た知見を復習がてらまとめていく＆自分でいつでも見直すメモのための記事です（そのため図解などは特にない）。
　今回は、ECRのサービスにローカルからコマンドでイメージをプッシュする方法についてまとめました。
 
# 必須知識
- Dockerの基本的な知識

# AWS ECRとは
　Elastic Container Resistoryの略で、直訳すると融通のきくコンテナの登録所です。融通のきくコンテナの「イメージ」を登録、つまり保存できます（EIRの方が正しいよなと思いました）。
 
 https://aws.amazon.com/jp/ecr/
 
 ## なにが"Elastic"
 ECRはフルマネージドサービスで以下の特徴をもつ。
 - 自動スケーリング
　ユーザーがイメージを何個保存しようがストレージを勝手に拡張して保存してくれる。
 
 - 高い可用性
  複数のAZに分散して保存。可用性・耐障害性が高い。
  
- 柔軟なアクセス管理
　IAMやリポジトリごとのアクセスコントロールによって柔軟にアクセスを管理できる。

- 価格もElastic 
　[価格](https://aws.amazon.com/jp/ecr/pricing/)も利用した分だけを支払えばよく、状況ごとに最適な価格で利用可能。

## なぜECRを用いるのか
イメージを保存、共有するサービスにDocker Hubがありますが、今回はなぜECRを利用するという判断になったのかを説明します。
- 他サービスとの連携のしやすさ
 　今回の最終目的として、AWSのサービスであるAWS Batchを使用したサービスの実装がありました。AWS Batchは、めちゃくちゃざっくりいうと作成したタスクに対して「環境の起動→実行→停止」を全部実行してくれるもので、Dockerのイメージがこのタスクの実行単位になります。その接続は、AWS CDKを利用すれば容易に実装できます。
 　他にも、EC2上でコンテナを動かしたい時や、Lambdaで容量が大きすぎてレイヤに追加できないパッケージを利用するコードを実行したいときは、ECRを用いると容易に実装することができます。

- 低コスト
　先にも書いたように、ECRは利用方法に応じて柔軟なコスト計算が行われます。また、AWSのサービスであれば、同一リージョン内では無料でECRからイメージのプルが可能です。そのため、AWSのサービスと組み合わせて使えば、低コストで実装が可能となります。

# 事前準備
・ Dockerfileの作成・イメージのローカルビルド
    このとき、以下のようにビルドしたとして進めていきます。
```bash
export IMAGE_NAME=イメージの名前
docker build -t ${IMAGE_NAME}:latest .
```
ビルドした後に、本当に動くかをローカルでテストしておきましょう。

・ AWSの準備
    AWS CLIのインストール（ここでは詳細は省きます）
    AWSアカウントID・リージョン・リポジトリ名の確認、設定を行う。これらも環境変数としておくと楽
```bash
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export REGION=ap-northeast-1
export REPO=任意
```

# 実装
### 1. ECR内にリポジトリの作成
ECRにリポジトリを作成します。

```bash
aws ecr create-repository --repository-name <REPO> --image-scanning-configuration scanOnPush=true
```

?"--image-scanning-configuration scanOnPush=true"とは？
　このオプションをつけることで、ECRがイメージプッシュ時に自動で脆弱性スキャンを行なってくれます。無料のOSパッケージのCVEチェック、有料のEnhancedスキャン（コンテナの言語ライブラリ層まで深掘りし、継続監視。Registry 設定で有効化）があります。

### 2. ログイン
Dockerにはログイン機能があり、どのレジストリにpush/pullして良いかの認証情報を保存します。

```bash
aws ecr get-login-password --region $REGION \
    | docker login \
        --username AWS \
        --password-stdin $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/&REPO:latest
```
このコマンドを実行すると、Dockerの認証ファイル ~/.docker/config.jsonに
```json
{
"auths": {
  "<ACCOUNT_ID>.dkr.ecr.<REGION>.amazonaws.com": { ... }
}
}
```
が書き込まれます。

＊AWSから発行されるトークンは12時間だけ有効なので、12時間後にもう一度pushを行いたい場合は再度ログインをしてください。

### 3. タグづけ・プッシュ
Dockerにおいて、希望するレジストリにイメージを送るには"送り先のURLを含む名前"を付け直す必要があるのでタグ付けを実行します。（このURLはAWSの他のサービスでこのイメージを指定するときにも使用します。）
```bash
docker tag $IMAGE_NAME:latest \ 
    $ACCOUNT_ID.dkr.ecr.$REGION.amazonaws.com/$REPO
```
いよいよレジストリに自分の作成したイメージをプッシュします。
```bash
docker push $ACCOUNT_IS.dkr.ecr.$REGION.amazonaws.com/$REPO:latest
```

### 4. 確認
最後にイメージがECR上にあるのかの確認をして終わりましょう。
```bash
aws ecr describe-images --repository-name $REPO \
    --region $REGION \
    --output table
```

### 運用Tips
- Lifecycle Policy
    開発を進める上で何度もイメージをプッシュしていくと、ECRにはその数だけイメージが蓄積されていってしまいます。それをそのままにしていると、ECRは保存容量に対しても課金がなされるので使っていないのに支払いのみが発生してしまいます。そこで、以下のようなポリシーを設定することで20個よりも古いイメージを自動削除すると言ったことが可能になるストレージの料金節約につながります（適宜消していれば問題はありませんが）。
```bash
aws ecr put-lifecycle-policy \
    --repository-name $REPO
    --lifecycle-policy-text `{
        "rules":[{
            "rulePriority":1,
            "description":"keep last 20 images",
            "selection":{"tagStatus":"any","conuntType":"imageCountMoreThan","countNumber":20},
            "action":{"type":"expire"}
        }]
    }`
```

# 最後に
以上の操作を行うことで、ECRにローカルからイメージをプッシュすることができます。今回は実行コマンドを順番に書く程度になりましたが、それぞれの工程の裏側で何が起きているのかを調べてみるとより理解が深まると思うので、ぜひお勧めします。余裕があれば、その内容も記事にしていきたい、、、

# 参考サイト
https://aws.amazon.com/jp/ecr/

https://docs.docker.jp/v1.11/index.html