Strapi is the headless CMS most teams reach for when they want a self-hostable admin panel and REST or GraphQL APIs, and its hosted offering prices by project and seat. Self-hosting on Dokploy costs the server, but Strapi is pickier than a plain Node app: it needs a real database in production, six secret variables before it will start, somewhere persistent for uploads, and enough memory to build its admin panel. This guide covers all four for Strapi 5 on a MassiveGRID server from the Dokploy hosting page.

Step 1: PostgreSQL as a Dokploy service

Strapi's default SQLite is for development; production needs PostgreSQL (or MySQL). Create a PostgreSQL 16 service in a Dokploy project with a database, user and generated password, note the internal hostname Dokploy shows, and schedule a daily backup to an S3 destination. Your content, admin users and API tokens all live here.

Step 2: the environment Strapi requires

Strapi reads these from the environment and refuses to start in production without the secrets. Generate each with openssl rand -base64 32 (four comma-separated values for APP_KEYS):

HOST=0.0.0.0
PORT=1337
NODE_ENV=production
URL=https://cms.example.com
APP_KEYS=key1,key2,key3,key4
API_TOKEN_SALT=...
ADMIN_JWT_SECRET=...
TRANSFER_TOKEN_SALT=...
JWT_SECRET=...
ENCRYPTION_KEY=...
DATABASE_CLIENT=postgres
DATABASE_HOST=<postgres service host>
DATABASE_PORT=5432
DATABASE_NAME=strapi
DATABASE_USERNAME=strapi
DATABASE_PASSWORD=...
DATABASE_SSL=false

HOST=0.0.0.0 is the Traefik rule again; URL is the public address so the admin panel builds its links correctly behind the proxy. Keep the secrets stable across deploys: changing APP_KEYS or ADMIN_JWT_SECRET logs every admin out, and changing ENCRYPTION_KEY breaks encrypted fields.

Step 3: a Dockerfile that builds the admin panel

FROM node:22-alpine AS build
RUN apk add --no-cache build-base gcc autoconf automake zlib-dev libpng-dev vips-dev git
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
ENV NODE_ENV=production
RUN npm run build

FROM node:22-alpine
RUN apk add --no-cache vips-dev
WORKDIR /app
ENV NODE_ENV=production HOST=0.0.0.0 PORT=1337
COPY --from=build /app ./
EXPOSE 1337
CMD ["npm", "run", "start"]

The build stage compiles sharp (Strapi's image processing) and the admin panel; the runtime stage keeps only vips. Choose the Dockerfile build type in Dokploy and add the domain on port 1337 with HTTPS. Nixpacks works too for a quick start, but Strapi's admin build is where memory runs out, so the Dockerfile's explicit stages are worth having.

Step 4: uploads, the part that gets lost on redeploy

Strapi stores media in public/uploads inside the container, which is gone on the next deploy unless you persist it. Two options:

Step 5: memory, builds and the first admin

Strapi runs at 300 to 500 MB but its admin build can need 2 GB or more, so a Strapi server wants the Growth preset (8 GB) or at least a 2 GB NODE_OPTIONS=--max-old-space-size=2048 cap on Starter, with one build at a time (Dokploy's default). Our slow builds post covers exit code 137 if the build dies. After the first deploy open https://cms.example.com/admin to create the first administrator, then create API tokens for your frontend (Astro, SvelteKit or Next.js in the same project reach Strapi over the Docker network at build time).

Behind the proxy: the settings that make the admin and API behave

Cost against Strapi Cloud

Strapi with PostgreSQL and a frontend fits the MassiveGRID Starter preset (2 vCPU, 4 GB RAM, 64 GB NVMe) at $9.58 a month on shared cores, or $19.80 on dedicated cores when build times and response latency must stay steady; the Growth preset (4 vCPU, 8 GB) at $19.16 or $39.60 adds room for previews, a worker and a second project. Dokploy is free, MassiveGRID installs it on request after you order from the Dokploy hosting page, and the server runs on a Proxmox HA cluster with Ceph storage and a 15-day money-back guarantee.

Strapi Cloud prices per project with seat and asset limits per tier (check strapi.io/pricing for current figures); self-hosting has no per-seat, per-entry or per-asset limits beyond the server.

Frequently Asked Questions

Can Strapi run on SQLite in production on Dokploy?

It can start, but Strapi’s own guidance is PostgreSQL or MySQL for production, and on Dokploy the database is a one-click service with scheduled backups, so there is no reason not to. SQLite inside a container also lives on the container filesystem unless you mount a volume for it.

Why does Strapi fail to start with a missing APP_KEYS or JWT error?

Because Strapi 5 requires APP_KEYS, API_TOKEN_SALT, ADMIN_JWT_SECRET, TRANSFER_TOKEN_SALT, JWT_SECRET and ENCRYPTION_KEY in production. Set all six in Dokploy’s Environment tab, keep them unchanged between deploys, and redeploy.

How do I keep Strapi uploads after a redeploy?

Mount a named volume at /app/public/uploads (and add it to Volume Backups), or configure the S3 upload provider so media lives in a bucket. Without one of the two, the uploads directory is recreated empty with every new container.

Dokploy hosting from $9.58 a month

A MassiveGRID VPS preset for Dokploy: 2 vCPU, 4 GB RAM and 64 GB NVMe for $9.58 a month on shared cores or $19.80 on dedicated cores, in New York, London, Frankfurt or Singapore, on a Proxmox HA cluster with Ceph storage, a 100% uptime SLA and a 15-day money-back guarantee. Run the one-line installer yourself or open a ticket and we install Dokploy for you.

Configure a Dokploy server

Further Reading