【Docker】Terraform+AWS CLI+DooD環境を構築

AWSの環境構築をTerraformで行う際に、環境依存やバージョン管理を考慮する必要があります。
その管理を簡略化するため、Dockerを用いて環境をコンテナ化します。
また、コンテナ内のTerraformでECRの操作を行うため、DooD(Docker outside of Docker)という仕組みでコンテナ内からDockerの機能が利用できるようにします。

# ターゲット

- TerraforomまたはAWS CLI環境をコンテナ化したい
- Dockerコンテナ内でDockerを使いたい

# Terraformを使う方法

TerraformをDockerコンテナで使用する方法として公式イメージを使用します。
バージョンを固定したい方は、`latest`を置き換えてください。

```Dockerfile:Dockerfile
FROM hashicorp/terraform:latest
```

[HashiCorp公式のDocker Hub](https://github.com/hashicorp/terraform)を参照することで、golang:alpineイメージにセットアップする方法も分かります。

# AWS CLIを使う方法

AWS CLIを使用するには、`glibc`のインストールも必要です。
バージョンは`ENV GLIBC_VER=`で指定してください。(例として2021/9/9時点で最新の`2.34-r0`を指定します。)
今回はAlpine Linuxにインストールする想定で作成しています。また、AWS CLIはv2をインストールします。

```Dockerfile:Dockerfile
FROM golang:alpine

# install glibc
ENV GLIBC_VER=2.34-r0
RUN apk --no-cache add binutils curl && \
curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub && \
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk && \
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk && \
apk add --no-cache glibc-${GLIBC_VER}.apk glibc-bin-${GLIBC_VER}.apk

# install awscliv2
RUN curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip && \
unzip -q awscliv2.zip && \
aws/install
```

# DooDをするための方法

DooDはDocker outside of Dockerの略です。
ホストのDockerソケット`/var/run/docker.sock`をマウントすることで、Dockerコンテナ内からもDockerの機能を使用できるようにすることです。
注意としては、ホストと同じDockerデーモンを使用するためイメージなども共有されます。

Alpine Linuxなど、Dockerコマンドがない場合はインストールが必要です。

```Dockerfile:Dockerfile
FROM golang:alpine

# install Docker CLI
RUN apk update && \
apk add --no-cache docker-cli && \
apk add --no-cache docker-compose
```

`Dockerfile`を使用してコンテナを起動する際は、以下のように`-v`オプションでソケットをマウントします。

```bash
docker run -it -v /var/run/docker.sock:/var/run/docker.sock <IMAGE_ID> /bin/ash
```

おすすめの方法は、`docker-compose.yml`を作成して`volumes`で予め記述することです。

```yml:docker-compose.yml
version: '3'
services:
  dood:
    container_name: dood-container
    build: .
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    entrypoint: ash
    tty: true
```

```bash
docker-compose build --no-cache
docker-compose up -d
docker-compose exec dood /bin/ash
```

# Terraform+AWS CLI+DooDをする

これまで説明した内容をふまえて、Terraform,AWS CLI,Dockerコマンドが使用できるDockerfileを作成します。

```Dockerfile:Dockerfile
FROM hashicorp/terraform:latest

# install Docker CLI
RUN apk update && \
apk add --no-cache docker-cli && \
apk add --no-cache docker-compose

# install glibc
ENV GLIBC_VER=2.34-r0
RUN apk --no-cache add binutils curl && \
curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub && \
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-${GLIBC_VER}.apk && \
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/${GLIBC_VER}/glibc-bin-${GLIBC_VER}.apk && \
apk add --no-cache glibc-${GLIBC_VER}.apk glibc-bin-${GLIBC_VER}.apk

# install awscliv2
RUN curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip && \
unzip -q awscliv2.zip && \
aws/install
```

`docker-compose.yml`で作成したDcokerfileのフォルダパスを指定します。(例では同じ階層にある想定です。)
また、DooDのために`volumes`で`/var/run/docker.sock`をマウントします。

```yml:docker-compose.yml
version: '3'
services:
  terraform:
    container_name: terraform-container
    build: .
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    entrypoint: ash
    tty: true
```

コンテナを立ち上げてみましょう。

```bash
docker-compose build --no-cache
docker-compose up -d
docker-compose exec terraform /bin/ash
```

execで中に入れたら、各ツールが使えるか確かめましょう。
例としてバージョンを確認してみます。

```bash:Terraformバージョン確認
terraform -v
Terraform v1.0.6
```

```bash:Dockerバージョン確認
docker -v
Docker version 20.10.7, build f0df35096d5f5e6b559b42c7fde6c65a2909f7c5
```

```bash:AWSCLIバージョン確認
aws --version
aws-cli/2.2.36 Python/3.8.8 Linux/5.10.16.3-microsoft-standard-WSL2 exe/x86_64.alpine.3 prompt/off
```

# さいごに

Alpine Linuxコンテナをベースに、TerraformやAWS CLIを使用する方法を説明しました。
DooDを組み合わせることで、TerraformでAWSのコンテナ関連サービスを利用する際に役立つのではないかと思いますので、ぜひ利用して頂ければ幸いです。

# 参考

[DooD(Docker outside of Docker)でボリュームマウント](https://www.nullpo.io/2020/05/27/docker-dood-volume/)
[DockerでTerraformを使う](https://zenn.dev/nagi125/articles/8d1488ecfc2f5717756b)
[Alpine ベースのコンテナイメージで AWS CLI v2 を使う](https://kiririmode.hatenablog.jp/entry/20200725/1595621558)