Terraformでdockerコンテナをデプロイしてみた

# Terraformでdockerコンテナをデプロイしてみた

## はじめに

普段、Ansibleで自動化開発を進めてますが来年(もう今年)からTerraformも扱いそうなので、AI先生にハンズオンのチュートリアルを作成してもらって、実際にTerraformの基礎的なコマンドを触ってみました。  
また、できるだけお金をかけずに楽に体験したかったところ、Terraformでdockerコンテナが作成できるとのことだったので、今回はクラウド環境ではなくローカルにdockerコンテナをデプロイしてみるハンズオンにしました。

## ゴールと目的

1. TerraformでDockerコンテナをデプロイするまでの一連の流れを理解する
2. 基本的なTerraformコマンド(init,plan,apply,destroy)を学習する

まずは触って理解することに焦点を当てました。なので、細かいtfファイルの書き方やTerraformのベストプラクティス云々的なものは後回しにしてます。

## 前提条件

- 開発環境
  - Windows 10
    - localに`Terraform Version: 1.10.3`をインストール
  - Docker Desktop
    - dockerhubからイメージをpullするため、ログインが必要です
> 今回は、Docker DesktopとTerraformのインストールは割愛します


## ハンズオン

### Terraformの定義ファイルを作成

1. Terraformをインストールしたフォルダ内に`main.tf`ファイルを作成します

  ```terraform
  terraform {
    required_providers {
      docker = {
        source  = "kreuzwerker/docker"
        version = ">= 2.0.0"
      }
    }

    required_version = ">= 1.3.0"
  }

  provider "docker" {}

  resource "docker_image" "nginx" {
    name         = "nginx:latest"
    keep_locally = false
  }

  resource "docker_container" "nginx" {
    image = docker_image.nginx.image_id
    name  = "terraform-nginx"
    ports {
      internal = 80
      external = 8080
    }
  }
  ```

  - `terraform`ブロック : <br>Terraformで必要なプロバイダーやバージョンを指定します
    - `required_providers` : <br>Terraformに使用するプロバイダーを指定し、Terraformがそのプロバイダーを自動的にダウンロード・インストールできるようにします。<br>今回はdockerコンテナを作成するので、`docker`を使用します。
      -  `source` : <br>dockerプロバイダーのソースである`kreuzwerker/docker`を指定します。
      -  `version` : <br>`kreuzwerker/docker`のバージョン2.0.0以上を使用します。
    - `required_version` : <br>Terraform自体のバージョンを指定します。今回は1.3.0以上に制限しています。
  - `provider`ブロック : <br>実際にそのプロバイダー(今回なら`docker`)を使用する際の設定を記述します。<br>ここではプロバイダー固有の設定（APIエンドポイント、認証情報など）を記載しますが、今回は特に設定が必要ないため空のブロックになっています。
  - `resource "docker_image"` : <br>Dockerイメージを定義します。今回はnginxのイメージを使用します。
    - `name` : <br>使用するDockerイメージの名前とタグです。
    - `keep_locally` : <br>イメージをローカルで保持するかを定義します。今回は`false`で設定しています。
  - `resource "docker_container"` : <br>Dockerコンテナを定義します。
    - `image` : <br>使用するDockerイメージを指定します。この例では、`docker_image.nginx.image_id`と定義して作成したnginxのdockerイメージを指定しています。
    - `name` : <br>作成するコンテナの名前を指定します(今回は`terraform-nginx`と命名)。
    - `ports` : <br>コンテナ内のポート（80）をホストのポート（8080）にマッピングしています。

### Terraformでdockerコンテナをデプロイする

Terraformコマンドを実行して、nginxのdockerコンテナを作成していきます。
今回は以下のコマンドを実行していきます。

```txt
・terraform init
・terraform plan
・terraform apply
```

> :warning: 今回はWindows環境でTerraformを動かしているため、コマンドプロンプトでの実行になります(Linuxベースのgit bashなどでは操作できない)  
> :warning: Terraformをインストールしたフォルダでしか実行できません(~~理由は調べていない~~)ので、今回は対象フォルダ作らずにTerraformをインストールしたフォルダでチュートリアルを進めます。

1. まずは、`terraform init`コマンドで作業ディレクトリを初期化し、必要なプラグインをダウンロードします。
  - コマンド

    ```terminal
    $ terraform init
    ```

  - `Terraform has been successfully initialized!`と表示されたらOKです。

2. 次に、`terraform plan`コマンドでTerraformの設定ファイル(`main.tf`)に基づいて、これから実行される変更内容を確認します。
  - コマンド

    ```terminal
    $ terraform init
    ```

  - `Terraform will perform the following actions:`というテキストに続いて、<br>`# docker_container.nginx will be created`と`# docker_image.nginx will be created`表示されて、各リソースで作られる詳細が記載されていればOKです。

 `terraform apply`コマンドを使って、実際に`terraform plan`で確認した変更内容でコンテナをデプロイさせましょう。
  - コマンド

    ```terminal
    $ terraform apply
    ```

  - `Do you want to perform these actions?`と聞かれるので、変更内容に問題がなければ`Enter a value:`で`yes`と入力します。
  - `Apply complete! Resources: 2 added, 0 changed, 0 destroyed.`と表示されたらOKです。

### デプロイしたdockerコンテナの動作確認

実際に作成したnginxのdockerコンテナの動作確認をしてみましょう。
ブラウザで`http://localhost:8080`にアクセスし、Nginxのウェルカムページが表示されることを確認します。
また、`docker ps`コマンドを実行して、作成した`terraform-nginx`が存在することも確認してみましょう。

### dockerコンテナの削除

最後に、作成したdockerコンテナのお掃除をします。
Terraformでは、作成したリソースの削除は`terraform destroy`コマンドを使用します。

- コマンド

  ```terminal
  $ terraform destroy
  ```

- `Do you really want to destroy all resources?`と聞かれるので、変更内容に問題がなければ`Enter a value:`で`yes`と入力します。
- `Destroy complete! Resources: 2 destroyed.`と表示されたらOKです。

## 補足

### dockerプロバイダーで[kreuzwerker/docker](https://registry.terraform.io/providers/kreuzwerker/docker/3.0.2)を使用している背景

実は、dockerプロバイダにはdockerから出されている[docker/docker](https://registry.terraform.io/providers/docker/docker/0.4.0)も存在するのですが、活発に開発・メンテナンスされてるのは[kreuzwerker/docker](https://registry.terraform.io/providers/kreuzwerker/docker/3.0.2)のほうらしく、**kreuzwerker/docker**のほうが推奨されているらしいです(実際に**docker/docker**のdocでもそっちを推してる)。

### **main.tf**における`image = docker_image.nginx.image_id`について

`image = docker_image.nginx`までは作成したnginxイメージのリソースを差してるのはわかったんですが、その後ろの`.image_id`という記載がなんでもやもやしてたんですよね。なので、Gemini先生に聞いてみると以下の回答をいただきました。

```txt
質問のポイント: image = docker_image.nginx.image_idとは？
この行は、コンテナにどのイメージを使うかを指定しています。

.image_id: このイメージの一意な識別子（ID）を取得するための属性です。
つまり、この行は「'terraform-nginx'という名前のコンテナは、'nginx'という名前で作成したDockerイメージを使って起動する」ということを意味しています。
```

ふ～～ん？  
...勉強します！ww

## まとめ

今回はdockerコンテナのデプロイを通じて、基本的なTerraformコマンドについて実際にハンズオンで学習しました。とはいえ、tfファイルのお作法がまだ理解できてなく意外と時間がかかりました(年越しを検証で過ごした)...。今後は業務でもTerraformに触れていくので、更にTerraform~~で遊んで~~の理解を深めたいと思います。