経緯
業務でLaravelをECSを利用して運用しています。
Laravelメンテナンスモードを利用したいと思った時に、ディレクトリをマウントさせるか、イメージに含めるパターンがあると思います。
artisan
コマンドを打てるECSのタスク(コンテナ)も立ち上げていなかったこともあり、今回はイメージに含めるパターンで作成することにしました。
環境
- AWS ECS
構成
- ECSのタスク定義
- nginx + php-fpm
- Jenkins
前提条件
以下のコードは、既にLaravelが動作するイメージが作成できているのが前提になります。
Jenkins Jobファイル
LARAVEL_MAINTENANCE/Jenkinsfile
// Declarative pipeline
pipeline {
agent { label 'built-in' }
parameters {
booleanParam(name: 'MAINTENANCE_BUILD', defaultValue: false, description: 'メンテナンス状態にする(※チェックなしの場合はメンテナンスを解除する)')
}
environment {
// 実行環境
ENV = "<環境 (production | staging)>"
// ECR情報
AWS_ACCOUNT_ID = '<AWS アカウントID>'
AWS_REGION = '<リージョン>'
AWS_ECR = "${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_REGION}.amazonaws.com"
// 作成してあるイメージ名
IMAGE_NAME = "php"
// Dockerビルド作業フォルダ
DOCKER_BUILD_WORKSPACE = 'build_workspace_laravel_maintenance'
// ECS情報
CLUSTER_NAME = 'cluster'
SERVICE_NAME = 'frontend'
}
stages {
stage('作業フォルダ 削除') {
steps {
echo "======== Start!! ========"
deleteDir()
}
}
stage("メンテナンス ON") {
when {
expression {
return params.MAINTENANCE_BUILD
}
}
steps {
// AWS ECRログイン
sh '''#!/bin/bash -xe
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ECR}
'''
sh '''#!/bin/bash -xe
docker pull ${AWS_ECR}/${IMAGE_NAME}:latest
'''
sh '''#!/bin/bash -xe
docker run -e ENV=${ENV} --name ${IMAGE_NAME} -dit ${AWS_ECR}/${IMAGE_NAME}
docker exec ${IMAGE_NAME} php artisan down --render="errors::503" --secret="xxxxxxxxxx"
docker commit ${IMAGE_NAME} ${AWS_ECR}/${IMAGE_NAME}:latest
'''
}
//ステップ終了処理
post {
always {
sh '''#!/bin/bash -xe
docker stop ${IMAGE_NAME}
docker rm ${IMAGE_NAME}
'''
}
}
}
stage("メンテナンス OFF") {
when {
expression {
return !params.MAINTENANCE_BUILD
}
}
steps {
// AWS ECRログイン
sh '''#!/bin/bash -xe
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ECR}
'''
sh '''#!/bin/bash -xe
docker pull ${AWS_ECR}/${IMAGE_NAME}:latest
'''
sh '''#!/bin/bash -xe
docker run -e ENV=${ENV} --name ${IMAGE_NAME} -dit ${AWS_ECR}/${IMAGE_NAME}
docker exec ${IMAGE_NAME} php artisan up
docker commit ${IMAGE_NAME} ${AWS_ECR}/${IMAGE_NAME}:latest
'''
}
//ステップ終了処理
post {
always {
sh '''#!/bin/bash -xe
docker stop ${IMAGE_NAME}
docker rm ${IMAGE_NAME}
'''
}
}
}
stage("Docker プッシュ") {
steps {
// AWS ECRログイン
sh '''#!/bin/bash -xe
aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ECR}
'''
// ECRにプッシュ
sh '''#!/bin/bash -xe
docker push ${AWS_ECR}/${IMAGE_NAME}:latest
'''
// 成功したので過去のイメージを消す
sh '''#!/bin/bash -xe
docker image prune -f
'''
}
}
stage("デプロイ frontend(Rolling Update)") {
steps {
// ローリングアップデート実行
sh """
aws ecs update-service \
--cluster $CLUSTER_NAME \
--service $SERVICE_NAME_FRONT \
--platform-version 1.4.0 \
--force-new-deployment
"""
// アップデートが完了するまで待つ
sh """
aws ecs wait services-stable \
--cluster $CLUSTER_NAME \
--service $SERVICE_NAME_FRONT
"""
}
}
stage("HDD容量 &ビルドキャッシュクリア") {
steps {
// 容量表示
sh """
df -h
docker system df
"""
// ビルドキャッシュ クリア
sh """
docker builder prune -f
"""
}
}
}
post{
always{
echo "======== Finish!! ========"
}
}
}
メンテナンスにしている部分だけ抜粋
docker run -e ENV=${ENV} --name ${IMAGE_NAME} -dit ${AWS_ECR}/${IMAGE_NAME}
- 環境を指定して、イメージを起動させます
- ここで
artisan
コマンドを渡してしまうと、Webサービスとしては動作しないイメージが出来てしまいました - 使えるイメージにするためPHP-FPMとして起動だけさせます
- ここで
docker exec ${IMAGE_NAME} php artisan down --render="errors::503" --secret="xxxxxxxxxx"
- 起動中のコンテナに対して
artisan
コマンドでメンテナンスモードにします
docker commit ${IMAGE_NAME} ${AWS_ECR}/${IMAGE_NAME}:latest
- 起動中のコンテナからイメージを作成して完了です
最後に
Dockerビルドが実行されないので、Job実行の殆どはECSのデプロイ時間だけになります
既にECS環境で構築済みの場合でも導入しやすいかな?と思っています
誰かの役になっていたら嬉しいです