Strapi を開発環境と本番環境のDockerで動かしたい【その4】
前回はデータベースとの接続について考えました。
今回は、Strapi を実際にVPSへデプロイしてみます。
本番環境の構成
本番環境は以下の図のような構成になります。
VPS 上に Docker 環境を構築し、その Docker 環境内に Strapi コンテナと PostgreSQL コンテナの2つを立ち上げます。
実際に Strapi で管理されるデータは、VPS上に直接配置されるようにします。(Docker の volume
を使って外付けする)
デプロイの流れ
GitHub 上のリポジトリにプッシュされたらGitHub Actions
を使って自動でデプロイを行うようにします。
- ローカルで更新して GitHub のリポジトリにプッシュする
- GitHub Actions を使って自動でビルドを行う
- VPS上の既存コンテナを削除して作り直す(2と合わせて自動で行われる)
- プラグインの追加等の変更をした時は 1~3を行う
コンテナを作り直しても、実際のデータには影響がないため、誤ってコンテナが停止した場合でもデータは消えません。
ワークフローをつくる
今回は本番環境とほぼ同じ環境でできたステージング環境へのデプロイを行います。
GitHub Actions を使ってデプロイのワークフローを作成していきます。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# git 管理をはじめる
$ git init
# git 管理しないファイルを設定する
$ touch .gitignore
.gitignore
を作成して、git 管理しないフォルダを追加します。
デフォルトで作成されている.gitignore
にdata
とdist
を追加します。
############################
# OS X
############################
.DS_Store
.AppleDouble
.LSOverride
Icon
.Spotlight-V100
.Trashes
._*
############################
# Linux
############################
*~
############################
# Windows
############################
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
############################
# Packages
############################
*.7z
*.csv
*.dat
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
*.com
*.class
*.dll
*.exe
*.o
*.seed
*.so
*.swo
*.swp
*.swn
*.swm
*.out
*.pid
############################
# Logs and databases
############################
.tmp
*.log
*.sql
*.sqlite
*.sqlite3
############################
# Misc.
############################
*#
ssl
.idea
nbproject
public/uploads/*
!public/uploads/.gitkeep
############################
# Node.js
############################
lib-cov
lcov.info
pids
logs
results
node_modules
.node_history
############################
# Tests
############################
testApp
coverage
############################
# Strapi
############################
.env
license.txt
exports
*.cache
build
.strapi-updater.json
# 追加
data
dist
.gitignore
を編集後、コミットをして GitHub リポジトリにプッシュします。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# git ステージング
$ git add .
# git コミット
$ git commit -m "Initial commit"
# ブランチ名を master から main に変更
$ git branch -M main
# GitHub のブランチと紐づける
$ git remote add origin git@github.com:ユーザ名/Donuts-Strapi.git
# GitHub にプッシュする
$ git push -u origin main
ワークフローの作成は「Next.js のプロジェクトを VPS 上の Docker にデプロイする【その4】」の記事で戦ったので、それを元に書きます。
今回はステージング環境へのデプロイ用のワークフローを作成します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# ワークフローを配置するディレクトリを作成
$ mkdir -p .github/workflows/
# ワークフローファイルを作成する
$ touch .github/workflows/deploy.stg.yml
deploy.stg.yml
を書きます。
name: Deploy to Sakura VPS Staging
# staging ブランチにプッシュされた時に実行する
on:
push:
branches: [staging]
# 手動実行時のログを設定
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 }}
with:
name: GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
dockerfile: stg.Dockerfile
buildargs: HOST, PORT, APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, JWT_SECRET, DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USERNAME, DATABASE_PASSWORD
tags: latest
# VPSへのデプロイ
- name: Deploy to Sakura VPS
uses: appleboy/ssh-action@master
env:
GITHUB_USERNAME: ${{ github.actor }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
STRAPI_HOST: ${{ secrets.STRAPI_HOST }}
STRAPI_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 }}
with:
host: ${{ secrets.DEPLOY_STG_HOST }}
port: ${{ secrets.DEPLOY_STG_PORT }}
username: ${{ secrets.DEPLOY_STG_USER }}
key: ${{ secrets.DEPLOY_STG_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のユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
docker container rm -f donuts-strapi-staging
docker container rm -f donuts-strapi-postgres
docker system prune -f
docker network create donuts-strapi-staging
docker container run --name donuts-strapi-postgres -dit --net=donuts-strapi-staging -p $DATABASE_PORT:5432 -v /srv/donuts-strapi/data:/var/lib/postgresql/data -e POSTGRES_DB=$DATABASE_NAME -e POSTGRES_USER=$DATABASE_USERNAME -e POSTGRES_PASSWORD=$DATABASE_PASSWORD postgres
docker container run --name donuts-strapi-staging -dit -p $STRAPI_PORT:1337 --net=donuts-strapi-staging -v /srv/donuts-strapi/public:/opt/app/public --restart=always ghcr.io/GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
deploy.stg.yml
で利用する環境変数をGitHubのリポジトリ
>Secrets
>Actions
より追加します。
それぞれ適当な値を入力します。
HOST=0.0.0.0
PORT=1337
APP_KEYS=ランダムの値
API_TOKEN_SALT=ランダムの値
ADMIN_JWT_SECRET=ランダムの値
JWT_SECRET=ランダムの値
DATABASE_HOST=donuts-strapi-postgres(PostgreSQLのコンテナ名)
DATABASE_PORT=5432
DATABASE_NAME=donuts-strapi
DATABASE_USERNAME=donuts-strapi
DATABASE_PASSWORD=パスワード
DEPLOY_STG_HOST=さくらVPSのIPアドレス
DEPLOY_STG_PORT=SSH接続用のポート
DEPLOY_STG_USER=SSH接続するユーザ
DEPLOY_STG_KEY=SSH接続の秘密鍵
DATABASE_HOST
はPostgreSQLのコンテナ名を指定します。
ワークフローが起動することを確認します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# staging ブランチを作成
$ git branch staging
# staging ブランチに移動
$ git checkout staging
# staging ブランチを push する
$ git push origin staging
ワークフロー実行時にエラーが出ました。詳細を見てみます。
.env
がないと言われています。.env
は.gitignore
されているのでリポジトリに含まれていません。
環境変数は全て GitHub 上の Secrets で設定したので、stg.Dockerfile
上のCOPY --from=builder --chown=strapi:nodejs /opt/app/.env ./.env
の行を削除して、再度staging
にプッシュしておきます。
VPS のデプロイで転けてしまいました。
2022/09/28 15:30:01 dial tcp ***:***: connect: connection refused
jobs.deploy.steps
のDeploy to Sakura VPS
の方のenv
でHOST
, PORT
としていたのをリネームしたところ解決しました。予約語的なやつかな。。
- name: Deploy to Sakura VPS
uses: appleboy/ssh-action@master
env:
# これだとエラーが起きる
# HOST: ${{ secrets.STRAPI_HOST }}
# PORT: ${{ secrets.STRAPI_PORT }}
STRAPI_HOST: ${{ secrets.STRAPI_HOST }}
STRAPI_PORT: ${{ secrets.STRAPI_PORT }}
参照: https://github.com/appleboy/ssh-action/issues/41#issuecomment-621693365
deploy.stg.yml
の設定がうまくいっていれば、デプロイに成功します。
うまくいかない場合には上記メモやアクションのエラーを参考に修正が必要です。
サイトの確認
まずは、http://IPアドレス:STRAPIのポート番号 でアクセスしてみます。
表示できません。😢
コンテナの確認
コンテナの確認をします。
# VPSにログインする
$ ssh -p ポート番号 ユーザ名@IPアドレス
# docker コンテナの確認をする
% docker container ls
ea099807d5a4 ghcr.io/ユーザ名/donuts-strapi/donuts-strapi-staging-image:latest "docker-entrypoint.s…" 45 seconds ago Restarting (1) 5 seconds ago donuts-strapi-staging
0ee0657a592b postgres "docker-entrypoint.s…" 46 seconds ago Up 45 seconds 0.0.0.0:5432->5432/tcp
# docker イメージの確認もする
% docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ghcr.io/ユーザ名/donuts-strapi/donuts-strapi-staging-image latest a69ca3767d97 3 minutes ago 1.25GB
PostgreSQL のコンテナは正しく起動していますが、Strapi のコンテナは起動せず、リスタートを繰り返しているようです。
データ保管用のフォルダの確認
次にVPS上にデータ保管用フォルダを確認します。
# VPSにログインする
$ ssh -p ポート番号 ユーザ名@IPアドレス
# ボリュームを格納するフォルダに移動
% cd /srv/donuts-strapi/
# donuts-strapi フォルダの中身を表示
% ls
data public
# data の中を確認
% cd data
cd: permission denied: data
# public の中を確認
% cd public
% ls
なし
どうしてコンテナがうまく起動できていないのかを確認するために手動でコンテナを起動してみます。
# VPSにログインする
$ ssh -p ポート番号 ユーザ名@IPアドレス
% コンテナを確認
% docker container ls
ea099807d5a4 ghcr.io/ユーザ名/donuts-strapi/donuts-strapi-staging-image:latest "docker-entrypoint.s…" 45 seconds ago Restarting (1) 5 seconds ago donuts-strapi-staging
0ee0657a592b postgres "docker-entrypoint.s…" 46 seconds ago Up 45 seconds 0.0.0.0:5432->5432/tcp
# すでに起動しているStrapiコンテナを止めて削除する(リスタートを繰り返している)
% docker container rm -f donuts-strapi-staging
% コンテナを確認
% docker container ls
0ee0657a592b postgres "docker-entrypoint.s…" 9 minutes ago Up 9 minutes 0.0.0.0:5432->5432/tcp donuts-strapi-postgres
# Strapiコンテナを立ち上げる(-dit オプションと --restart オプションを外す)
% docker container run --name donuts-strapi-staging -p ポート番号:1337 --net=donuts-strapi-staging -v /srv/donuts-strapi/public:/opt/app/public ghcr.io/GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
error: The upload folder (/opt/app/public/uploads) doesn't exist or is not accessible. Please make sure it exists.
uploads フォルダがないのが問題なようです。
# VPSにログインする
$ ssh -p ポート番号 ユーザ名@IPアドレス
# ボリュームを格納するフォルダに移動
% cd /srv/donuts-strapi/
# donuts-strapi フォルダの中身を表示
% ls
data public
# public ディレクトリに移動
% cd public
# uploads フォルダの作成
% sudo mkdir uploads
/srv/public/uploads
フォルダを作ることにより、上記エラーは解消しましたが、次のエラーが発生しました。
# Strapiコンテナを手動で立ち上げる(-dit オプションと --restart オプションを外す)
% docker container run --name donuts-strapi-staging -p ポート番号:1337 --net=donuts-strapi-staging -v /srv/donuts-strapi/public:/opt/app/public ghcr.io/GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
yarn run v1.22.19
$ strapi start
[2022-09-29 06:28:59.965] debug: ⛔️ Server wasn't able to start properly.
[2022-09-29 06:28:59.968] error: connect ECONNREFUSED 127.0.0.1:5432
Error: connect ECONNREFUSED 127.0.0.1:5432
Strapi と PostgreSQLデータベースがうまく紐づいていません…。
そもそもenv
で設定しているデータベースの値等が、特に Strapi コンテナ起動時には使われていないので、デフォルトの値が使われてしまっています。
次はそこを変えてみましょう。
stg.Dockerfile
を修正して、deploy.stg.yml
で設定している環境変数を使えるようにします。
.env
サーバ側に配置するのも手軽ですが、今回はDockerfile
に設定します。
### 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 DATABASE_PASSWORD
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
# 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
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 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.ico ./favicon.ico
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"]
これで再度 staging ブランチにプッシュし、ワークフローを実行してみます。
さて、またエラーが出ました。
# Strapiコンテナを手動で立ち上げる(-dit オプションと --restart オプションを外す)
% docker container run --name donuts-strapi-staging -p ポート番号:1337 --net=donuts-strapi-staging -v /srv/donuts-strapi/public:/opt/app/public ghcr.io/GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
yarn run v1.22.19
$ strapi start
[2022-09-29 07:32:35.478] debug: ⛔️ Server wasn't able to start properly.
[2022-09-29 07:32:35.480] error: password authentication failed for user "donuts-strapi"
error: password authentication failed for user "donuts-strapi"
これは Docker コマンドに渡す環境変数名を間違えているだけでした😢
$DATABASE_USER
を$DATABASE_USERNAME
に修正して解決しました。
# 修正前
docker container run --name donuts-strapi-postgres -dit --net=donuts-strapi-staging -p $DATABASE_PORT:5432 -v /srv/donuts-strapi/data:/var/lib/postgresql/data -e POSTGRES_DB=$DATABASE_NAME -e POSTGRES_USER=$DATABASE_USER -e POSTGRES_PASSWORD=$DATABASE_PASSWORD postgres
# 修正後
docker container run --name donuts-strapi-postgres -dit --net=donuts-strapi-staging -p $DATABASE_PORT:5432 -v /srv/donuts-strapi/data:/var/lib/postgresql/data -e POSTGRES_DB=$DATABASE_NAME -e POSTGRES_USER=$DATABASE_USERNAME -e POSTGRES_PASSWORD=$DATABASE_PASSWORD postgres
また、外付けされている/srv/donuts-strapi/data
の方でユーザ名とパスワードがすでに設定されてしまっている状態なので、一度/srv/donuts-strapi/data
を削除してやり直す必要がありました。
各環境変数が正しく設定されている状態で、再度確認をしていきます。
サイトの確認
まずは、http://IPアドレス:STRAPIのポート番号 でアクセスしてみます。
表示できました!
コンテナの確認
コンテナの確認をします。
# VPSにログインする
$ ssh -p ポート番号 ユーザ名@IPアドレス
# docker コンテナの確認をする
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
91c475f5f910 ghcr.io/ユーザ名/donuts-strapi/donuts-strapi-staging-image:latest "docker-entrypoint.s…" 30 seconds ago Up 29 seconds 0.0.0.0:Strapiポート番号->1337/tcp donuts-strapi-staging
5f63e0439908 postgres "docker-entrypoint.s…" 31 seconds ago Up 30 seconds 0.0.0.0:データベースポート番号->5432/tcp donuts-strapi-postgres
# docker イメージの確認もする
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ghcr.io/ユーザ名/donuts-strapi/donuts-strapi-staging-image latest c4fecc0023e9 2 minutes ago 1.25GB
稼働中になっていまね!
データ保存の確認
実際に Strapi にデータを追加してみます。
http://IPアドレス:ポート番号/admin/auth/register-admin
にアクセスしてユーザ登録を行います。
ユーザ登録が完了したら User を追加してみます。
登録後、登録内容が正しく表示されていることを確認します。
次にメディアも置いてみます。
無事に置くことができました。
最後に、GitHub Actions より、Re-run all jobs
から再度ワークフローを実行してみます。
ワークフローの実行によりコンテナは一度廃棄され、別のコンテナが作成されます。
その前後でデータが消滅しないことを確認します。
詳しくは、前回の記事で書いています。
ビルドが完了したら再度アクセスして、追加した User と メディア が正しく表示されることを確認します。
確認できたのでこれでデプロイは完了です。
最終的なステージング環境のファイル
無事に Strapi のコンテナが起動した ワークフロー と Dockerfile を最後に貼っておきます。
### 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 DATABASE_PASSWORD
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
# 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
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 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.ico ./favicon.ico
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 Staging
# staging ブランチにプッシュされた時に実行する
on:
push:
branches: [staging]
# 手動実行時のログを設定
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 }}
with:
name: GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
dockerfile: stg.Dockerfile
buildargs: HOST, PORT, APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, JWT_SECRET, DATABASE_HOST, DATABASE_PORT, DATABASE_NAME, DATABASE_USERNAME, DATABASE_PASSWORD
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_STG_HOST }}
port: ${{ secrets.DEPLOY_STG_PORT }}
username: ${{ secrets.DEPLOY_STG_USER }}
key: ${{ secrets.DEPLOY_STG_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のユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
docker container rm -f donuts-strapi-staging
docker container rm -f donuts-strapi-postgres
docker system prune -f
docker network create donuts-strapi-staging
docker container run --name donuts-strapi-postgres -dit --net=donuts-strapi-staging -p $DATABASE_PORT:5432 -v /srv/donuts-strapi/data:/var/lib/postgresql/data -e POSTGRES_DB=$DATABASE_NAME -e POSTGRES_USER=$DATABASE_USERNAME -e POSTGRES_PASSWORD=$DATABASE_PASSWORD postgres
docker container run --name donuts-strapi-staging -dit -p $STRAPI_PORT:1337 --net=donuts-strapi-staging -v /srv/donuts-strapi/public:/opt/app/public --restart=always ghcr.io/GitHubのユーザ名/donuts-strapi/donuts-strapi-staging-image:latest
おわりに
変数名のミスなどですごくハマりましたが、無事にデプロイすることができました。
本番環境でも同様にprod.Dockerfile
を作成し、deploy.prod.yml
にワークフローを定義します。本番環境では別のブランチ(main)へのマージでワークフローを実行します。また、ホストやポートなどの環境変数も本番環境用に定義をして利用します。
何か問題が起こるとすれば、ほとんどが環境変数の設定ミスのはずということがわかったので、その辺に留意しながら本番環境も設定していきたいです。
次回は、独自ドメインの設定を行なっていこうと思います。