👍

TerraformとAWSで実現する安全なDocker環境: EC2インスタンスの自動セットアップガイド

2024/08/28に公開

はじめに

クラウド環境でのアプリケーション開発において、Docker環境の構築は重要なステップです。本記事では、AWSのEC2インスタンス上にTerraformを使用して自動的にDockerとDocker Composeをセットアップする方法を詳しく解説します。セキュリティを重視したプライベートサブネットの利用や、Systems Manager (SSM)によるアクセス管理など、実践的なクラウドインフラ構築のノウハウを学べます。

なぜEC2インスタンスでDockerを使うのか?

  1. 柔軟性: EC2インスタンス上でDockerを利用することで、様々なアプリケーションやサービスを柔軟にデプロイできます。
  2. スケーラビリティ: 需要に応じてインスタンスのサイズを変更したり、複数のインスタンスを追加したりすることが容易です。
  3. コスト効率: 必要な時だけリソースを使用し、不要な時は停止することでコストを最適化できます。
  4. セキュリティ: プライベートサブネットとNAT Gatewayを使用することで、セキュアな環境を構築できます。

Terraformを使ったEC2インスタンスのセットアップ手順

環境準備

  • Terraformのインストール
  • AWS CLIのセットアップと認証情報の設定

Terraformの設定

プロジェクトディレクトリに移動し、必要なファイルを準備します:

cd s08_ec2_docker
cp terraform.tfvars.example terraform.tfvars

terraform.tfvarsファイルを編集して、プロジェクト固有の設定を行います:

aws_region         = "ap-northeast-1"
project_name       = "my-docker-compose-project"
vpc_cidr           = "10.0.0.0/16"
private_subnet_cidr = "10.0.1.0/24"
ami_id             = "ami-0d52744d6551d851e"
instance_type      = "t3.medium"
key_name           = "your-ssh-key-name"

インフラストラクチャのデプロイ

以下のコマンドを実行して、インフラストラクチャをデプロイします:

terraform init
terraform plan
terraform apply

主要なTerraformコードの解説

VPCの作成

resource "aws_vpc" "main" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = {
    Name = "${var.project_name}-vpc"
  }
}

このコードブロックでは、指定したCIDRブロックを持つVPCを作成し、DNSホスト名とDNSサポートを有効にしています。

EC2インスタンスの作成

resource "aws_instance" "app_server" {
  ami                    = var.ami_id
  instance_type          = var.instance_type
  subnet_id              = aws_subnet.private.id
  vpc_security_group_ids = [aws_security_group.ec2.id]
  iam_instance_profile   = aws_iam_instance_profile.ec2_profile.name
  key_name               = var.key_name

  user_data = <<-EOF
              #!/bin/bash
              # Docker and Docker Compose installation script
              ...
              EOF

  tags = {
    Name = "${var.project_name}-ec2"
  }
}

このリソースブロックでは、指定したAMIとインスタンスタイプを使用してEC2インスタンスを作成します。user_dataセクションでは、インスタンス起動時にDockerとDocker Composeをインストールするスクリプトを定義しています。

セキュリティグループの設定

resource "aws_security_group" "ec2" {
  name        = "${var.project_name}-ec2-sg"
  description = "Security group for EC2 instance"
  vpc_id      = aws_vpc.main.id

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

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = [var.vpc_cidr]
  }

  tags = {
    Name = "${var.project_name}-ec2-sg"
  }
}

このセキュリティグループは、EC2インスタンスに適用されます。すべての送信トラフィックを許可し、VPC内からの443ポートへの着信トラフィックのみを許可しています。

セキュリティ対策の重要ポイント

  1. プライベートサブネットの使用: EC2インスタンスはプライベートサブネットに配置され、直接のインターネットアクセスを防いでいます。

  2. NAT Gatewayの利用: プライベートサブネット内のインスタンスがインターネットにアクセスするためのNAT Gatewayを設定しています。

    resource "aws_nat_gateway" "main" {
      allocation_id = aws_eip.nat.id
      subnet_id     = aws_subnet.public.id
    
      tags = {
        Name = "${var.project_name}-nat-gw"
      }
    
      depends_on = [aws_internet_gateway.main]
    }
    
  3. Systems Manager (SSM)の使用: SSHポートを開放せずにインスタンスにアクセスするため、SSMを利用しています。

    resource "aws_vpc_endpoint" "ssm" {
      vpc_id              = aws_vpc.main.id
      service_name        = "com.amazonaws.${var.aws_region}.ssm"
      vpc_endpoint_type   = "Interface"
      private_dns_enabled = true
    
      subnet_ids         = [aws_subnet.private.id]
      security_group_ids = [aws_security_group.ec2.id]
    }
    

SSH接続の設定と使用方法

開発やトラブルシューティングの際に、EC2インスタンスにSSH接続する必要がある場合があります。以下に、SSH接続を行うための手順と注意点を説明します。

セキュリティグループの設定

SSH接続を許可するには、セキュリティグループにSSHポート(22)のインバウンドルールを追加する必要があります。セキュリティ上の理由から、特定のIPアドレスからのみアクセスを許可することをおすすめします。

resource "aws_security_group" "ec2" {
  # ...既存の設定...

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["YOUR_IP_ADDRESS/32"]  # あなたのIPアドレスを指定
  }

  # ...
}

SSH接続の実行

インスタンスが起動し、セキュリティグループが適切に設定されたら、以下のコマンドでSSH接続を行うことができます:

ssh -i "C:\Users\makim\.ssh\streamlit-terraform-keypair-tokyo-PEM.pem" ubuntu@i-0f9cd7c06ab7abeea

このコマンドの各部分を解説します:

  • -i "C:\Users\makim\.ssh\streamlit-terraform-keypair-tokyo-PEM.pem": 秘密キーファイルのパスを指定します。
  • ubuntu: EC2インスタンスのデフォルトユーザー名です(AMIによって異なる場合があります)。
  • i-0f9cd7c06ab7abeea: EC2インスタンスのIDです。これはパブリックDNS名やパブリックIPアドレスに置き換えることもできます。

注意点とベストプラクティス

  • セキュリティ: SSHポートを公開することはセキュリティリスクを伴います。可能な限り、Systems Manager Session Managerなどのマネージドサービスを使用することをおすすめします。
  • 一時的なアクセス: 開発やデバッグ目的でSSHアクセスが必要な場合は、作業が終わったら速やかにセキュリティグループのSSHルールを削除してください。
  • キーの管理: SSHキーペアは安全に管理し、決して公開リポジトリにコミットしないようにしてください。

まとめ

TerraformとAWSを組み合わせることで、セキュアで効率的なDocker環境を自動的に構築できることがわかりました。この方法は、開発環境から本番環境まで幅広く適用可能で、クラウドインフラストラクチャの管理を大幅に簡素化します。

今後のステップとして、CI/CDパイプラインとの統合や、より複雑なマルチコンテナアプリケーションのデプロイなど、さらなる拡張が考えられます。クラウドネイティブな開発手法を取り入れることで、より効率的で柔軟なアプリケーション開発が可能になるでしょう。

リポジトリ

https://github.com/Sunwood-ai-labs/aws-terraform-sandbox

参考リソース

クラウドインフラストラクチャの自動化に興味がある方は、ぜひこの方法を試してみてください。セキュアで効率的なDocker環境構築のスキルは、現代のソフトウェア開発において非常に価値があります。

Discussion