Skip to main content
To self-host a Ghost blog with Docker, clone Ghost’s official TryGhost/ghost-docker repository to /opt/ghost, copy .env.example to .env and caddy/Caddyfile.example to caddy/Caddyfile, then set your domain, two database passwords and SMTP details. Run docker compose pull and docker compose up -d, and open https://example.com/ghost to create your account.

What is Ghost?

Ghost is an open-source publishing platform for blogs, newsletters and paid memberships. The official Docker setup runs four parts: Ghost itself (ghost:6-alpine), a MySQL 8 database, the Caddy web server, which gets and renews HTTPS certificates automatically, and optional analytics and ActivityPub services.

Before you start

  • Docker 20.10.13 or newer with the Compose plugin: install Docker. Check with docker --version.
  • A domain with an A record pointing to your server. See point a domain to your server.
  • Ports 80 and 443 free. Caddy in this stack uses them. Stop any Nginx or Apache on the server first, or use a separate server.
  • An SMTP service for transactional email. Ghost needs it for staff logins, invites and password resets. This is separate from newsletter sending.
  • Ghost’s guide uses a 2 GB RAM / 1 CPU server as its example.
  • The commands use sudo; leave it out if you are root.

How to install Ghost with Docker

1

Clone the official repository

2

Copy the example files

3

Generate two database passwords

Use the first for DATABASE_ROOT_PASSWORD and the second for DATABASE_PASSWORD.
4

Edit .env

Open it with sudo nano .env and set at least:
Don’t change the DATABASE_ values after the first start. To run Ghost Admin on its own domain, also set ADMIN_DOMAIN=admin.example.com and uncomment the matching block in caddy/Caddyfile.
5

Start Ghost

Caddy requests a Let’s Encrypt certificate for DOMAIN on the first request, so the A record must already point here.
6

Create your account

Open https://example.com/ghost, then enter your site title, your name, email and a strong password. This first account becomes the site owner.
Complete the /ghost setup straight after the site goes live. Until you do, whoever opens it first can create the owner account.

How does HTTPS work in this setup?

You don’t need Certbot or a separate reverse proxy. Caddy is the reverse proxy: it listens on ports 80 and 443, gets the certificate, and forwards requests to Ghost on the internal network (ghost:2368). Ghost and MySQL publish no ports to the internet. To redirect www.example.com to example.com, add DNS for both names and uncomment the www block in caddy/Caddyfile, replacing CHANGE_ME with your domain.

How to check it worked

The caddy, ghost and db services show Up, and curl returns a 200 response with a valid certificate. If the site doesn’t load, read sudo docker compose logs caddy, then sudo docker compose logs ghost.

How to back up Ghost

Your content is in two places under /opt/ghost/data: ghost (images, themes and files) and mysql (the database). Dump the database and archive the content folder:
Copy both files off the server. See back up and restore MySQL databases and back up Docker volumes.

How to update Ghost

Back up first, then pull the latest stack definition and images:
After changing .env, apply it with sudo docker compose up -d --force-recreate ghost. If you change DOMAIN or ADMIN_DOMAIN, recreate both: sudo docker compose up -d --force-recreate ghost caddy.

Frequently asked questions

Why can’t I log in or invite staff?

Ghost needs working transactional email for logins, staff invites and password resets. Check the mail__ settings in .env, recreate the ghost container and look for mail errors in sudo docker compose logs ghost.

Can I send newsletters from a self-hosted Ghost?

Yes, with a bulk email service. The SMTP settings above only cover transactional email; newsletters need separate configuration. See Ghost’s mail configuration docs.

Can I keep Nginx on the same server?

This official stack expects ports 80 and 443 for Caddy. .env lets you change HTTP_PORT and HTTPS_PORT, but then you must route traffic and certificates yourself. A dedicated server or VPS for Ghost is simpler.

How do I enable web analytics or ActivityPub?

Both are optional profiles. Set COMPOSE_PROFILES=analytics (with a Tinybird account) or COMPOSE_PROFILES=activitypub in .env and follow the Ghost Docker guide.

How do I move an existing Ghost-CLI install to Docker?

The repository includes scripts/migrate.sh. It stops Nginx, so other sites on that server go offline during the move. Read the migration section of the Ghost Docker guide first.

VPS and dedicated server guides

Every guide in this section.

Install Docker

Docker Engine from the official repository.

Run WordPress with Docker Compose

Another blog platform in Docker.

Update Docker containers

Pull new images safely.

Check if a port is open

Test ports 80 and 443.

Checked against the official Ghost Docker documentation and the TryGhost/ghost-docker repository on 4 November 2026 (images ghost:6-alpine, mysql:8.0.46, caddy:2.11.7-alpine); the repository’s compose.yml validated with docker compose config on Ubuntu 24.04 LTS. The stack can change with each repository update.

Need Extra Help?

If you encounter any issues, our support team is ready to assist:

Save on Your Hosting

Ready to upgrade your hosting? Use code KB20 at checkout for 20% off your first order!

Last Updated: November 2026