Strapi のコンテンツ追加/更新/削除時にVercelのデプロイをする
今回は、Strapi のコンテンツ追加/更新/削除時にVercelのデプロイ処理を実行させる方法についてまとめました。
発端は、Webフロント側をSSGでの実装をしていたために、単にStrapiのコンテンツを追加してもサイトに反映されなかったためです(再デプロイが必要)。これを解決するために、Strapi のコンテンツ追加/更新/削除時にVercelの再デプロイを行う実装をStrapi側に追加しました。
環境
Strapi を開発環境と本番環境のDockerで動かしたい【まとめ版】で VPS上に Strapi 環境を構築しています。
コンテンツを表示させるフロント側のWebサイトは Vercel を利用してデプロイしています。
Vercel の Deploy Hook を利用する
まずは、追加/更新/削除時に再デプロイを行いたい Content-Types に lifecycles.ts
を追加します。
# Strapiのプロジェクトに移動する
$ cd ~/StrapiProjects/vps-docker-strapi
# Hookを利用したい Content-Types に lifecycles.ts を追加する
$ touch src/api/news/content-types/news/lifecycles.ts
かなり深いですが、この場所にあります。
├── src
│ ├── api
│ │ ├── news(コンテンツ名)
│ │ │ ├── content-types
│ │ │ │ ├── news(コンテンツ名)
│ │ │ │ │ ├── schema.json
│ │ │ │ │ ├── lifecycles.ts (←追加)
STEP.1 で追加した lifecycles.ts
にデプロイ処理を書きます。
Strapi の lifecycle についてはModels | Strapi Documentationに書かれています。
Vercelへのデプロイについては、「定期実行などに使えそう!VercelのDeploy Hookがとても便利だったという話|カルキチのブログ」の関数を利用させていただきました。
import fetch from 'node-fetch';
module.exports = {
afterCreate() {
deployToVercel()
},
afterUpdate() {
deployToVercel()
},
afterDelete() {
deployToVercel()
},
};
async function deployToVercel() {
const vercelDeployUrl = process.env.VERCEL_DEPLOYMENT_URL;
if (!vercelDeployUrl) throw new Error('環境変数が設定されていません。');
await fetch(vercelDeployUrl, { method: 'POST' });
}
かなりシンプルに、コンテンツ作成後/更新後/削除後にデプロイ処理が走るようにできました。
STEP.3 で作成したURLを Strapiプロジェクトをデプロイする時に環境変数に設定されるようにします。
このやり方ではない場合は、 .env
にVERCEL_DEPLOYMENT_URL=STEP.3で取得したURL
を配置するといいと思います。
Strapi を開発環境と本番環境のDockerで動かしたい【まとめ版】 – 本番環境へのデプロイのセクションの prod.Dockerfile
とdeploy.prod.yml
に追記しました。
# Strapiのプロジェクトに移動する
$ cd ~/StrapiProjects/vps-docker-strapi
全体を載せるのでちょっと探しづらいですが# 追加
の部分に環境変数を追加しました。
### deps ステージ ###
FROM node:16 AS deps
RUN apt-get update && apt-get install libvips-dev -y
ENV NODE_ENV=production
WORKDIR /opt/
COPY ./package.json ./yarn.lock ./
ENV PATH /opt/node_modules/.bin:$PATH
RUN yarn config set network-timeout 600000 -g && yarn install
### builder ステージ ###
FROM node:16 AS builder
ENV NODE_ENV=production
WORKDIR /opt/app
ARG HOST
ARG PORT
ARG APP_KEYS
ARG API_TOKEN_SALT
ARG ADMIN_JWT_SECRET
ARG JWT_SECRET
ARG DATABASE_HOST
ARG DATABASE_PORT
ARG DATABASE_NAME
ARG DATABASE_USERNAME
# 追加
ARG VERCEL_DEPLOYMENT_URL
ENV HOST=$HOST
ENV PORT=$PORT
ENV APP_KEYS=$APP_KEYS
ENV API_TOKEN_SALT=$API_TOKEN_SALT
ENV ADMIN_JWT_SECRET=$ADMIN_JWT_SECRET
ENV JWT_SECRET=$JWT_SECRET
ENV DATABASE_HOST=$DATABASE_HOST
ENV DATABASE_PORT=$DATABASE_PORT
ENV DATABASE_NAME=$DATABASE_NAME
ENV DATABASE_USERNAME=$DATABASE_USERNAME
ENV DATABASE_PASSWORD=$DATABASE_PASSWORD
# 追加
ENV VERCEL_DEPLOYMENT_URL=$VERCEL_DEPLOYMENT_URL
# deps ステージでインストールしたライブラリをコピーする
COPY --from=deps /opt/node_modules ./node_modules
COPY . .
RUN yarn build
### runner ステージ ###
FROM node:16 AS runner
WORKDIR /opt/app
ARG HOST
ARG PORT
ARG APP_KEYS
ARG API_TOKEN_SALT
ARG ADMIN_JWT_SECRET
ARG JWT_SECRET
ARG DATABASE_HOST
ARG DATABASE_PORT
ARG DATABASE_NAME
ARG DATABASE_USERNAME
ARG DATABASE_PASSWORD
# 追加
ARG VERCEL_DEPLOYMENT_URL
ENV HOST=$HOST
ENV PORT=$PORT
ENV APP_KEYS=$APP_KEYS
ENV API_TOKEN_SALT=$API_TOKEN_SALT
ENV ADMIN_JWT_SECRET=$ADMIN_JWT_SECRET
ENV JWT_SECRET=$JWT_SECRET
ENV DATABASE_HOST=$DATABASE_HOST
ENV DATABASE_PORT=$DATABASE_PORT
ENV DATABASE_NAME=$DATABASE_NAME
ENV DATABASE_USERNAME=$DATABASE_USERNAME
ENV DATABASE_PASSWORD=$DATABASE_PASSWORD
# 追加
ENV VERCEL_DEPLOYMENT_URL=$VERCEL_DEPLOYMENT_URL
ENV NODE_ENV=production
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 strapi
COPY --from=builder /opt/app/public ./public
COPY --from=builder /opt/app/package.json ./package.json
COPY --from=builder /opt/app/favicon.png ./favicon.png
COPY --from=builder --chown=strapi:nodejs /opt/app/dist ./
COPY --from=builder --chown=strapi:nodejs /opt/app/node_modules ./node_modules
EXPOSE 1337
ENV PORT 1337
CMD ["yarn", "start"]
name: Deploy to Sakura VPS Production
# main ブランチにプッシュされた時に実行する
on:
push:
branches: [main]
# 手動実行時のログを設定
workflow_dispatch:
inputs:
logLevel:
description: 'Log level'
required: true
default: 'warning'
jobs:
deploy:
runs-on: ubuntu-latest
container: node:16
steps:
# チェックアウト
- uses: actions/checkout@v3
# Github Container Registry へビルドしてイメージを格納
- name: Build and Publish to Github Container Registry
uses: elgohr/Publish-Docker-Github-Action@master
env:
HOST: ${{ secrets.STRAPI_HOST }}
PORT: ${{ secrets.STRAPI_PORT }}
APP_KEYS: ${{ secrets.APP_KEYS }}
API_TOKEN_SALT: ${{ secrets.API_TOKEN_SALT }}
ADMIN_JWT_SECRET: ${{ secrets.ADMIN_JWT_SECRET }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
DATABASE_HOST: ${{ secrets.DATABASE_HOST }}
DATABASE_PORT: ${{ secrets.DATABASE_PORT }}
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
# 追加
VERCEL_DEPLOYMENT_URL: ${{ secrets.VERCEL_DEPLOYMENT_URL }}
with:
name: GitHubのユーザ名/vps-docker-strapi/vps-docker-strapi-image
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
dockerfile: prod.Dockerfile
# 追加
buildargs: HOST, PORT, APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, JWT_SECRET, DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USERNAME, DATABASE_PASSWORD, VERCEL_DEPLOYMENT_URL
tags: latest
# VPSへのデプロイ
- name: Deploy to Sakura VPS
uses: appleboy/ssh-action@master
env:
GITHUB_USERNAME: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
STRAPI_PORT: ${{ secrets.STRAPI_PORT }}
DATABASE_HOST: ${{ secrets.DATABASE_HOST }}
DATABASE_PORT: ${{ secrets.DATABASE_PORT }}
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
with:
host: ${{ secrets.DEPLOY_PROD_HOST }}
port: ${{ secrets.DEPLOY_PROD_PORT }}
username: ${{ secrets.DEPLOY_PROD_USER }}
key: ${{ secrets.DEPLOY_PROD_KEY }}
envs: GITHUB_USERNAME, GITHUB_TOKEN, STRAPI_HOST, STRAPI_PORT, APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, JWT_SECRET, DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USERNAME, DATABASE_PASSWORD
script: |
docker login ghcr.io -u $GITHUB_USERNAME -p $GITHUB_TOKEN
docker image pull ghcr.io/GitHubのユーザ名/vps-docker-strapi/vps-docker-strapi-image:latest
docker container rm -f vps-docker-strapi
docker container rm -f vps-docker-strapi-postgres
docker system prune -f
docker network create vps-docker-strapi
docker container run --name vps-docker-strapi-postgres -dit --restart=always --net=vps-docker-strapi -p $DATABASE_PORT:5432 -v /srv/vps-docker-strapi/data:/var/lib/postgresql/data -e POSTGRES_DB=$DATABASE_NAME -e POSTGRES_USER=$DATABASE_USERNAME -e POSTGRES_PASSWORD=$DATABASE_PASSWORD -e PGPORT=$DATABASE_PORT postgres
docker container run --name vps-docker-strapi -dit --restart=always -p $STRAPI_PORT:1337 --net=vps-docker-strapi -v /srv/vps-docker-strapi/public:/opt/app/public --restart=always ghcr.io/GitHubのユーザ名/vps-docker-strapi/vps-docker-strapi-image:latest
GitHubでStrapiのプロジェクトを開き、STEP.3のURLを secrets に追加します。
Name はVERCEL_DEPLOYMENT_URL
で Secrets をSTEP.3のURL
に指定します。
最後にStrapiの本番環境に設定を反映させます。
production ブランチにマージすると先ほどのdeploy.prod.yml
の Action が実行され本番環境にデプロイされます。
おわりに
Strapi の ライフサイクルはかなり便利そうです。なんでもできそう。
Vercel でデプロイしたフロント側と組み合わせることがあるかはわかりませんが、何かの役に立てば幸いです。