2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1行の変更でStrapiの本番DBを吹き飛ばした話

2
Last updated at Posted at 2026-05-15

image.png

はじめに

それは、何の変哲もないデプロイでした。

変更内容は、たった1行。

外部サービスの所有権確認用に、

public/verify.txt

を追加しただけです。

DB変更なし。
コード変更ほぼなし。

verify.txt を置いただけでした。

本当に、それだけのはずでした。

ところが、デプロイ直後、Strapi の本番 DB から Content-Type とデータが消えました。

当時の構成

  • Strapi v4.12.7 (Community Edition)
  • PostgreSQL 12
  • GitHub Actions
  • Dokku
  • Docker 運用

デプロイは GitHub Actions から Dokku へ push する構成でした。

with:
  git_push_flags: "--force"

この設定で、サーバー側は毎回 Git の状態へ強制的に同期されます。

事故の経緯

1. verify.txt を追加

外部 SaaS(CDN 系)の所有権確認のため、

public/verify.txt

を追加。

Strapi の public/ 配下に置いたファイルは、そのまま静的配信されるため、ただファイルを置くだけの作業でした。

2. デプロイ実行

GitHub Actions → Dokku 経由でデプロイ。

デプロイ自体は正常終了。

しかし、その直後。

  • 一部 Content-Type が消失
  • 管理画面からコレクションが消える
  • データが参照不能になる

という異常が発生しました。

最初に疑ったこと

最初は PostgreSQL 側の事故を疑いました。

「DB が壊れた?」
「migration が誤実行された?」
「Dokku の volume が飛んだ?」

かなり焦りました。

しかし DB ログを確認すると、恐ろしい痕跡が残っていました。

ALTER TABLE ... DROP COLUMN

さらに、

DROP TABLE ...

まで実行されていました。
つまり、

DB を消していたのは Strapi 自身でした。

原因

image.png

ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}

CMD ["yarn", "develop"]

本番環境なのに、Strapi を develop モードで起動していました。

develop モードで何が起きていたのか

Strapi の Content-Type Builder は、管理画面でポチポチ編集しているように見えます。

しかし実際には、

src/api/*/content-types/*/schema.json

を書き換えています。

つまり、

「DB を編集している」のではなく、
「サーバー上のコードを書き換えている」

という状態でした。

そして --force push が噛み合った

ここから、一気に事故が加速します。

管理画面で編集された schema.json は、サーバー上にしか存在していませんでした。

Git にコミットしていなかったのです。

そこへ、

git_push_flags: "--force"

付きのデプロイが実行されました。

結果、サーバー上で変更されていた schema.json は、Git 上の古い状態で強制的に上書きされました。

この時点では、まだ何が起きているか理解できていませんでした。

Strapi の自動同期が発動

ここで Strapi が起動します。

Strapi は起動時に、

  • schema.json
  • 実際の DB 構造

を比較し、コード側へ DB を同期します。

この時点で状態はこうなっていました。

Git にある古い schema.json

{
  "attributes": {
    "title": {
      "type": "string"
    }
  }
}

実際の DB

  • fieldA カラムが存在
  • 管理画面で追加した Content-Type が存在

Strapi はこう判断します。

「schema.json に存在しないので不要」

そして静かに、

ALTER TABLE articles DROP COLUMN "fieldA";

を実行。

さらに、コード上に存在しなかった Content-Type は、

DROP TABLE ...

によって消滅しました。

なぜ起きたのか

今回の事故は、複数の地雷が綺麗に噛み合って発生しました。

① Strapi のスキーマは「コード」

管理画面の編集内容は DB ではなく schema.json に保存されます。

DB は二次的な投影に過ぎず、真実はコード側にあります。

② 本番なのに develop モード

CMD ["yarn", "develop"]

production モードでは、Content-Type Builder はロックされます。

つまり本来、

「本番管理画面からスキーマ変更する」

という運用自体ができません。

しかし今回は develop モードだったため、本番でも schema.json を編集し放題でした。

--force push

git_push_flags: "--force"

これにより、サーバー上のローカル変更はすべて破棄されます。

つまり、管理画面で変更した schema.json は、デプロイの瞬間に消えます。

④ Strapi の同期は「コード → DB」

Strapi はコードを正として DB を同期します。

逆方向(DB → コード)への吸い上げは存在しません。

つまり、

コードに無い = DB から削除対象

です。

再発防止策

1. スキーマ変更はローカルのみ

  1. ローカルの Strapi(develop モード)で変更
  2. schema.json を Git コミット
  3. 本番へデプロイ

本番管理画面は「コンテンツ入力専用」にするべきです。

2. 本番は必ず production モード

ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

CMD ["yarn", "start"]

production モードでは Content-Type Builder がロックされます。

つまり、

「Content-Type はコード管理するもの」

という Strapi 本来の運用に強制されます。

3. --force push を見直す

便利ですが、かなり危険です。

少なくともデプロイ前に schema.json のスナップショットや DB backup は必要でした。

4. DBバックアップを自動化する

Dokku なら、

dokku postgres:export

を CI のデプロイ前へ入れるだけでも命綱になります。

幸い PostgreSQL のバックアップから一部復旧できましたが、最新データの一部は失われました。

おわりに

「1行の変更だから安全」

そんな保証はどこにもありませんでした。

Strapi の管理画面にある「保存」ボタンは、DB 保存ではありません。

あれは、

サーバー上のコードを書き換えるボタン

です。

そのコードは次のデプロイで消えます。

私の犠牲が、誰かの DB を守る糧になれば幸いです。

同じ運用をしている人、本当に気をつけてください。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?