Ghost is a fast, focused publishing platform used by everyone from solo bloggers to large media teams. The official Docker image makes deployment approachable, but production Ghost has specific requirements: MySQL 8 (not SQLite), persistent storage for uploaded images, correct URL config, and working email. Let's cover all of it.
Ghost's production requirements
Ghost officially supports two databases: SQLite (for local/dev) and MySQL 8 for production. As of recent versions, MySQL 8 is the recommended and supported production database. You'll also need:
- Persistent storage for
/var/lib/ghost/content(images, themes, settings) — or an external storage adapter. - A correct
url— Ghost bakes its public URL into generated links, so getting this right matters. - A mail provider for member signups, password resets, and newsletters.
Running the official image
The official ghost image is well maintained. Configure it entirely through environment variables (Ghost maps database__connection__* style vars to its config):
NODE_ENV=production
url=https://blog.example.com
database__client=mysql
database__connection__host=<db-host>
database__connection__port=3306
database__connection__user=<db-user>
database__connection__password=<db-password>
database__connection__database=<db-name>Ghost automatically runs its own database migrations on startup, so you don't manage migrations manually — just point it at an empty MySQL 8 database and it initializes the schema.
The persistent content directory
This is the most common Ghost deployment mistake. Ghost stores uploaded images, installed themes, and some settings in /var/lib/ghost/content. In a container, that directory is ephemeral by default — redeploy and your images are gone.
Two solutions:
- 1Mount a persistent volume at
/var/lib/ghost/content. - 2Use a storage adapter that writes images to S3-compatible object storage instead of local disk.
For a containerized cloud deployment, the storage-adapter route is cleaner because it works seamlessly across redeploys and replicas. A community S3 storage adapter handles this; configure it via env vars pointing at your bucket.
Email configuration
Ghost uses email for transactional messages and (with a bulk provider like Mailgun) newsletters. Set the mail transport:
mail__transport=SMTP
mail__options__host=smtp.example.com
mail__options__port=587
mail__options__auth__user=<smtp-user>
mail__options__auth__pass=<smtp-pass>Without working mail, member signups and staff invites silently fail — test this early.
A note on the URL setting
Ghost generates absolute URLs (canonical tags, RSS, sitemap, email links) from the url value. Set it to your real public HTTPS URL from the start. Changing it later requires care because existing content may reference the old domain.
Deploying on PandaStack
- 1Create a MySQL 8 database — connection details are injected as env vars; map them to Ghost's
database__connection__*variables. - 2Connect the official
ghostimage (or a thin Dockerfile based on it) as a container app. - 3Set
url, the database vars, and mail vars in the dashboard. - 4Configure an S3-compatible storage adapter for images so media survives redeploys.
- 5Push — Ghost migrates its schema on boot, and you get automatic SSL on your custom domain.
| Concern | Production value |
|---|---|
| Database | MySQL 8 (managed) |
| Content/media | Object storage adapter |
| URL | Real public HTTPS URL |
| SMTP / bulk provider | |
| Port | 2368 |
Common pitfalls
- SQLite in production — unsupported at scale; data lives in the ephemeral filesystem.
- No persistent storage for
content/— uploaded images disappear on redeploy. - Wrong
url— broken links, RSS, and emails. - No mail provider — silent failures on signups and invites.
- Forgetting Ghost runs on port 2368 — map your service port correctly.
References
- Ghost official documentation: https://ghost.org/docs/
- Ghost Docker image: https://hub.docker.com/_/ghost
- Ghost configuration reference: https://ghost.org/docs/config/
- Ghost MySQL requirement: https://ghost.org/docs/install/ubuntu/#requirements
- Ghost storage adapters: https://ghost.org/integrations/custom-integrations/
---
PandaStack's free tier includes a container app and a managed MySQL database — deploy the official Ghost image, add an object-storage adapter for media, and get automatic SSL on your domain. Start at https://dashboard.pandastack.io