先日の記事で、Azure DevOps の Multi-Stage Pipelines を使って Azure Web Apps と Functions にデプロイする内容を記載しました。
gooner.hateblo.jp
gooner.hateblo.jp
今回は、Azure Storage の Static website 向けのパイプラインを構築します。Static website の場合、カスタムドメインで HTTPS を構成するために、Azure CDN や Front Door を配置する必要があります。今回は、Azure CDN を配置する構成を選択しました。アプリケーションは、Vue.js をデプロイします。
パイプラインの全体設計
先日の記事と同様に、パイプラインは、自動デプロイされる開発環境向け(Commit Stage)と承認デプロイされる本番環境向け(Production Stage)を作ります。YAML を Build と Release を分けて、可変部をパラメータで切り替えできるテンプレートを作ることで再利用性を向上させます。
開発環境向けパイプライン
まずは、パイプライン起動用の azure-pipelines.yml です。
trigger: - master variables: - group: variable-group-commit - name: imageName value: 'ubuntu-latest' - name: nodeVersion value: '10.x' - name: azureSubscription value: 'AzureSponsorships' - name: environment value: 'Commit-Stage' stages: - stage: Build jobs: - template: pipelines/build-pipelines.yml parameters: imageName: $(imageName) nodeVersion: $(nodeVersion) - stage: Release dependsOn: - Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) jobs: - template: pipelines/release-pipelines.yml parameters: imageName: $(imageName) azureSubscription: $(azureSubscription) storageAccountName: $(storageAccountName) environment: $(environment) cdnResourseGroupName: $(cdnResourseGroupName) cdnEndpointName: $(cdnEndpointName) cdnProfileName: $(cdnProfileName)
Azure Web Apps との違いは、Azure Storage と CDN の名前を渡している部分ぐらいで、全体の構成は変わりません。
次に、ビルド用の build-pipelines.yml です。
parameters: imageName: '' nodeVersion: '' jobs: - job: Build pool: vmImage: ${{parameters.imageName}} steps: - task: NodeTool@0 inputs: versionSpec: ${{parameters.nodeVersion}} displayName: 'Install Node.js' - script: | npm install npm run build displayName: 'npm install and build' - task: ArchiveFiles@2 inputs: rootFolderOrFile: '$(Build.SourcesDirectory)/dist' includeRootFolder: false archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildNumber).zip' replaceExistingArchive: true displayName: 'Archive artifact' - task: PublishBuildArtifacts@1 inputs: PathtoPublish: '$(Build.ArtifactStagingDirectory)' ArtifactName: 'webapp' publishLocation: 'Container' displayName: 'Publish artifact'
Node.js Tool Installer task で npm コマンドでインストールとビルドを行い、Archive Files task で dist ディレクトリに出力されたファイル群を zip にまとめています。
最後に、Publish Build Artifacts task で、リリースパイプラインに渡すための zip をアーティファクトへ発行しています。
最後に、リリース用の release-pipelines.yml です。
parameters: imageName: '' azureSubscription: '' storageAccountName: '' environment: '' cdnResourseGroupName: '' cdnEndpointName: '' cdnProfileName: '' jobs: - deployment: Deploy_Static_Website_with_Azure_Storage displayName: 'Release' pool: vmImage: ${{parameters.imageName}} environment: ${{parameters.environment}} strategy: runOnce: deploy: steps: - script: | wget https://aka.ms/downloadazcopy-v10-linux tar -xvf downloadazcopy-v10-linux cp ./azcopy_linux_amd64_*/azcopy ./ displayName: 'Install AzCopy v10' - task: ExtractFiles@1 inputs: archiveFilePatterns: '$(Pipeline.Workspace)/**/*.zip' destinationFolder: '$(Pipeline.Workspace)/deploy' cleanDestinationFolder: true displayName: 'Extracting site content' - task: AzureCLI@1 inputs: azureSubscription: ${{parameters.azureSubscription}} scriptLocation: 'inlineScript' inlineScript: | end=`date -d "5 minutes" '+%Y-%m-%dT%H:%M:%SZ'` sas=`az storage container generate-sas -n '$web' --account-name $1 --https-only --permissions dlrw --expiry $end -otsv` ./azcopy sync "$(Pipeline.Workspace)/deploy/" "https://$1.blob.core.windows.net/\$web?$sas" --recursive --delete-destination=true arguments: ${{parameters.storageAccountName}} displayName: 'Deploy to Static Website with Azure Storage' - task: AzureCLI@1 inputs: azureSubscription: ${{parameters.azureSubscription}} scriptLocation: 'inlineScript' inlineScript: | az cdn endpoint purge -g ${{parameters.cdnResourseGroupName}} -n ${{parameters.cdnEndpointName}} --profile-name ${{parameters.cdnProfileName}} --content-paths '/*' displayName: 'Purge content for a CDN endpoint'
デプロイする Vue.js アプリケーションのファイル群は、AzCopy v10 を使って Blob Storage にアップロードしたいので、まずはインストールです。
インストールが完了したら、Extract Files task でビルドパイプラインから渡されたアーティファクトの zip を解凍し、AzCopy でアップロードします。
AzCopy は copy コマンドではなく、sync コマンドを使うことで、ファイルの削除や移動を気にせずにデプロイできます。Blob Storage へのアクセスには、Azure CLI task で SAS を発行して、一時的な権限を発行しています。
デプロイ自体はこれで完了ですが、最後に Azure CDN のエンドポイントにあるコンテンツを Purge しています。これでパイプライン完了後、Vue.js アプリケーションの更新をすぐに反映できます。
本番環境向けパイプライン
パイプライン起動用の azure-pipelines-production.yml です。
trigger: - production variables: - group: variable-group-production - name: imageName value: 'ubuntu-latest' - name: nodeVersion value: '10.x' - name: azureSubscription value: 'AzureSponsorships' - name: environment value: 'Production-Stage' stages: - stage: Build jobs: - template: pipelines/build-pipelines.yml parameters: imageName: $(imageName) nodeVersion: $(nodeVersion) - stage: Release dependsOn: - Build condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/production')) jobs: - template: pipelines/release-pipelines.yml parameters: imageName: $(imageName) azureSubscription: $(azureSubscription) storageAccountName: $(storageAccountName) environment: $(environment) cdnResourseGroupName: $(cdnResourseGroupName) cdnEndpointName: $(cdnEndpointName) cdnProfileName: $(cdnProfileName)
トリガーとなるブランチが production
となっている箇所が開発環境向けパイプラインとの違いです。
Azure Web Apps の Deployment Slot 機能のような機能がないので、そのままデプロイしています。承認デプロイは使いたいので、承認設定した Environments を Production-Stage
で登録しておきます。
まとめ
Azure DevOps の Multi-Stage Pipelines を使って、Azure Storage の Static website 向けのパイプラインを構築してみました。
Vue.js のような静的な Web アプリケーションの場合、Azure Web Apps を使う選択肢も十分に考慮しておきたいところです。
- Azure CDN や Front Door を必須にしたくない
- Blue / Green デプロイを実現したい(Deployment Slot 機能)
- Easy Auth 機能で認証したい
- Application Insight のモニタリングを活用したい
このような要件がある場合には、リリースパイプラインを Web Apps 向けに差し替えて使ってください。
こちらから、パイプライン YAML の全体を確認できます。
github.com