0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Laravel メンテナンスモードをJenkinsで実装してみた

Posted at

経緯

業務で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環境で構築済みの場合でも導入しやすいかな?と思っています

誰かの役になっていたら嬉しいです

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?