Strapi を開発環境と本番環境のDockerで動かしたい【その1】
今回より、Next.js で作ったサイトに、Strapi からコンテンツの配信を行っていくことを目指していきます。
Strapiとは
Strapiは Node.js ベースのヘッドレスCMSです。無料のオープンソースで、自分で用意したサーバー上に環境を構築して利用することができます。
ヘッドレスCMSにも色々ありますが、自分で用意したサーバ上にコンテンツを置くことができることと、自分で機能を拡張することができるという点で利用することにしました。
Strapi を Docker で導入するには
Strapi の Docker での導入方法は、現在v3
でしか対応しておらず、v4
を利用するにはDocker with Strapi V4を参考にすると良いようです。
また、Strapi 公式の Docker イメージもありますが、こちらもv3
までの対応となっています。
目指すところ
Next.js のプロジェクトを Docker + VPS で動かすことができたので、それと同様に Docker + VPS で Strapi を動かすことを目標とします。
要件は以下の通りです。
- GitHub Actions を用いて自動デプロイ
- データベースのバックアップを取りたい
- Strapi のプラグインを使いたい
- ステージング環境で試せるようにしたい
タスク
タスクの洗い出しをします。開発や運用フローはNext.js の記事と同様にします。
Strapi での開発自体はほとんどない予定ですが、Strapi のバージョンのアップデートやプラグイン等の拡張機能を追加した時にローカル環境とステージング環境にて確認できるようにしておこうと思います。
- 開発環境の Docker で Strapi を動かすために Dockerfile を用意する
- GitHub のリポジトリを作成する
- 本番環境用の Dockerfile を用意する
- GitHub Actions を利用してワークフローを作成する
- 本番環境のVPS上で Nginx の設定をする
開発環境の Docker で Strapi を動かす(方法1)
まずは、開発環境の Docker 上で Strapi を動かしてみようと思います。
「Docker with Strapi V4」の記事通りにDockerfile
を用意します。
前回の Next.js プロジェクトのCMS用にしたいので、
donuts_strapi
というプロジェクト名にしました。
# 作業ディレクトリを作成して移動する
$ mkdir StrapiProjects
$ cd ~/StrapiProjects
# Strapi をインストールする(TypeScript を利用したいので--ts オプションをつける。
$ yarn create strapi-app donuts-strapi --ts
# データベースをデフォルトのSQLiteからMySQLに変更したいのでCustomを選択
? Choose your installation type
Quickstart (recommended)
❯ Custom (manual settings)
? Choose your default database client
sqlite
postgres
❯ mysql
? Database name: donuts-strapi
? Host: 127.0.0.1
? Port: 3306
? Username: donuts-strapi
? Password: **********
? Enable SSL connection: Yes
~/StrapiProjects/donuts-strapi
の中身は以下の通りです。
.
├── .editorconfig
├── .env
├── .env.example
├── .gitignore
├── README.md
├── config
├── database
├── favicon.ico
├── node_modules
├── package.json
├── public
├── src
├── tsconfig.json
└── yarn.lock
より詳細はProject Structure – Strapi Developer Docsにて確認できます。
Strapi を利用するにはデータベースが必須になります。どのデータベースで構築されているかは、./config/database.ts
で確認することができます。
デフォルトではSQLite
が使用されていますが、今回はMySQL
に変更してインストールしました。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Dockerfile を作成する
$ touch dev.Dockerfile
FROM node:16
# Installing libvips-dev for sharp Compatability
RUN apt-get update && apt-get install libvips-dev -y
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY ./package.json ./yarn.lock ./
ENV PATH /opt/node_modules/.bin:$PATH
RUN yarn config set network-timeout 600000 -g && yarn install
WORKDIR /opt/app
COPY ./ .
RUN yarn build
EXPOSE 1337
CMD ["yarn", "develop"]
上記のDockerfile
でCOPY ./ .
を行う時に無視したいファイルを.dockerignore
にて指定します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# .dockerignore を作成する
$ touch .dockerignore
.tmp/
.cache/
.git/
build/
node_modules/
data/
作成したDockerfile
を元に Docker イメージを作成します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Dockerイメージを作成
# docker build -f Dockerfile のファイル名 -t 作成するするイメージ名 もとになるDockerfileの場所
$ docker build -f dev.Dockerfile -t donuts-strapi-image .
# イメージができたことを確認
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
donuts-strapi-image latest cb3567cb4c33 12 minutes ago 2.61GB
STEP.4 で作成したイメージからコンテナを起動します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# コンテナの起動
# docker run -d(バックグラウンドで起動) -p ポート --name コンテナの名前 元になるイメージ
$ docker run -d -p 1337:1337 --name donuts-strapi donuts-strapi-image
コンテナの起動を試みましたが、エラーが出ました。
$ docker run -p 1337:1337 --name donuts-strapi donuts-strapi-image
yarn run v1.22.19
$ strapi develop
Starting the compilation for TypeScript files in /opt/app
[2022-09-20 19:22:52.262] debug: ⛔️ Server wasn't able to start properly.
[2022-09-20 19:22:52.265] error: connect ECONNREFUSED 127.0.0.1:3306
Error: connect ECONNREFUSED 127.0.0.1:3306
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1247:16)
--------------------
at Protocol._enqueue (/opt/node_modules/mysql/lib/protocol/Protocol.js:144:48)
at Protocol.handshake (/opt/node_modules/mysql/lib/protocol/Protocol.js:51:23)
at Connection.connect (/opt/node_modules/mysql/lib/Connection.js:116:18)
at /opt/node_modules/knex/lib/dialects/mysql/index.js:66:18
at new Promise (<anonymous>)
at Client_MySQL.acquireRawConnection (/opt/node_modules/knex/lib/dialects/mysql/index.js:61:12)
at create (/opt/node_modules/knex/lib/client.js:252:39)
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
デフォルトではSQLite
を使用しており、「Docker with Strapi V4」の記事にも書かれているように、SQLite
はコンテナの内部に存在するデータベースであり、上記のイメージのみでコンテナを起動することができますが、同時にコンテナを停止するとデータベースの中身も消えてしまいます。
今回 MySQLを利用しているため、MySQLのコンテナを起動する必要があります。
上記エラーを解決するために、MySQLのコンテナを作成します。
MySQLコンテナとStrapiコンテナをつなぐためのnetwork
も作成します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# ネットワークを作成する
$ docker network create donuts-strapi-network
24a135ec61e96e1affc289964d92f74e5a0ab877a90726779fdb359500f6cab9
# ネットワークが作成されたことを確認する
$ docker network ls
24a135ec61e9 donuts-strapi-network bridge local
# MySQLのコンテナを作成する
# docker run --name コンテナ名 -dit --net=ネットワーク名 -p ポートの指定 環境の設定
$ docker run --name donuts-strapi-mysql -dit --net=donuts-strapi-network -p 3306:3306 -e MYSQL_ROOT_PASSWORD=donuts-strapi -e MYSQL_DATABASE=donuts-strapi -e MYSQL_USER=donuts-strapi -e MYSQL_PASSWORD=donuts-strapi mysql --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password
# コンテナの確認をする
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a89fc261fe45 mysql "docker-entrypoint.s…" 4 seconds ago Up 3 seconds 0.0.0.0:3306->3306/tcp, 33060/tcp donuts-strapi-mysql
MySQLのパスワード等は./config/database.ts
の内容を書きます。
改めてSTEP.5のコンテナを起動してみます。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# コンテナの起動
# docker run -d(バックグラウンドで起動) -p ポート --net=ネットワーク名 --name コンテナの名前 元になるイメージ
$ docker run -d -p 1337:1337 --net=donuts-strapi-network --name donuts-strapi donuts-strapi-image
同様のエラーで起動できず。。。。😢
うまくいかないので、手順を変更してやってみます。
その前に全て後片付けをしておきます。
# MySQL のコンテナを止める
$ docker container stop donuts-strapi-mysql
# 停止しているコンテナを確認
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
949058f9a2d7 donuts-strapi-image "docker-entrypoint.s…" 2 minutes ago Exited (1) 2 minutes ago donuts-strapi
a89fc261fe45 mysql "docker-entrypoint.s…" 6 minutes ago Up 6 minutes 0.0.0.0:3306->3306/tcp, 33060/tcp donuts-strapi-mysql
# 作成したコンテナを削除する
$ docker container rm donuts-strapi donuts-strapi-mysql
# 作成したネットワークを削除する
$ docker network rm donuts-strapi-network
# 作成したイメージを削除する
$ docker image rm donuts-strapi-image
後述するやり方でなくても、こちらの方法でも無事に起動することができたので追記します。
STEP.6 のあとに.env
ファイルに以下を追記します。先ほどMySQLのコンテナに設定した情報を入力します。
DATABASE_HOST=donuts-strapi-mysql
DATABASE_PORT=3306
DATABASE_NAME=donuts-strapi
DATABASE_USERNAME=donuts-strapi
DATABASE_PASSWORD=donuts-strapi
MYSQL_ROOT_PASSWORD=donuts-strapi
DATABASE_HOST
にSTEP.6で作成したMySQLのコンテナ名を指定します。
.env
を更新したので再度イメージのビルドからやり直し、コンテナを起動します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Dockerイメージを作成
# docker build -f Dockerfile のファイル名 -t 作成するするイメージ名 もとになるDockerfileの場所
$ docker build -f dev.Dockerfile -t donuts-strapi-image .
# docker run -p ポート --net=ネットワーク名 --name コンテナの名前 元になるイメージ
$ docker run -p 1337:1337 --net=donuts-strapi-network --name donuts-strapi donuts-strapi-image
これで http://localhost:1337/ にアクセスして Strapi の画面を表示することができました。
また今回のように最初にMySQLの設定を行う方法+後述のDockerComposeを利用した形でも無事に起動することができました。
開発環境の Docker で Strapi を動かす(方法2)
上記やり方では MySQL のところでハマってしまい、うまく起動することができませんでした。(後で成功したやり方も追記しました!)
以前うまく行った時のメモを見ながら再度やり直してみます。
先ほどは最初からMySQLを利用する形で設定していましたが、今回はSQLiteのままインストールしていきます。
# 作業ディレクトリを作成して移動する
$ mkdir StrapiProjects
$ cd ~/StrapiProjects
# Strapi をインストールする(TypeScript を利用したいので--ts オプションをつける。
$ npx create-strapi-app@latest donuts-strapi --quickstart --ts
http://localhost:1337/admin/auth/register-admin が自動で起動するのでcontrol
+c
で止めておきます。
STEP.2, 3, 4は先ほどと全く同じです。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Dockerfile を作成する
$ touch dev.Dockerfile
FROM node:16
# Installing libvips-dev for sharp Compatability
RUN apt-get update && apt-get install libvips-dev -y
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY ./package.json ./yarn.lock ./
ENV PATH /opt/node_modules/.bin:$PATH
RUN yarn config set network-timeout 600000 -g && yarn install
WORKDIR /opt/app
COPY ./ .
RUN yarn build
EXPOSE 1337
CMD ["yarn", "develop"]
上記のDockerfile
でCOPY ./ .
を行う時に無視したいファイルを.dockerignore
にて指定します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# .dockerignore を作成する
$ touch .dockerignore
.tmp/
.cache/
.git/
build/
node_modules/
data/
作成したDockerfile
を元に Docker イメージを作成します。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Dockerイメージを作成
# docker build -f Dockerfile のファイル名 -t 作成するするイメージ名 もとになるDockerfileの場所
$ docker build -f dev.Dockerfile -t donuts-strapi-image .
# イメージができたことを確認
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
donuts-strapi-image latest 8f728c883637 About a minute ago 2.95GB
先ほどとは異なり、まだSQLiteで設定されているため、コンテナを起動することができるはず。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# コンテナの起動
# docker run -p ポート --name コンテナの名前 元になるイメージ
$ docker run -p 1337:1337 --name donuts-strapi donuts-strapi-image
http://localhost:1337/ にアクセスして無事に表示されました。
確認できたらコンテナは削除しておきます。
# コンテナを止めて削除する
$ docker container stop donuts-strapi
$ docker container rm donuts-strapi
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# MySQLを追加する
$ yarn add mysql
Docker Compose を利用して、MySQLのコンテナを作成とネットワークの作成等の定義を行います。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# Docker Compose の定義ファイルを作成
$ touch docker-compose.dev.yml
Docker Compose の定義は「HeadlessCMSの「Strapi」をDockerで爆速で立ち上げる」の記事を参考にしています。
version: '3'
services:
strapi:
container_name: donuts-strapi
build:
context: .
dockerfile: dev.Dockerfile
restart: always
env_file: .env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: mysql
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PORT: ${DATABASE_PORT}
JWT_SECRET: ${JWT_SECRET}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
NODE_ENV: ${NODE_ENV}
links:
- mysql:mysql
volumes:
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
- ./.env:/opt/app/.env
ports:
- "1337:1337"
networks:
- strapi
depends_on:
- mysql
mysql:
image: mysql
command: mysqld --default-authentication-plugin=mysql_native_password
volumes:
- ./data:/var/lib/mysql
ports:
- '3306:3306'
restart: always
env_file: .env
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${DATABASE_NAME}
MYSQL_USER: ${DATABASE_USERNAME}
MYSQL_PASSWORD: ${DATABASE_PASSWORD}
cap_add:
- SYS_NICE
networks:
- strapi
networks:
strapi:
name: Strapi
driver: bridge
./config/database.ts
をMySQL用に書き換えます。
export default ({ env }) => ({
connection: {
client: 'mysql',
connection: {
host: env('DATABASE_HOST', '127.0.0.1'),
port: env.int('DATABASE_PORT', 3306),
database: env('DATABASE_NAME', 'strapi'),
user: env('DATABASE_USERNAME', 'strapi'),
password: env('DATABASE_PASSWORD', 'strapi'),
ssl: {
rejectUnauthorized: env.bool('DATABASE_SSL_SELF', false), // For self-signed certificates
},
},
debug: false,
},
});
.env
で環境設定を行います。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# 開発環境用の環境変数設定ファイルを用意
$ touch .env.development
HOST=0.0.0.0
PORT=1337
APP_KEYS="toBeModified1,toBeModified2"
API_TOKEN_SALT=tobemodified
ADMIN_JWT_SECRET=tobemodified
JWT_SECRET=tobemodified
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=strapi
NODE_ENV=development
DATABASE_CLIENT=mysql
MYSQL_ROOT_PASSWORD=pass
STEP.6で作成した定義を元に、イメージの作成とコンテナの起動を行います。
# 作業ディレクトリに移動する
$ cd ~/StrapiProjects/donuts-strapi
# イメージの作成
$ docker compose -f docker-compose.dev.yml build
# コンテナの起動
$ docker compose -f docker-compose.dev.yml up -d
http://localhost:1337/ にアクセスしてもみれません😢
ログを見るためにバックグラウンドオプションを外してみました。
# コンテナの起動
$ docker compose -f docker-compose.dev.yml up
http://localhost:1337/ にアクセスしてみれるようになりました。どうして😢
おわりに
とりあえず開発環境のDocker上で動くようにはなりました。
まだわかってない部分が多いので、もう少し色々勉強して試してから本番環境へ臨みたいと思います。
続きます。