Deploying a Ghost CMS with Docker and Portainer

Deploying a Ghost CMS with Docker and Portainer

You can build your own or deploy one easily with Docker.  I choose the easy way.

I started with a Linode droplet as a Docker server.  On this server, I added Portainer Community Edition.  Portainer is an excellent web-based tool to deploy and maintain Docker instances.

The first stack I deployed was Nginx Proxy Manager (NPM).  NPM allows me to set up reverse proxy configurations to Portainer and Ghost instances with LetsEncrypt certificates for HTTPS connections.

The initial setup of Portainer was via HTTP and thus in the clear.  After setting up the reverse proxy with HTTPS to Portainer, I immediately added a new admin account and deleted the one I created during setup.  Better safe than sorry when credentials are sent in the clear.

Every Ghost instance is easily repeatable with the following stack.  I just needed to set up a new domain and mail service before getting deployment.

    external: true
    name: nginx-proxy-manager_default


    image: ghost:4.41.3-alpine
    container_name: ghost_sitename
    restart: always
      - data:/var/lib/ghost/content
      mail__transport: "SMTP"
      mail__from: "'Site Name' <>"
      mail__options__service: "SMTP"
      mail__options__host: ""
      mail__options__port: 587
      mail__options__pool: "true"
      mail__options__auth__user: ""
      mail__options__auth__pass: "yourverylongpassword"
Docker Stack for Ghost
IMPORTANT: All of the Ghost stacks and Portainer container need to be in the name network as the Nginx Proxy Manager or else you will spend hours trying to figure out why your newly set up Ghost CMS does not work. Speaking from experience, of course.

I will need to eventually move over from sqlite3 to mySQL or another database engine before the next major release of Ghost.   The next major revision of Ghost will not support sqlite3, although I like it for these small sites due to the low memory overhead.

The data remains portable through the use of the "volume" declaration.  In Portainer the volume is named "ghost-sitename_data".

Updating is easy.  I modify the image in the stack to the current version and restart.  Easy as pie.

John Schroeder