はじめに
クラウド環境でのアプリケーション開発において、Docker環境の構築は重要なステップです。本記事では、AWSのEC2インスタンス上にTerraformを使用して自動的にDockerとDocker Composeをセットアップする方法を詳しく解説します。セキュリティを重視したプライベートサブネットの利用や、Systems Manager (SSM)によるアクセス管理など、実践的なクラウドインフラ構築のノウハウを学べます。
なぜEC2インスタンスでDockerを使うのか?
- 柔軟性: EC2インスタンス上でDockerを利用することで、様々なアプリケーションやサービスを柔軟にデプロイできます。
- スケーラビリティ: 需要に応じてインスタンスのサイズを変更したり、複数のインスタンスを追加したりすることが容易です。
- コスト効率: 必要な時だけリソースを使用し、不要な時は停止することでコストを最適化できます。
- セキュリティ: プライベートサブネットと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ポートへの着信トラフィックのみを許可しています。
セキュリティ対策の重要ポイント
-
プライベートサブネットの使用: EC2インスタンスはプライベートサブネットに配置され、直接のインターネットアクセスを防いでいます。
-
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] }
-
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パイプラインとの統合や、より複雑なマルチコンテナアプリケーションのデプロイなど、さらなる拡張が考えられます。クラウドネイティブな開発手法を取り入れることで、より効率的で柔軟なアプリケーション開発が可能になるでしょう。
リポジトリ
参考リソース
クラウドインフラストラクチャの自動化に興味がある方は、ぜひこの方法を試してみてください。セキュアで効率的なDocker環境構築のスキルは、現代のソフトウェア開発において非常に価値があります。