Docker コンテナーで Strapi を動かす
Strapi は公式のコンテナーイメージを配布していません。以下はコミュニティ向けの参考手順です。質問は Discord などでどうぞ。
Strapi アプリケーションを、Strapi 以外が作成した既存データベースに接続したり、Strapi v3 のデータベースに接続したりすることは想定されていません。Strapi チームはそのような構成をサポートしません。サポート外のデータベースに接続すると、テーブル消失などデータ損失が起きる可能性が高いです。
このドキュメントでは、既存の Strapi プロジェクト用にカスタムの Docker コンテナーをビルドする流れを説明します。
Docker はコンテナー(ライブラリや依存関係などアプリ実行に必要なものをまとめたパッケージ)でアプリを開発・配布・実行するオープンなプラットフォームです。コンテナー同士は分離され、それぞれがソフトウェア・ライブラリ・設定ファイルを持ち、定められた経路で通信します。
- マシンに Docker をインストール済みであること
- 対応バージョンの Node.js
- 既存の Strapi 5 プロジェクト、または クイックスタート で新規作成したプロジェクト -(任意)マシンに Yarn をインストール済み -(任意)Docker Compose をインストール済み
開発環境・ステージング環境
ホストマシン上で Strapi を扱うには Dockerfile を使えます。必要に応じて docker-compose.yml でデータベース用コンテナーも起動できます。
いずれも、既存の Strapi プロジェクト、または クイックスタート で新規作成したプロジェクトが必要です。
開発用 Dockerfile
次の Dockerfile で、Strapi プロジェクト用の本番以外の Docker イメージをビルドできます。
docker-compose を使う場合、環境変数は docker-compose.yml や .env で設定されるため、手動で個別に設定しなくても構いません。
Strapi を Docker コンテナーで動かすには、次の環境変数が必要です。
| 変数名 | 説明 |
|---|---|
NODE_ENV | アプリケーションが動作する環境。 |
DATABASE_CLIENT | 使用するデータベースクライアント。 |
DATABASE_HOST | データベースのホスト。 |
DATABASE_PORT | データベースのポート。 |
DATABASE_NAME | データベース名。 |
DATABASE_USERNAME | データベースのユーザー名。 |
DATABASE_PASSWORD | データベースのパスワード。 |
JWT_SECRET | Users-Permissions プラグインの JWT に署名する秘密鍵。 |
ADMIN_JWT_SECRET | 管理パネルの JWT に署名する秘密鍵。 |
APP_KEYS | セッションクッキーに署名する秘密鍵。 |
任意の環境変数 も設定できます。
Dockerfile と各命令の詳細は Docker 公式ドキュメント を参照してください。
Dockerfile の例:
- yarn
- npm
FROM node:22-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["yarn", "build"]
EXPOSE 1337
CMD ["yarn", "develop"]
FROM node:22-alpine
# Installing libvips-dev for sharp Compatibility
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev nasm bash vips-dev git
ARG NODE_ENV=development
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
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN chown -R node:node /opt/app
USER node
RUN ["npm", "run", "build"]
EXPOSE 1337
CMD ["npm", "run", "develop"]
(任意)Docker Compose
次の docker-compose.yml で、データベースコンテナーと Strapi コンテナーを、相互通信用の共通ネットワーク付きで起動できます。
Docker Compose の実行やコマンドの詳細は Docker Compose ドキュメント を参照してください。
docker-compose.yml の例:
- MySQL
- MariaDB
- PostgreSQL
services:
strapi:
container_name: strapi
build: .
image: strapi:latest
restart: unless-stopped
env_file: .env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: strapiDB
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
APP_KEYS: ${APP_KEYS}
NODE_ENV: ${NODE_ENV}
volumes:
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
- ./.env:/opt/app/.env
- ./public/uploads:/opt/app/public/uploads
ports:
- "1337:1337"
networks:
- strapi
depends_on:
- strapiDB
strapiDB:
container_name: strapiDB
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: .env
image: mysql:8.0
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_USER: ${DATABASE_USERNAME}
MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
MYSQL_PASSWORD: ${DATABASE_PASSWORD}
MYSQL_DATABASE: ${DATABASE_NAME}
volumes:
- strapi-data:/var/lib/mysql
#- ./data:/var/lib/mysql # if you want to use a bind folder
ports:
- "3306:3306"
networks:
- strapi
volumes:
strapi-data:
networks:
strapi:
name: strapi
driver: bridge
version: "3"
services:
strapi:
container_name: strapi
build: .
image: strapi:latest
restart: unless-stopped
env_file: .env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: strapiDB
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
APP_KEYS: ${APP_KEYS}
NODE_ENV: ${NODE_ENV}
volumes:
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
- ./.env:/opt/app/.env
- ./public/uploads:/opt/app/public/uploads
ports:
- "1337:1337"
networks:
- strapi
depends_on:
- strapiDB
strapiDB:
container_name: strapiDB
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: .env
image: mariadb:latest
environment:
MYSQL_USER: ${DATABASE_USERNAME}
MYSQL_ROOT_PASSWORD: ${DATABASE_PASSWORD}
MYSQL_PASSWORD: ${DATABASE_PASSWORD}
MYSQL_DATABASE: ${DATABASE_NAME}
volumes:
- strapi-data:/var/lib/mysql
#- ./data:/var/lib/mysql # if you want to use a bind folder
ports:
- "3306:3306"
networks:
- strapi
volumes:
strapi-data:
networks:
strapi:
name: strapi
driver: bridge
version: "3"
services:
strapi:
container_name: strapi
build: .
image: strapi:latest
restart: unless-stopped
env_file: .env
environment:
DATABASE_CLIENT: ${DATABASE_CLIENT}
DATABASE_HOST: strapiDB
DATABASE_PORT: ${DATABASE_PORT}
DATABASE_NAME: ${DATABASE_NAME}
DATABASE_USERNAME: ${DATABASE_USERNAME}
DATABASE_PASSWORD: ${DATABASE_PASSWORD}
JWT_SECRET: ${JWT_SECRET}
ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
APP_KEYS: ${APP_KEYS}
NODE_ENV: ${NODE_ENV}
volumes:
- ./config:/opt/app/config
- ./src:/opt/app/src
- ./package.json:/opt/package.json
- ./yarn.lock:/opt/yarn.lock
- ./.env:/opt/app/.env
- ./public/uploads:/opt/app/public/uploads
ports:
- "1337:1337"
networks:
- strapi
depends_on:
- strapiDB
strapiDB:
container_name: strapiDB
platform: linux/amd64 #for platform error on Apple M1 chips
restart: unless-stopped
env_file: .env
image: postgres:16.0-alpine
environment:
POSTGRES_USER: ${DATABASE_USERNAME}
POSTGRES_PASSWORD: ${DATABASE_PASSWORD}
POSTGRES_DB: ${DATABASE_NAME}
volumes:
- strapi-data:/var/lib/postgresql/data/ #using a volume
#- ./data:/var/lib/postgresql/data/ # if you want to use a bind folder
ports:
- "5432:5432"
networks:
- strapi
volumes:
strapi-data:
networks:
strapi:
name: strapi
driver: bridge
本番環境
本番用 Docker イメージは、開発・ステージング用と異なります。管理パネルのビルド手順と、アプリの起動コマンドが違うためです。典型例ではリバースプロキシがアプリと管理パネルを配信します。イメージは管理パネルの production ビルドで作られ、起動コマンドは strapi start です。
本番用 Dockerfile を用意したら、本番コンテナーをビルドできます。任意でレジストリに公開し、配布することもできます。コミュニティツールが本番イメージの構築とデプロイを補助します。
本番用 Dockerfile
次の Dockerfile で、Strapi プロジェクト用の本番 Docker イメージをビルドできます。
- yarn
- npm
# Creating multi-stage build for production
FROM node:22-alpine AS build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/
COPY package.json yarn.lock ./
RUN yarn global add node-gyp
RUN yarn config set network-timeout 600000 -g && yarn install --production
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN yarn build
# Creating final production image
FROM node:22-alpine
RUN apk add --no-cache vips-dev
ENV NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/app
COPY --from=build /opt/node_modules ./node_modules
COPY --from=build /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["yarn", "start"]
# Creating multi-stage build for production
FROM node:22-alpine AS build
RUN apk update && apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git > /dev/null 2>&1
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
ENV PATH=/opt/node_modules/.bin:$PATH
WORKDIR /opt/app
COPY . .
RUN npm run build
# Creating final production image
FROM node:22-alpine
RUN apk add --no-cache vips-dev
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}
WORKDIR /opt/app
COPY --from=build /opt/node_modules ./node_modules
COPY --from=build /opt/app ./
ENV PATH=/opt/node_modules/.bin:$PATH
RUN chown -R node:node /opt/app
USER node
EXPOSE 1337
CMD ["npm", "run", "start"]
本番コンテナーのビルド
本番用 Docker イメージのビルドにはさまざまなオプションがあります。以下は docker build の例です。高度なオプションは Docker ドキュメント も参照してください。
Strapi プロジェクトの本番イメージをビルドする例:
docker build \
--build-arg NODE_ENV=production \
# --build-arg STRAPI_URL=https://api.example.com \ # Uncomment to set the Strapi Server URL
-t mystrapiapp:latest \ # Replace with your image name
-f Dockerfile.prod .
(任意)レジストリへの公開
本番用イメージをビルドしたら、Docker レジストリにプッシュできます。イメージに機微情報が含まれるため、本番ではプライベートレジストリを使うのが望ましいです。
ホスティング事業者によっては公開コマンドが異なることがあります。詳細は Docker ドキュメント を参照してください。
よく使われるレジストリの例:
- AWS ECR
- Azure Container Registry
- GCP Container Registry
- Digital Ocean Container Registry
- IBM Cloud Container Registry
- GitHub Container Registry
- Gitlab Container Registry
コミュニティツール
クラウドへのデプロイや、開発・本番での Docker セットアップを支援するコミュニティ製ツールがあります。
コミュニティの取り組みを歓迎しており、次のツールの利用・開発へのコントリビューションも検討してください。
ここにツールを追加したい場合は、Strapi documentation リポジトリ にプルリクエストを送ってください。
@strapi-community/dockerize
@strapi-community/dockerize は、Strapi プロジェクト用の Dockerfile と docker-compose.yml を生成する CLI です。
既存の Strapi プロジェクトフォルダで npx @strapi-community/dockerize@latest を実行し、CLI の案内に従ってください。
詳細は公式の GitHub リポジトリ または npm パッケージ を参照してください。
@strapi-community/deployify
@strapi-community/deployify は、各種クラウドやホスティングへアプリをデプロイする CLI です。Docker で Strapi を載せる方式に対応しているものもあり、必要なファイルがなければ @strapi-community/dockerize で生成します。
既存の Strapi プロジェクトフォルダで npx @strapi-community/deployify@latest を実行し、CLI の案内に従ってください。
詳細は公式の GitHub リポジトリ または npm パッケージ を参照してください。
Docker に関する FAQ
なぜ Strapi は公式 Docker イメージを配らないのですか?
Strapi はさまざまな種類のアプリを構築するためのフレームワークであり、すべてのユースケースに対応する単一の Docker イメージを用意することはできません。
なぜ開発用と本番用で Dockerfile が違うのですか?
主な理由は管理パネルのビ ルド方法です。管理パネルは React でビルドされ、ビルド時に Strapi アプリケーションにバンドルされます。バックエンドが管理パネルを配信するウェブサーバーとしても動くため、一部の環境変数はビルド済み管理パネルに静的に埋め込まれます。
Strapi では開発用と本番用で別イメージを作るのが一般的です。開発環境はパフォーマンス最適化されておらず、公開インターネットに晒す想定でもありません。