なぜ今、StrapiをDocker化すべきなのか?
Strapiは優れたHeadless CMSですが、デプロイのたびにNode.jsやPostgreSQLのバージョンを手動で設定するのは非常に手間がかかります。以前、ローカル環境とUbuntuサーバー間のライブラリバージョンの不一致を修正するだけで、午前中を丸々潰してしまったことがあります。Dockerは、まさに「自分のマシンでは動くのに」という悩みを根本から解決してくれます。
実務経験から言うと、Strapiはかなりリソースを消費します。2GB RAMのVPSでは、ビルドプロセスがシステムをフリーズさせてしまうこともあります。Multi-stage buildを活用することで、イメージサイズを1.2GBから約450MBまで削減できました。これにより、帯域幅の節約だけでなく、CI/CDの速度も3倍に向上します。
標準的なプロジェクト構造の作成
まずは新しいStrapiプロジェクトを作成しましょう。実案件では、SQLiteよりも負荷耐性とデータ整合性に優れたPostgreSQLを優先的に使用します。
npx create-strapi-app@latest my-project --quickstart --no-run
最適化されたディレクトリ構造は以下のようになります:
.
├── strapi-app/
│ ├── Dockerfile
│ ├── .dockerignore
│ └── ... (ソースコード)
├── docker-compose.yml
└── .env
最適なDockerfileの構築(Multi-stage build)
このプロセスの核心はDockerfileにあります。すべてのビルドツールを最終イメージに含めるのではなく、「Build」と「Runtime」の2つのステージに分けます。この手法により、不要な依存関係を排除し、本番環境を常にクリーンで軽量に保つことができます。
strapi-app/ ディレクトリに Dockerfile を作成します:
# ステージ 1: ビルド
FROM node:18-alpine as build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json package-lock.json ./
RUN npm install -g node-gyp
RUN npm config set fetch-retry-maxtimeout 600000 -g && npm install --only=production
WORKDIR /opt/app
COPY . .
RUN npm run build
# ステージ 2: 実行環境
FROM node:18-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY --from=build /opt/node_modules ./node_modules
WORKDIR /opt/app
COPY --from=build /opt/app ./
EXPOSE 1337
CMD ["npm", "run", "start"]
重要な注意点: .dockerignore ファイルを忘れないでください。ローカルの node_modules ディレクトリを誤ってコンテナにコピーしてしまうと、sharp のようなネイティブライブラリがOSアーキテクチャの違いにより即座にエラーを起こします。
Docker ComposeによるStrapiとPostgreSQLの連携
Strapiには、データベースの起動が完了していないと頻繁にクラッシュするという「癖」があります。これを解決するために、healthcheck メカニズムを使用します。Docker Composeは、PostgreSQLが完全に準備できるまで待機してからStrapiコンテナを起動します。
ルートディレクトリにある docker-compose.yml の内容は以下の通りです:
version: '3.8'
services:
strapi-db:
image: postgres:15-alpine
container_name: strapi-db
env_file: .env
volumes:
- strapi-data:/var/lib/postgresql/data
healthcheck:
# データベースが準備できているか確認
test: ["CMD-SHELL", "pg_isready -U $${DATABASE_USERNAME} -d $${DATABASE_NAME}"]
interval: 10s
timeout: 5s
retries: 5
strapi-app:
container_name: strapi-app
build:
context: ./strapi-app
depends_on:
strapi-db:
condition: service_healthy
env_file: .env
ports:
- "1337:1337"
volumes:
- ./strapi-app/uploads:/opt/app/public/uploads
volumes:
strapi-data:
安定運用のための実践的なテクニック
1. ユーザーデータの保護
コンテナ内のデータは、イメージを更新すると消失します。Strapiでは、uploads ディレクトリにすべての画像やドキュメントが保存されます。データ消失を防ぐため、Composeファイルで行ったように、このディレクトリを必ず外部ボリュームにマッピングしてください。
2. 低スペックサーバー向けのRAM最適化
低価格なVPS(DigitalOceanの$6プランやLinodeの1GBプランなど)にデプロイする場合は、Node.jsのRAM使用量を制限しましょう環境変数 NODE_OPTIONS=--max-old-space-size=1024 を追加することで、Strapiがメモリを使い果たしてサーバーがダウンするのを防げます。
3. 開発環境のワークフロー
ローカルでコードを書く際は、ホットリロード機能が必要です。本番用のDockerfileを使用する代わりに、コードを直接コンテナにマウントして npm run develop コマンドを実行します。これにより、イメージを再ビルドすることなく、変更を即座に反映できます。
システムのデプロイ
準備が整いました。あとは次のコマンドを1つ実行するだけで、システム全体が起動します:
docker-compose up -d --build
Dockerがイメージをダウンロードし、ソースコードをビルドするまで約2分待ちます。その後、http://localhost:1337/admin にアクセスして最初の管理者アカウントを作成してください。おめでとうございます!これであなたのCMSは、隔離され、安全で、非常にスケーラブルな環境に構築されました。

