[Docker 入門] コンテナ内からAWS S3のバケット名を取得する

## 本記事でやること


- Dockerコンテナ内からboto3 / aws cliを使ってAWS S3のバケット一覧を取得する 

上記を達成するために行うこと

1. AWSアカウントを作成し、`aws_access_key_id`と`aws_secret_access_key`を取得しておく
2. AWS上の対象ユーザーにS3のアクセス権限を付与しておく
3. ECR上にベースとなるDockerイメージ（Pythonイメージにansibleをインストールしたもの）をアップする

本記事では、1と2に関しては記載をしないので他の記事等を参照してください。

## 対象読者

- 「Dockerって何それ？美味しいの?」状態を超えた、Docker初学者
   - Dockerに関する基礎的な書籍を一通り読んだ人
- AWS初学者の人 
   - S3やECRが何をするためのサービスなのかは理解している人

## 使用する言語
- Python 3.6.3


## AWS ECR上にベースとなるDockerイメージ（Pythonイメージにansibleをインストールしたもの）をアップする

AWS ECRの勉強も込めてpythonイメージにansibleもインストールをしたイメージをECRにアップし、そのイメージを使ってdockerコンテナを作成することにする。
ansibleをインストールする意味は、`aws_access_key_id`と`aws_secret_access_key`と言った機密性の高いものを扱うのでgithubなどでファイルを管理する場合に暗号化（及び復元）が必要になるためです。（業務では、必ずと言っていいほど使用するので普段の個人的な勉強でも使って身につけておいた方がいいと思われます。）

以下が、今回使用するベースとなるイメージのDockerfileになります。

```Dockerfile:Dockerfile
#######################################################
# pythonのイメージにansibleをインストールしたイメージ
#######################################################
FROM python:3.6.3

# ansibleをインストールしておく
RUN apt-get update
RUN apt-get -y install ansible

# pythonで必要なものをそろえる
RUN pip3 install --upgrade pip
RUN pip install aws==0.2.5 awscli==1.15.17 boto3==1.7.8

```

pythonのイメージを使っているので、pip installで今回必要になるであろうライブラリーをインストールしておく。
今回は、`aws`と`aws cli`、`boto3`を入れておく。このファイルを適当なディレクトリにいれる。このイメージをECRにプッシュする前に、AWSのコンソールにログインしレポジトリを作成しておく。
※画像内にはすでにイメージがプッシュされている状態であるが、何も無い状態が正しい。

<img width="1432" alt="スクリーンショット 2018-12-29 16.34.24.png" src="https://qiita-image-store.s3.amazonaws.com/0/270991/f3b3df28-1899-3d52-db6d-a81b4994e2db.png">

上記画像内右上の`プッシュコマンドの表示`を押下すると以下のコマンドが表示されるはずなので、それをコピペし実行するとECRにイメージがプッシュされる。
<img width="820" alt="スクリーンショット 2018-12-29 16.25.44.png" src="https://qiita-image-store.s3.amazonaws.com/0/270991/3e9799ad-4878-507d-5a85-e9304866b7fb.png">


```
# ECRにログインする
$(aws ecr get-login --no-include-email --region ap-northeast-1 --profile hoge)

# イメージのビルド（イメージの名前は適当に"python"とする）
docker build -t python .

# 上でビルドしたイメージにタグをつける(hogehogeの部分には)
docker tag python:latest hogehoge.dkr.ecr.ap-northeast-1.amazonaws.com/python:latest

# イメージをAWS ECRにプッシュする
docker push hogehoge.dkr.ecr.ap-northeast-1.amazonaws.com/python:latest
```

上記のコマンドを実行し、AWSコンソール上にタグ付けした名前でプッシュされていればOK。

## Dockerコンテナ内からboto3を使ってAWS S3のバケット名を取得する

上記の事前準備が終われば、本題であるDockerコンテナからboto3を使ってAWS S3のバケット名を取得する方法を紹介していきます。

今回使用するファイルやディレクトリ構成は以下になります。

```
.
├── infra
│   └── Dockerfile
│   └── .vault_password
│	  └── .aws
│	       └── config
│        └── credentials
└── run.py
```

一つ一つ上記のファイルを紹介していく。
`.aws/config`は、コンテナからaws cliを使う際に必要となるAWSの設定情報を記載したファイルである。以下のような形式で記載をしておく。

```:config
[profile hoge]
output = json
region = ap-northeast-1
```

`.aws/credentials `にはAWSの認証情報(`aws_access_key_id`と`aws_secret_access_key`）が記載されている。

```:credentials
[hoge]
aws_access_key_id = fugafuga
aws_secret_access_key = piyopiyo
```
このままだと、認証情報が丸見えなのでansibleで暗号化した状態にしておく必要がある。
ansibleで暗号化する際は以下のコマンドをターミナルで実行する。
passwordの設定及び確認が求められるので、入力する。

```
ansible-vault encrypt file名
New Vault password: 
Confirm New Vault password: 
```

そして、上記で暗号化する際に入力したpasswordを`.vault_password`に記載をしておく。
このpasswordは後ほど暗号化された認証情報を復元する際に必要になります。

```:.vault_password
password
```


`Dockerfile`は、今回作成するコンテナの環境を構築するためのファイル。
使用しているイメージは先でECRにプッシュしたイメージになりますので、適切なimage URLをコピペする。

```Dockerfile:Dockerfile
FROM hogehoge.ecr.ap-northeast-1.amazonaws.com/python:latest

# userの作成
RUN groupadd -g 10000 test && \
    useradd  -u 10000 -g test -s /bin/bash test && \
    echo 'test:test' | chpasswd

ENV HOME /home/test
WORKDIR $HOME
RUN chown test:test -hR ./

USER test

ADD --chown=test:test infra/ $HOME

# 暗号化されているaws認証情報を復元する
RUN ansible-vault decrypt .aws/credentials --vault-password-file .vault_password

ADD --chown=test:test . test
USER root
WORKDIR /home/test/test

CMD ["python", "run.py"]

```

コンテナ内のディレクトリ構成としては、以下の様になっています。
`home/test`内は、インフラの構成部、`home/test/test`内はアプリケーション部として役割を分けるためにこの様な構成にしています。（あまりこだわらない方は適当に`ADD`してください）

```
home
└──test
    ├── Dockerfile
    ├── .aws
    │    ├── config
    │    └── credentials
    ├── .vault_password
    └── test
         ├── infra
         │    ├── Dockerfile
         │    ├── .aws
         │    │    ├── config
         │    │    └── credentials
         │    └ .vault_password
         └── run.py 
```

`run.py`は、boto3でAWS S3のバケット一覧を取得するコードが記載されています。

```python:run.py
from boto3.session import Session

def get_bucket_list():
    resource = Session(profile_name="hoge").resource("s3")

    for bucket in resource.buckets.all():
        print(bucket.name)

if __name__ == '__main__':
    get_bucket_list()

```

これで必要なファイルが揃ったので早速イメージのビルド~コンテナの作成と起動をして、AWS S3のバケット一覧を取得する。

```
# イメージをビルドする
docker build -t test -f infra/Dockerfile .

# イメージがビルドされたのを確認
docker image ls

REPOSITORY   TAG        IMAGE ID            CREATED             SIZE
test         latest     c42e52280332        57 seconds ago      811MB

# コンテナの作成と起動
docker container run -it test 
s3のバケット名

# コンテナ内に入る
docker container run -it test /bin/bash
# aws cliを使ってs3のバケット名を取得
root@:~/test# aws s3 ls --profile hoge
s3のバケット名
```

これで、コンテナ内からAWS S3に接続できたことが確認できました。
Dockerfileでは`CMD`でrun.pyを実行するところまで行っていますが、`bin/bash`でコンテナの中に入り、あらかじめインストールしておいた`aws cli`を使ってでもAWS S3のバケット名を取得することが可能です。


## 終わりに

今回は、AWS ECRにプッシュしたイメージをローカルのコンテナにプルしてアプリケーションを実行しているだけですが、AWS ESCやAWS Batchを使ってクラウド環境でアプリケーションを実行することも可能です。
この記事の続きとして、AWS Btach / ECSを使ってAWS CloudWatchにS3のバケット名を出力させる記事も作成しますので合わせて読んでいただければAWSやDockerの勉強になると思います。