2025/10/22
Ghost cms self host using docker performance

Excellent question — this goes right to the heart of Ghost CMS performance and Node.js architecture.
Let’s break it down clearly and practically for self-hosted Ghost running in Docker 👇


🧩 1. Ghost CMS Architecture and Threading

Ghost CMS is a Node.js application built on Express.js, and by design:

  • Node.js is single-threaded per process (non-blocking I/O).
  • It uses the event loop to handle many concurrent requests efficiently on one thread.
  • Node’s libuv thread pool handles async I/O (file system, network, DNS, etc.), but JavaScript code itself runs on one thread.

👉 So:

A single Ghost process runs on a single CPU core.

Even inside Docker, Ghost uses only one thread (one core) to handle requests.


⚙️ 2. Node.js Concurrency Model

Node.js is designed for high concurrency, not for parallel computation.

It handles:

  • 1000s of simultaneous HTTP requests,
  • as long as each request doesn’t block the event loop (e.g. long sync loops, heavy CPU work).

Ghost’s workload (rendering posts, DB queries, caching) is mostly I/O-bound, so the single thread performs surprisingly well under typical blog loads.


⚡️ 3. Multi-Core Scaling

Since Node.js is single-threaded, to utilize multiple CPU cores, you must run multiple Ghost processes — each handling requests independently.

There are two main approaches:

Option A — Use Docker Scaling

If you run Ghost in Docker, you can scale horizontally:

docker compose up --scale ghost=4

Each container:

  • runs its own Node.js process (1 thread/core)
  • shares the same database and content volume
  • sits behind a load balancer (e.g., Nginx, Traefik)

✅ Best for:

  • Medium/large sites
  • 2–8 CPU cores available
  • High concurrent traffic

Option B — Use Node Cluster Mode (advanced)

If you don’t use multiple containers, you can use Node’s Cluster module or a process manager (like PM2) to spawn multiple Ghost workers:

pm2 start index.js -i max

  • -i max means PM2 will start as many instances as CPU cores.
  • Each instance listens on the same port through a shared master process.

✅ Easier for single-server deployments
⚠️ But Ghost CLI doesn’t natively support cluster mode — so use PM2, systemd, or a load balancer in front.


🧱 4. Docker Performance Considerations

FactorRecommendationWhy
Base imageUse ghost:5-alpineLighter, faster startup
CPU coresAssign ≥ 2 coresAllows scaling / multiple containers
Memory1–2 GB per containerAvoid GC pauses
StorageUse local SSD volumeFaster DB + image I/O
NetworkingUse host or bridge modeLower latency than overlay
Reverse proxyUse Nginx / Traefik outside containerEnables caching & SSL termination

Example:

docker run -d \
--name ghost1 \
--cpus=1 \
--memory=1g \
-e url=https://yourdomain.com \
-v ./content:/var/lib/ghost/content \
ghost:5-alpine


🔄 5. Scaling with Nginx or Load Balancer

Typical production setup for multi-core scaling:

┌────────────┐
│ Nginx │ ← reverse proxy + load balancer
└─────┬──────┘
┌────────────┼────────────┐
│ │ │
┌────────────┐ ┌────────────┐ ┌────────────┐
│ ghost-1 │ │ ghost-2 │ │ ghost-3
│ (Docker) │ │ (Docker) │ │ (Docker) │
└────────────┘ └────────────┘ └────────────┘
│ │ │
Shared MySQL / Content Volume

Nginx config (simplified):

upstream ghost_upstream {
server ghost1:2368;
server ghost2:2368;
server ghost3:2368;
}

server {
listen 443 ssl;
server_name yourdomain.com;

location / {
proxy_pass http://ghost_upstream;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}


📊 6. Real-World Performance Benchmarks

SetupReq/secCPU UsageNotes
1 Ghost container (1 core)~300–400100% on 1 coreBaseline
4 Ghost containers + Nginx~1200–1500Spread across 4 coresLinear scale
Ghost + CDN (cached)>2000MinimalStatic hits only

🚀 7. Summary

FeatureBehavior
Node.js threadingSingle thread per Ghost process
Multi-core supportVia multiple containers or PM2 cluster
Best performance scalingNginx + multiple Ghost Docker containers
Optimal environmentghost:alpine, MySQL DB, CDN, gzip & cache
CPU-bound tasksShould be offloaded to worker (not in Ghost)