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).
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.
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.
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