概要
- 本記事では CI/CD は実装してないです。すべて手動。
- 手動でやる部分は全て構成図のように CodePipeline で自動化できると思います。
- ALB も省略しています。Fargate に直接アクセスさせます。
C:.
├─docker
│ │ .env
│ │ docker-compose.yml
│ │
│ └─php
│ Dockerfile
│
├─laravel
├─Dockerile.deploy
└─terraform
│ main.tf
└─ task-definitions.json
ローカルで Docker コンテナ作成 ↓ コンテナ内で Laravel プロジェクト作成&ローカル PC のディレクトリにマウント ↓ Fargate にプッシュする際に、ローカル PC のディレクトリにマウントした Laravel プロジェクトをコピーしてプッシュする
ローカル開発環境作成
php/Dockerfile
FROM php:8.2-apache
RUN a2enmod rewrite
RUN docker-php-ext-install pdo_mysql mysqli
RUN apt-get update && apt-get install -y unzip
# Apacheのドキュメントルートを設定
ENV APACHE_DOCUMENT_ROOT /var/www/html/public
# Apacheの各設定ファイルのドキュメントルートを変更
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# composerをDockerHub経由でインストール
COPY --from=composer:2.5.4 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
docker-compose.yml
version: "3.8"
services:
php:
container_name: sphp
build:
context: ./php/
dockerfile: Dockerfile
ports:
- 8080:80
volumes:
- ../laravel:/var/www/html
.env
COMPOSE_PROJECT_NAME=laravel
Docker イメージビルド&コンテナ立ち上げ
イメージビルド&コンテナ立ち上げ
docker-compose up -d
立ち上がったコンテナ内に入り、Laravel プロジェクトを作成する
composer create-project --prefer-dist laravel/laravel .
laravel ディレクトリにプロジェクトが作成されていることを確認 
バージョン確認
# php artisan -V
Laravel Framework 10.1.5
AWS デプロイ(デベロッパー)
コードの更新。ECR を更新 ※ローカル PC の AWS CLI はセッティング済みとします ※ECR リポジトリは作成済みとします
Dockerfile.deploy
FROM php:8.2-apache
RUN a2enmod rewrite
RUN docker-php-ext-install pdo_mysql mysqli
RUN apt-get update && apt-get install -y unzip
# Apacheのドキュメントルートを設定
ENV APACHE_DOCUMENT_ROOT /var/www/html/public
# Apacheの各設定ファイルのドキュメントルートを変更
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
# composerをDockerHub経由でインストール
COPY --from=composer:2.5.4 /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
# ローカルのlaravelディレクトリをコンテナ内にコピー
COPY laravel/ /var/www/html/
# アクセス権限エラーの回避
RUN chmod -R 775 /var/www/html/storage && \
chown -R www-data:www-data /var/www/html/storage
ECR にログイン&プッシュ
※AWS コンソールの ECR の画面に以下で行うプッシュコマンドが表示されています
# ECRログイン
aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin 828642921232.dkr.ecr.ap-northeast-1.amazonaws.com
# イメージをビルド(Dockerfile.deployのあるディレクトリまで移動しておいてください)
docker build -t laravel -f Dockerfile.deploy .
# ECRにプッシュする用にタグ付け
docker tag laravel:latest 828642921232.dkr.ecr.ap-northeast-1.amazonaws.com/smatag-laravel:latest
# ECRにプッシュ
docker push 828642921232.dkr.ecr.ap-northeast-1.amazonaws.com/laravel:latest
AWS デプロイ(インフラ)
Fargate とネットワーク周りのデプロイ ※Terraform インストール済み
terraform/main.tf
####################################
## プロバイダー設定
####################################
# Terraform のバージョン指定
terraform {
required_version = "~> 1.3.0"
}
# プロバイダーを指定
provider "aws" {
region = "ap-northeast-1"
}
####################################
## 環境変数の設定
####################################
## プレフィックス
variable "project_name" {
type = string
default = "laravel"
}
####################################
## リソースの定義
####################################
# VPCの作成(Terraform Registryの使用)
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "3.10.0"
name = "${var.project_name}-vpc"
cidr = "10.0.0.0/16"
enable_dns_hostnames = true
enable_dns_support = true
azs = ["ap-northeast-1a", "ap-northeast-1c"]
public_subnets = ["10.0.11.0/24", "10.0.12.0/24"]
#デフォルトセキュリティグループのルール削除
manage_default_security_group = true
default_security_group_ingress = []
default_security_group_egress = []
}
# ECSタスクがECRリポジトリを見れる用のIAMロール作成
data "aws_iam_policy_document" "default" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ecs-tasks.amazonaws.com"]
}
}
}
resource "aws_iam_role" "default" {
name = "MyEcsTaskRole"
assume_role_policy = data.aws_iam_policy_document.default.json
}
resource "aws_iam_role_policy_attachment" "default" {
role = aws_iam_role.default.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
}
# タスク定義
resource "aws_ecs_task_definition" "default" {
family = "${var.project_name}-task"
#0.25vCPU
cpu = "256"
#0.5GB
memory = "512"
network_mode = "awsvpc"
requires_compatibilities = ["FARGATE"]
container_definitions = file("./task-definitions.json")
execution_role_arn = aws_iam_role.default.arn
}
# クラスター
resource "aws_ecs_cluster" "default" {
name = "${var.project_name}-cluster"
}
# サービス
resource "aws_ecs_service" "default" {
name = "${var.project_name}-service"
cluster = aws_ecs_cluster.default.arn
task_definition = aws_ecs_task_definition.default.arn
desired_count = 1
launch_type = "FARGATE"
platform_version = "1.4.0"
network_configuration {
assign_public_ip = true
security_groups = [aws_security_group.default.id]
subnets = module.vpc.public_subnets
}
## デプロイ毎にタスク定義が更新されるため、リソース初回作成時を除き変更を無視
lifecycle {
ignore_changes = [task_definition]
}
}
# セキュリティグループ
resource "aws_security_group" "default" {
name = "${var.project_name}-sg"
description = "sg"
vpc_id = module.vpc.vpc_id
ingress {
from_port = 80
to_port = 80
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"]
}
tags = {
Name = "${var.project_name}-sg"
}
}
terraform/task-definitions.json
※事前に作成した EMR の URI を指定していることに注意
[
{
"name": "laravel",
"image": "828642921232.dkr.ecr.ap-northeast-1.amazonaws.com/laravel:latest",
"essential": true,
"memory": 128,
"portMappings": [
{
"protocol": "tcp",
"containerPort": 80
}
]
}
]
デプロイ
※terraform ディレクトリに移動しておく
# 初回実行時のみ
terraform init
# 事前確認
terraform plan
# デプロイ
terraform apply
デプロイ後の確認
ECS のコンソール画面からパブリック IP を確認できます。 ECS -> クラスター名 -> タスクタブ -> タスク名
パブリック IP にアクセス