Simplifying Ghost Setup with Docker: My Journey from Complexity to Clarity

The Initial Challenge
When I decided to set up Ghost for my blog, I thought it would be straightforward. I had some Docker experience, and Ghost seemed like a popular, well-documented platform. Little did I know I was about to embark on a debugging journey that would teach me valuable lessons about complexity vs simplicity.
The Complex Setup That Failed
I started with what seemed like a comprehensive Ghost development environment, a monorepo setup with 15+ services. Here's what I initially tried to run:
The Docker Compose File has 317 lines. What I started with was a complex monorepo setup for services:
server: Ghost Server (2GB RAM)
admin: Ghost Admin (Port 4200)
combined: Combined Ghost (Multiple ports)
mysql: MySQL 8.4.5 (Port 3306)
redis: Redis 7.0 (Port 6379)
caddy: Reverse Proxy (Ports 80, 443)
mailhog: Email Testing (Ports 1025, 8025)
analytics: Analytics Service (Port 3000)
tinybird-local: TinyBird Local (Port 7181)
Prometheus: Prometheus (Port 9090)
Grafana: Grafana (Port 3000)
pushgateway: Push Gateway (Port 9091)
portal: Portal (Ports 4175-4176)
comments-ui: Comments UI (Ports 7173-7174)
announcement-bar: Announcement Bar (Port 4177)
search: Search (Port 4178)
signup-form: Signup Form (Port 6174)
... and more!
Resource Requirements:
Memory: 8-16GB RAM
CPU: High-end development machine
Storage: Several GB for all the services
Network: 15+ port mappings
Major Issues I Encountered
- SSH_AUTH_SOCK Error: Invalid interpolation format for "volumes" service "server": invalid mount config for type "bind": Bind source path does not exist: /tmp/ssh-agent
What I Tried: Setting the SSH_AUTH_SOCK environment variable
- Memory Issues - Admin Killed Error: Admin service killed due to memory constraints. Ghost admin container exiting with code 137
What I Tried:
Increasing Docker memory limits
Closing other applications
Theme Errors Theme error: Could not load theme. Failed to build admin assets
Port Conflicts Error: Port 3000 already in use. Cannot bind to port 4200
Build Failures ERROR: failed to solve: process "/bin/sh -c yarn install" did not complete successfully: exit code 1
The Solution: Simplicity Wins
After hours of debugging, I made a crucial decision: Start simple, then scale up.
Instead of trying to run a full development environment, I switched to the official Ghost Docker image. Here's what changed everything:
The Simple Setup That Works
My working solution - Clean and simple services:
version: '3.8'
services:
ghost:
image: ghost:latest # Official Ghost image
restart: always
ports:
- "2368:2368"
environment:
database__client: mysql
database__connection__host: mysql
database__connection__user: root
database__connection__password: yourpassword
database__connection__database: ghost
url: http://localhost:2368
NODE_ENV: development
volumes:
- ghost_content:/var/lib/ghost/content
depends_on:
mysql:
condition: service_healthy
deploy:
resources:
limits:
memory: 512M
mysql:
image: mysql:8.0
restart: always
ports:
- "3307:3306"
environment:
MYSQL_ROOT_PASSWORD: yourpassword
MYSQL_DATABASE: ghost
volumes:
- mysql_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
timeout: 20s
retries: 10
adminer:
image: adminer:latest
restart: always
ports:
- "8080:8080"
volumes:
ghost_content:
mysql_data:
Result: From 317 lines to 62 lines, from 15+ services to 3 services, from 8-16GB RAM to 1.5GB RAM.
Step-by-Step Working Setup
Here's exactly how I got Ghost running:
Step 1: Clean Slate Remove all previous containers and images docker-compose down -v docker system prune -a
Step 2: Create the Simple Docker Compose. yml Create a new docker-compose.yml with the simple setup above, touch docker-compose.yml. Copy the working configuration
Step 3: Start the Services Start Ghost with the new setup: docker-compose up -d
Check if everything is running with docker-compose ps
Total Setup Time: 2 minutes Memory Usage: ~1.5GB Success Rate: 100%
Lessons Learned
Start Simple, Scale Later Mistake: Trying to run a full development environment when I just needed Ghost. Lesson: Use official images first, then customise when you understand the system
Official Images Are Your Friend Mistake: Assuming custom builds are better. Lesson: Official Docker images are tested, stable, and maintained
Resource Management Matters Mistake: Ignoring memory and CPU requirements. Lesson: Always check your system resources before running complex setups
Debugging Skills Are Essential Mistake: Not systematically debugging each error. Lesson: Break down problems, test one component at a time
Next Steps: Contributing to Open Source
Now that I have a stable Ghost setup, I've created a learning path to eventually contribute to Ghost as an open source project:
Final Thoughts
This experience taught me that simplicity is not the enemy of power. My current Ghost setup gives me:
All the features I need for blogging
A stable, reliable environment
Room to learn and grow
A foundation for future development
Sometimes the best solution is not the most complex one. Start with what works, understand it completely, then add complexity when you actually need it.
Have you faced similar challenges setting up development environments? Share your experiences in the comments below!




