Terraformを使用してAWS上にStreamlitアプリケーションをデプロイする方法

## はじめに

この記事では、Terraformを使用してAWS上にStreamlitアプリケーションをデプロイする方法を詳しく解説します。VPCの設定からEC2インスタンスの起動、そしてStreamlitアプリケーションの自動デプロイまでを一つのTerraformスクリプトで実現します。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">Terraform+Claude 3.5 SonnetでIaCデビュー<br>ワンパンでインスタンスの構築＋アプリのデプロイしてみた！！<br>これはめちゃ楽しい！！！<br>＊さらにワンパンで作成した環境を一瞬で消し去れるのも助かる！！ <a href="https://t.co/AwZjO0KMGq">pic.twitter.com/AwZjO0KMGq</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1821208276429951007?ref_src=twsrc%5Etfw">August 7, 2024</a></blockquote> 

## 前提条件

- AWSアカウント
- Terraformがインストールされていること
- AWS CLIがインストールされ、設定されていること

## 手順

### 1. IAMユーザーの作成

まず、Terraformの実行に必要な権限を持つIAMユーザーを作成します。

1. IAMユーザー名: `streamlit-terraform-deployer`
2. 必要な権限:
   - AmazonVPCFullAccess
   - AmazonEC2FullAccess
   - カスタムポリシー（詳細は省略）

### 2. AWS CLIの設定

作成したIAMユーザーの認証情報を使用してAWS CLIを設定します。

```bash
aws configure --profile streamlit-deployer
```

プロンプトに従って、アクセスキーID、シークレットアクセスキー、リージョン（ap-northeast-1）を入力します。

### 3. キーペアの作成

EC2インスタンスにSSH接続するためのキーペアを作成します。

キーペア名: `streamlit-terraform-keypair-tokyo`

AWSコンソールのEC2ダッシュボードで作成してください。

### 4. Terraformスクリプトの作成

`streamlit_aws_setup.tf`というファイル名で以下のTerraformスクリプトを作成します。

```hcl
# プロバイダーの設定
provider "aws" {
  region = "ap-northeast-1"  # 東京リージョン
}

# VPCの作成
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "streamlit-vpc"
  }
}

# パブリックサブネットの作成
resource "aws_subnet" "public" {
  vpc_id     = aws_vpc.main.id
  cidr_block = "10.0.1.0/24"
  availability_zone = "ap-northeast-1a"
  map_public_ip_on_launch = true
  tags = {
    Name = "streamlit-subnet"
  }
}

# インターネットゲートウェイの作成
resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id
  tags = {
    Name = "streamlit-igw"
  }
}

# ルートテーブルの作成
resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.main.id
  }
  tags = {
    Name = "streamlit-rt"
  }
}

# サブネットとルートテーブルの関連付け
resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

# セキュリティグループの作成
resource "aws_security_group" "streamlit" {
  name        = "streamlit-sg"
  description = "Security group for Streamlit server"
  vpc_id      = aws_vpc.main.id

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 8501
    to_port     = 8501
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

# EC2インスタンスの作成
resource "aws_instance" "streamlit" {
  ami           = "ami-0d52744d6551d851e"  # Ubuntu 22.04 LTS (HVM), SSD Volume Type
  instance_type = "t2.micro"
  key_name      = "streamlit-terraform-keypair-tokyo"
  vpc_security_group_ids = [aws_security_group.streamlit.id]
  subnet_id     = aws_subnet.public.id

  tags = {
    Name = "streamlit-server"
  }

  user_data = <<-EOF
              #!/bin/bash
              sudo apt update
              sudo apt install -y python3-pip
              pip3 install streamlit

              # Create a simple Streamlit app
              cat <<EOT > /home/ubuntu/app.py
              import streamlit as st

              st.title('Simple Streamlit App')
              name = st.text_input('Enter your name')
              if name:
                  st.write(f'Hello, {name}!')
              
              number = st.slider('Select a number', 0, 100)
              st.write(f'You selected: {number}')
              EOT

              # Run the Streamlit app
              nohup streamlit run /home/ubuntu/app.py --server.port 8501 --server.address 0.0.0.0 &
              EOF
}

# Elastic IPの割り当て
resource "aws_eip" "streamlit" {
  instance = aws_instance.streamlit.id
  domain   = "vpc"
}

# 出力
output "public_ip" {
  value = aws_eip.streamlit.public_ip
}
```

### 5. Terraformの実行

以下のコマンドを順番に実行します：

```bash
export AWS_PROFILE=streamlit-deployer
terraform init
terraform plan
terraform apply
```

`terraform apply`の実行時に`yes`と入力して、リソースの作成を承認します。

### 6. アプリケーションへのアクセス

Terraformの実行が完了すると、出力にEC2インスタンスのパブリックIPアドレスが表示されます。ブラウザで`http://<パブリックIPアドレス>:8501`にアクセスすると、Streamlitアプリケーションが表示されます。

## リソースの削除

作成したリソースを削除する場合は、以下のコマンドを実行します：

```bash
terraform destroy
```

確認メッセージが表示されたら、`yes`と入力して削除を承認します。

## まとめ

この記事では、Terraformを使用してAWS上にStreamlitアプリケーションをデプロイする方法を解説しました。VPCの設定、EC2インスタンスの起動、Streamlitアプリケーションの自動デプロイまでを一つのスクリプトで実現できることがわかりました。

この方法を使うことで、インフラストラクチャをコードとして管理し、簡単に再現可能な環境を構築できます。さらに、このスクリプトをベースにして、より複雑なアプリケーションやインフラストラクチャの構築にも応用できるでしょう。

## 注意点

- セキュリティグループの設定は、本番環境ではより厳密に行う必要があります。
- AMI IDは定期的に更新されるため、最新のIDを使用するようにしてください。
- 作業完了後は、不要なリソースを削除してコストを抑えることを忘れずに。

以上で、Terraformを使用してAWS上にStreamlitアプリケーションをデプロイする方法の解説を終わります。ハッピーコーディング！

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>