Updating ghost container issues

I am currently self hosting ghost using docker. Whenever i need to update the container, i lose all of my content. I mitigate this by using the “export content” feature in ghost prior to re-pulling the image, then import it after it has been updated. Is there a way to avoid this? I have /var/lib/ghost/content volume mapped and that stays untouched during the update. It seems the database for my site gets wiped every time.

Apart from having a volume for the Ghost content directory, you would also need a volume for your database. Otherwise, it won’t persist after a container restart (or update, in your case).

If you want specific help for implementing it, feel free to post your compose file/docker run command here (and remove any sensitive information, such as passwords first).

1 Like

I am using portainer and installed the container from there. So i don’t have a compose file or run command, here are some of the enviroments and volumes:

Volume:
/portainer/Files/AppData/Config/Ghost → /var/lib/ghost/content

Env:

GHOST_CLI_VERSION 1.25.3
GHOST_CONTENT /var/lib/ghost/content
GHOST_INSTALL /var/lib/ghost
GHOST_VERSION 5.75.2
GOSU_VERSION 1.16
NODE_ENV development
NODE_VERSION 18.19.0
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
url https://www.mywebsite.com
YARN_VERSION 1.22.19

Let me know what other information you need. It sounds like I just need to map the DB, where is that generally installed in the container?

So, I assume you just used the “one-click” app template in Portainer?

Just tried it and out of the box, it’s looking for a MySQL database on the same server. Did you set that up? It should be a separate container.

I did the one click setup, i did not have any option to setup a mysql database, nor is there a separate container.

Hm, I honestly don’t know how Portainer sets up the database then. What does it say when you click on Settings → About Ghost inside your Ghost Admin?

It says the following:

Update available!

Ghost is currently unable to send email. See Configuration - Adapt your publication to suit your needs for instructions.

Version: 5.75.2

Environment: development

Database: sqlite3

Mail: Direct


User documentationGet help with GhostGet involved


Alright, your problem is that you’re using SQLite, apparently stored within the Ghost container. Since it doesn’t seem to be mounted as a volume, a restart of the container “resets” it.

Additionally, SQLite is not supported for Ghost in production anymore: Supported databases in production for self-hosting Ghost - Ghost Developers

I would recommend you to ditch the one-click install. If you want to keep using Portainer, set up a normal stack (select “Stacks” in the navigation panel inside an environment) using a Docker compose file.

@ajfriesen has a great post on running Ghost with Docker compose, which includes the MySQL database you need:

I suggest having a look there and adapting the docker compose file as you need.

Here is my compose file, it just throws me a bunch of caddy errors when trying to deploy it in portainer:

version: ‘3’

services:

caddy:
image: caddy:2
restart: always
ports:
- “80:80”
- “443:443”
volumes:
- /portainer/Files/AppData/Config/Caddyfile:/etc/caddy/Caddyfile
- /portainer/Files/AppData/Config/caddy-data:/data
networks:
- docker-network

ghost:
image: ghost:latest
restart: always
environment:
database__client: mysql
database__connection__host: db
database__connection__database: ghost
database__connection__user: ghost
database__connection__password: “SECRET”
url: www.website.com
# mail__transport: “SMTP”
# mail__options__host: “${MAIL_HOST}”
# mail__options__port: “${MAIL_PORT}”
# mail__options__secureConnection: “${MAIL_SECURE_CONNECTION}”
# mail__options__auth__user: “name@website.com
# mail__options__auth__pass: “SECRET”
ports:
- “2370:2368”
volumes:
- /portainer/Files/AppData/Config/ghost-data:/var/lib/ghost/content
links:
- db

db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: “SECRET”
MYSQL_DATABASE: ghost
MYSQL_USER: ghost
MYSQL_PASSWORD: “SECRET”
cap_add:
- SYS_NICE
volumes:
- /portainer/Files/AppData/Config/ghost-db:/var/lib/mysql

volumes:
ghost-data:
ghost-db:
caddy-data:

so I removed caddy out of the compose because i use cloudflare for reverse proxing. Now i get this error from ghost:

[2024-04-06 00:51:02] WARN Ghost is shutting down

[2024-04-06 00:51:02] WARN Ghost has shut down

[2024-04-06 00:51:02] WARN Your site is now offline

[2024-04-06 00:51:02] WARN Ghost was running for a few seconds

[2024-04-06 00:51:31] INFO Ghost is running in production…

[2024-04-06 00:51:31] INFO Your site is now available on https://www.website.com/

[2024-04-06 00:51:31] INFO Ctrl+C to shut down

[2024-04-06 00:51:31] INFO Ghost server started in 2.305s

[2024-04-06 00:51:32] ERROR Host ‘172.25.0.3’ is not allowed to connect to this MySQL server

Host ‘172.25.0.3’ is not allowed to connect to this MySQL server

“Unknown database error”

Can you post your current docker compose file (ideally using the code formatting)?

version: '3'

services:

  ghost:
    image: ghost:latest
    restart: always
    environment:
      database__client: mysql
      database__connection__host: db
      database__connection__database: ghost
      database__connection__user: ghost
      database__connection__password: "SECRET"
      url: https://www.website.com
      # mail__transport: "SMTP"
      # mail__options__host: "${MAIL_HOST}"
      # mail__options__port: "${MAIL_PORT}"
      # mail__options__secureConnection: "${MAIL_SECURE_CONNECTION}"
      # mail__options__auth__user: "name@website.com"
      # mail__options__auth__pass: ""
    ports:
      - "2370:2368"
    volumes:
      - /portainer/Files/AppData/Config/ghost-data:/var/lib/ghost/content
    links:
      - db

  db:
    image: mysql:8.0
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: "ROOT_SECRET"
      MYSQL_DATABASE: ghost
      MYSQL_USER: ghost
      MYSQL_PASSWORD: "SECRET"
    cap_add:
      - SYS_NICE
    volumes:
      - /portainer/Files/AppData/Config/ghost-db:/var/lib/mysql

volumes: 
  ghost-data:
  ghost-db:

Check the solution from the docker-library container if you plan to use docker for your production environment: Docker

If you plan to use kubernetes, Icheck my repo: GitHub - sredevopsorg/ghost-on-kubernetes: Deploy a full Self Hosted Ghost 5 CMS (from @TryGhost), compatible with any Kubernetes ≥ 1.27 (k3s, GKE, AKS, etc), production-ready, using our custom hardened distroless non root image.

That is the exact docker image I’m using and if you notice the instructions say it uses sqllite which jannis just said is no longer supported

The only way to not lose the ball is to deploy it using docker compose (or at least the simplest and the easiest)

So, the error surprised me a bit:

Host ‘172.25.0.3’ is not allowed to connect to this MySQL server

This isn’t a docker networking issue but comes from within the MySQL container.

Did a quick Google and this seems to be connected to the way the volumes are configured. What I noticed in your case is that you define a ghost-data and a ghost-db volume, but never actually use them. Instead, you mount the file paths.

I would suggest changing the volumes to the ones you have defined:

    volumes:
      - ghost-data:/var/lib/ghost/content

and

    volumes:
      - ghost-db:/var/lib/mysql

So this allowed me to create the containers without any errors. However when i go to the site, i just get a general connection error. When checking the logs there are no error messages or anything.

i actually got it fixed for now. Thank you.

2 Likes

Huzzah!

If you have new knowledge to share for users who might have a similar issue, I hope you’ll update the thread so that future users with a similar problem can find a solution.

1 Like

Based on what @Rob_Wright and @jannis posted on Updating ghost container issues - #16 by jannis

I guess the solution for them was realizing that the volumes has to be managed separately, but I strongly recommend to use mounts in docker compose instead of volumes, because the volumes are managed by your setup of docker and you have potential data loss if the installation deletes those volumes.

A better example for docker compose would be:

services:

  ghost:
    image: docker.io/ghost:5
    restart: unless_stopped
    env_file:
      - dev.env
    environment:
      database__client: ${DB_CLIENT}
      database__connection__host: ${DB_HOST}
      database__connection__database: ${DB_DATABASE}
      database__connection__user: ${DB_USER}
      database__connection__password: ${DB_PASSWORD}
      url: ${GHOST_URL} # Depends on environment, can be http://localhost:2368
      # mail__transport: "SMTP"
      # mail__from: "${MAIL_FROM}"
      # mail__options__service: "${MAIL_SERVICE}"
      # mail__options__host: "${MAIL_HOST}"
      # mail__options__port: "${MAIL_PORT}"
      # mail__options__secureConnection: "${MAIL_SECURE_CONNECTION}"
      # mail__options__auth__user: "name@website.com"
      # mail__options__auth__pass: ""
    ports:
      - "2370:2368"
    volumes:
      - ./dev-env-data/ghost:/var/lib/ghost/content
    depends_on:
      - db

  db:
    image: mysql:8.2
    restart: unless-stopped
    env_file:
      - dev.env
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${DB_DATABASE}
      MYSQL_USER: ${DB_USER}
      MYSQL_PASSWORD: ${DB_PASSWORD}
      MYSQL_HOST: ${DB_HOST}

    volumes:
      - ./dev-env-data/ghost:/var/lib/mysql

The file dev.env should content secrets in the form of

DB_CLIENT=value
DB_HOST=value
GHOST_URL=value