先日の記事で、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