Strapi

更新:2025-03-29
JavaScript

概要

ヘッドレスCMS「Strapi」を使ってみた。

環境を用意する

Dockerで構築。node_modulesの扱いはこちらの記事を参照した。

/some/directory/docker-compose.yml
services:
app:
build: ./src/strapi
ports:
- '1337:1337'
volumes:
- ./app:/usr/src/app
- node-modules-volume:/usr/src/app/node_modules
tty: true
volumes:
node-modules-volume:
/some/directory/src/strapi/Dockerfile
# 22以下推奨だった
FROM node:22
WORKDIR /usr/src/app
# npmのアップデートが案内されたので、あらかじめここで入れておく
RUN npm install -g npm@11.2.0
/some/directory/.dockerignore
.git
.log
node_modules
.strapi
.tmp

ビルド。

/some/directory
docker compose build

起動。

/some/directory
docker compose up -d

アプリのコンテナに入る。

/some/directory
docker compose exec app bash

Strapiのプロジェクトを作成する。

app:/usr/src/app
npx create-strapi-app@latest .

今回は無料で試したいので、Strapi CloudはSkipする。

app:/usr/src/app
? Please log in or sign up. (Use arrow keys)
Login/Sign up
Skip
? Please log in or sign up. Skip
? Do you want to use the default database (sqlite) ? Yes
? Start with an example structure & data? No
? Start with Typescript? Yes
? Install dependencies with npm? Yes
? Initialize a git repository? No

Strapiを起動。

app:/usr/src/app
npm run develop
# http://localhost:1337/

アカウント登録すればダッシュボードが確認できる。

Consoleでエラーが出た

GET http://localhost:5173/admin/ net::ERR_CONNECTION_REFUSED

GitHubに同様のissueがあり、解決方法が書かれていた。

package.jsonを変更する。

app:/usr/src/app/package.json
{
..
"scripts": {
..
"dev": "strapi develop",
"develop": "strapi develop",
"dev": "strapi develop --no-watch-admin",
"develop": "strapi develop --no-watch-admin",
..
},
...
}

データを登録してみる

たとえばモンスターの名前と属性を管理する。

Content-Type Builder

データの型を作成する。

項目内容
Display nameMonster
API ID (Singular)monster(自動)
API ID (Plural)monsters(自動)
FieldNameType or Value
TextnameShort text
EnumerationelementFire
Water
Earth
Wind
Thunder

Content Manager

データを登録する。APIにデータを含める場合は「Publish」しておく。

NAMEELEMENT
AAAAAFire
BBBBBWater
CCCCCEarth
DDDDDWind
EEEEEThunder

Setting

[Users & Permissions plugin] - [Roles] - [Public] - [Monster] - [find]にチェックを入れると、APIにアクセスできる。以下は整形したデータ。

http://localhost:1337/api/monsters
{
"data": [
{
"id": 2,
"documentId": "nds6yl0rhi6mc8qajkbnst33",
"name": "AAAAA",
"element": "Fire",
"createdAt": "2025-03-29T06:50:05.891Z",
"updatedAt": "2025-03-29T06:50:05.891Z",
"publishedAt": "2025-03-29T06:50:05.901Z"
},
{
"id": 4,
"documentId": "h5b5eqhpx4rqad9qhybbgk2q",
"name": "BBBBB",
"element": "Water",
"createdAt": "2025-03-29T06:50:13.760Z",
"updatedAt": "2025-03-29T06:50:13.760Z",
"publishedAt": "2025-03-29T06:50:13.770Z"
},
{
"id": 6,
"documentId": "x97lxl2ubqhnvi4eovdb6hgm",
"name": "CCCCC",
"element": "Earth",
"createdAt": "2025-03-29T06:50:19.803Z",
"updatedAt": "2025-03-29T06:50:19.803Z",
"publishedAt": "2025-03-29T06:50:19.811Z"
},
{
"id": 11,
"documentId": "ckresuyjxosy2l32oxu87u5m",
"name": "DDDDD",
"element": "Wind",
"createdAt": "2025-03-29T06:50:26.119Z",
"updatedAt": "2025-03-29T06:51:02.108Z",
"publishedAt": "2025-03-29T06:51:02.119Z"
},
{
"id": 12,
"documentId": "jdw4gtrevl98ikz184g3dfw5",
"name": "EEEEE",
"element": "Thunder",
"createdAt": "2025-03-29T06:50:47.909Z",
"updatedAt": "2025-03-29T07:10:25.227Z",
"publishedAt": "2025-03-29T07:10:25.238Z"
}
],
"meta": {
"pagination": {
"page": 1,
"pageSize": 25,
"pageCount": 1,
"total": 5
}
}
}

idが不規則になっているのが気になったので、実際にSQLiteのデータを確認。

/some/directory/src/strapi/app/.tmp
sqlite3 data.db
sqlite>
SELECT * FROM monsters;
monsters
1|nds6yl0rhi6mc8qajkbnst33|AAAAA|Fire|1743231005891|1743231005891||1|1|
2|nds6yl0rhi6mc8qajkbnst33|AAAAA|Fire|1743231005891|1743231005891|1743231005901|1|1|
3|h5b5eqhpx4rqad9qhybbgk2q|BBBBB|Water|1743231013760|1743231013760||1|1|
4|h5b5eqhpx4rqad9qhybbgk2q|BBBBB|Water|1743231013760|1743231013760|1743231013770|1|1|
5|x97lxl2ubqhnvi4eovdb6hgm|CCCCC|Earth|1743231019803|1743231019803||1|1|
6|x97lxl2ubqhnvi4eovdb6hgm|CCCCC|Earth|1743231019803|1743231019803|1743231019811|1|1|
7|ckresuyjxosy2l32oxu87u5m|DDDDD|Wind|1743231026119|1743231062108||1|1|
9|jdw4gtrevl98ikz184g3dfw5|EEEEE|Thunder|1743231047909|1743232225227||1|1|
11|ckresuyjxosy2l32oxu87u5m|DDDDD|Wind|1743231026119|1743231062108|1743231062119|1|1|
12|jdw4gtrevl98ikz184g3dfw5|EEEEE|Thunder|1743231047909|1743232225227|1743232225238|1|1|

どうも同じデータを編集した場合、UPDATEではなくINSERTしているように見える。

MySQLで使ってみる

/some/directory/docker-compose.yml
services:
app:
build: ./src/strapi
ports:
- '1337:1337'
volumes:
- ./app:/usr/src/app
- node-modules-volume:/usr/src/app/node_modules
tty: true
db:
image: mysql/mysql-server:8.0
env_file: .env
ports:
- '3306:3306'
volumes:
- ./src/mysql/my.cnf:/etc/my.cnf
- ./db:/var/lib/mysql
volumes:
node-modules-volume:
/some/directory/.env
MYSQL_DATABASE=strapi
MYSQL_USER=strapi
MYSQL_PASSWORD="password"
MYSQL_ROOT_PASSWORD="password"
TZ=Asia/Tokyo
/some/directory/.dockerignore
.git
.log
node_modules
.strapi
.tmp
.env
/some/directory/src/mysql/my.cnf
# ------------------------------
# 普通にイメージ作成した時のデフォルト設定項目
# ------------------------------
[mysqld]
skip-host-cache
skip-name-resolve
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
secure-file-priv=/var/lib/mysql-files
user=mysql
pid-file=/var/run/mysqld/mysqld.pid
# ------------------------------
# 追加項目
# ------------------------------
# サーバ側の文字コード
character-set-server = utf8mb4
# ソート順
collation_server = utf8mb4_ja_0900_as_cs_ks
# タイムゾーン
default-time-zone = 'SYSTEM'
log_timestamps = 'SYSTEM'
# エラーログを残す
log-error = mysql-error.log
# スロウ(ここでは1秒とする)ログを残す
slow_query_log = 1
slow_query_log_file = mysql-slow.log
long_query_time = 1.0
log_queries_not_using_indexes = 0
# 通常のログを残す
general_log = 1
general_log_file = mysql-general.log
[mysql]
# mysqlコマンドの文字コード
default-character-set = utf8mb4
[client]
# 他クライアントツール(mysqlコマンドも含むが重複して問題ない)の文字コード
default-character-set = utf8mb4

create-strapi-app時に、MySQLを選択する。

app:/usr/src/app
? Please log in or sign up. Skip
? Do you want to use the default database (sqlite) ? No
? Choose your default database client mysql
? Database name: strapi
? Host: db # コンテナ名を指定する
? Port: 3306
? Username: strapi
? Password: ********
? Enable SSL connection: No
? Start with an example structure & data? No
? Start with Typescript? Yes
? Install dependencies with npm? Yes
? Initialize a git repository? No

データを確認するために、DBコンテナに入る。

/some/directory
docker compose exec db /bin/bash

MySQLに入る。

db:/
mysql -u root -p

DB「strapi」を選択して、monstersの中身を表示。

mysql>
use strapi;
mysql>
SELECT * FROM monsters;
mysql>
+----+--------------------------+-------+---------+----------------------------+----------------------------+----------------------------+---------------+---------------+--------+
| id | document_id | name | element | created_at | updated_at | published_at | created_by_id | updated_by_id | locale |
+----+--------------------------+-------+---------+----------------------------+----------------------------+----------------------------+---------------+---------------+--------+
| 1 | au4avn7jlw1fbp99zv8tkpwn | AAAAA | Fire | 2025-03-29 13:16:51.823000 | 2025-03-29 13:16:51.823000 | NULL | 1 | 1 | NULL |
| 2 | au4avn7jlw1fbp99zv8tkpwn | AAAAA | Fire | 2025-03-29 13:16:51.823000 | 2025-03-29 13:16:51.823000 | 2025-03-29 13:16:51.833000 | 1 | 1 | NULL |
| 3 | bz6ze1w0qjekyca7httrhhsp | BBBBB | Water | 2025-03-29 13:17:01.044000 | 2025-03-29 13:17:01.044000 | NULL | 1 | 1 | NULL |
| 4 | bz6ze1w0qjekyca7httrhhsp | BBBBB | Water | 2025-03-29 13:17:01.044000 | 2025-03-29 13:17:01.044000 | 2025-03-29 13:17:01.058000 | 1 | 1 | NULL |
| 5 | j9dgf9l54izmdrtflvbz14jx | CCCCC | Earth | 2025-03-29 13:17:09.291000 | 2025-03-29 13:17:09.291000 | NULL | 1 | 1 | NULL |
| 6 | j9dgf9l54izmdrtflvbz14jx | CCCCC | Earth | 2025-03-29 13:17:09.291000 | 2025-03-29 13:17:09.291000 | 2025-03-29 13:17:09.303000 | 1 | 1 | NULL |
| 7 | dalpv7r7gxzx5ilxal3ekowk | DDDDD | Wind | 2025-03-29 13:17:18.973000 | 2025-03-29 13:17:39.929000 | NULL | 1 | 1 | NULL |
| 9 | z3j7kqdutlt6r6j633cbsea4 | EEEEE | Thunder | 2025-03-29 13:17:29.755000 | 2025-03-29 13:17:29.755000 | NULL | 1 | 1 | NULL |
| 10 | z3j7kqdutlt6r6j633cbsea4 | EEEEE | Thunder | 2025-03-29 13:17:29.755000 | 2025-03-29 13:17:29.755000 | 2025-03-29 13:17:29.766000 | 1 | 1 | NULL |
| 11 | dalpv7r7gxzx5ilxal3ekowk | DDDDD | Wind | 2025-03-29 13:17:18.973000 | 2025-03-29 13:17:39.929000 | 2025-03-29 13:17:39.942000 | 1 | 1 | NULL |
+----+--------------------------+-------+---------+----------------------------+----------------------------+----------------------------+---------------+---------------+--------+

データの編集がUPDATEではなくINSERTなのは同じだった。どうやらDBの種類による状態ではないらしい。

続く...かもね