dockerでterraform環境を作る

## 概要
AWSを操作するのに、terraformを使ってみようと思い、どこでも使えるようdocker化する

## 前提条件
* macOS
* Docker Toolbox ( Docker for mac )

## ファイル構成
下記のようなファイルを作成します。

```:ファイル構成
opt
　├ docker
　│　└ terraform
　│　   ├ .aws
　│　   │  ├ config.default
　│　   │  └ credentials.default
　│　   ├ Dockerfile
　│　   └ init.sh
　├ src
　│  ├ main.tf
　│  └ variables.tf
　└ docker-compose.yml
```

## terraform構築
dockerコンテナでterraformコマンドが使える環境を作成します。

### Dockerfileの作成

```Dockerfile:./docker/terraform/Dockerfile
FROM python:3.6

ARG pip_installer="https://bootstrap.pypa.io/get-pip.py"
ARG awscli_version="1.16.168"

# install aws-cli
RUN pip install awscli==${awscli_version}

# install sam
RUN pip install --user --upgrade aws-sam-cli
ENV PATH $PATH:/root/.local/bin

# install command.
RUN apt-get update && apt-get install -y less vim wget unzip

# install terraform.
# https://azukipochette.hatenablog.com/entry/2018/06/24/004354
RUN wget https://releases.hashicorp.com/terraform/0.11.13/terraform_0.11.13_linux_amd64.zip && \
    unzip ./terraform_0.11.13_linux_amd64.zip -d /usr/local/bin/

# create workspace.
COPY ./src /root/src

# initialize command.
ARG AWS_ACCESS_KEY_ID
ARG AWS_SECRET_ACCESS_KEY
COPY ./docker/terraform/.aws /root/.aws
COPY ./docker/terraform/init.sh /root/init.sh
RUN chmod +x /root/init.sh && /root/init.sh

WORKDIR /root/src
```

### init.shの作成

下記の内容で作成します。

```bash:docker/terraform/init.sh
#!/bin/bash

source /root/.bashrc

if [[ ! -e /root/.aws/config ]]; then
    mv /root/.aws/config.default /root/.aws/config
fi

if [[ ! -e /root/.aws/credentials ]]; then
    mv /root/.aws/credentials.default /root/.aws/credentials
    sed -i "s/<access-key>/${AWS_ACCESS_KEY_ID}/g" /root/.aws/credentials
    sed -i "s/<secret-key>/${AWS_SECRET_ACCESS_KEY}/g" /root/.aws/credentials
fi
```
※ `AWS_ACCESS_KEY_ID`と`AWS_SECRET_ACCESS_KEY` は外部から渡されます

### AWS設定ファイル
初期設定ファイルを作成する。

```:docker/terraform/.aws/config.default
[default]
region = ap-northeast-1
output = json
```
※ `ap-northeast-1`：東京リージョン

```:docker/terraform/.aws/credentials.default
[default]
aws_access_key_id = <access-key>
aws_secret_access_key = <secret-key>
```
※ `<access-key>`と`<secret-key>`は、init.shで置換します

### docker-compose.ymlの作成

下記の内容で作成します。

```yaml:docker-compose.yml
version: '3'
services:
  terraform:
    container_name: 'terraform'
    image: local/terraform
    build:
      context: ./
      dockerfile: docker/terraform/Dockerfile
      args:
        AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-**********}
        AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-****************}
    #volumes:
    #  - ./src:/root/src
```
※ volumes部分のコメントアウトについて
　 windows環境でterraformのmodules機能などを使うと、シンボリックリンクエラー発生
　 ( mac環境ならコメントアウト外してもいいかと思います )

### dockerイメージ作成
下記コマンドにてdockerイメージを作成する。

```bash:ターミナル
$ export AWS_ACCESS_KEY_ID='xxxxxxxxxxxxx'           # ← 自分のAWcdS Access Key ID
$ export AWS_SECRET_ACCESS_KEY='xxxxxxxxxxxxxxxxxx'  # ← 自分のAWS Secret Access Key
$ docker-compose build
```
※ Dockerfileに情報を渡すため、環境変数を設定してからビルドを実行する。

### dockerコンテナ起動
下記コマンドにてterraformコンテナを起動する。

```bash:ターミナル
# コンテナ起動
$ docker-compose run --rm terraform bash
```

terraformのバージョンを確認する。

```bash:ターミナル
$ terraform --version
Terraform v0.11.13
```

aws-cliのバージョンを確認する。

```bash:ターミナル
$ aws --version
aws-cli/1.16.168 Python/3.6.9 Linux/3.10.0-862.el7.x86_64 botocore/1.12.204
```

## terraform設定
S3バケットを作ってみる簡単な例です。

```tf:main.tf
# AWS設定
provider "aws" {
  region   = "${var.aws["region"]}"
  profile  = "${var.aws["profile"]}"
}

# S3バケットの作成
resource "aws_s3_bucket" "HogeSampleImage" {
  bucket = "hoge-sample-images"
  acl    = "private"
}
```
```tf:variables.tf
variable "aws" {
  default = {
    profile = "default"
    region  = "ap-northeast-1"
  }
}
```

## terraform実行

terraformを初期化して実行計画を確認後に実行します。

```bash:ターミナル
$ terraform init
$ terraform plan
$ terraform apply
```

以上

## その他
### AWSの設定変更について

#### aws configure
コンテナ起動後に設定変更を行う場合は、コンテナ内で以下のコマンドを実行します。

```bash:ターミナル
$ aws configure
AWS Access Key ID [None]: ***********************      # ← 自分のAWcdS Access Key ID
AWS Secret Access Key [None]: ***********************  # ← 自分のAWS Secret Access Key
Default region name [None]: ap-northeast-1
Default output format [None]: json
```
※ 操作に必要な権限があるIAMユーザーの情報をセットする

#### .aws/configファイル

下記ファイルにプロフィールなどの情報を追記する。

```bash:ターミナル
$ vi ~/.aws/config

[default]
region = ap-northeast-1
output = json

[profile hoge]
role_arn = arn:aws:iam::{AWSアカウントID}:role/AllowSwitchRole
source_profile = default
```
※ 上記の例のように、SwitchRoleできるようプロフィールを追記することができます

以上

## 参考サイト
* [HashiCorp - Terraformのインストール](https://learn.hashicorp.com/terraform/getting-started/install.html)
* [HashiCorp - Terraformドキュメント](https://www.terraform.io/docs/index.html)
* [HashiCorp - Terraformの構成言語](https://www.terraform.io/docs/configuration/index.html)
* [HashiCorp - Terraformコマンド](https://www.terraform.io/docs/commands/index.html)
* [Terraformにおけるディレクトリ構造のベストプラクティス](https://dev.classmethod.jp/devops/directory-layout-bestpractice-in-terraform/)
* [Terraformでmappingをmoduleに渡す方法](https://dev.classmethod.jp/cloud/aws/pass-mapping-to-module-in-terraform/)
* [Terraform職人入門: 日々の運用で学んだ知見を淡々とまとめる](https://qiita.com/minamijoyo/items/1f57c62bed781ab8f4d7)
* [Terraformのstate mvを使ってべた書きしたリソースをモジュールに移す](https://mozami.me/2018/05/12/terraform_state_mv.html)
* [TerraformでError reading config for xxxx : Invalid dot index foundエラ…](https://cloudpack.media/27842)