ECONNREFUSED when deploying Ghost via Docker

Hi everyone, I am trying to deploy Ghost 5 via docker on my Synology NAS. The problem I am running into is that I keep getting an error that prevents Ghost from communicating with MySQL.

[2022-12-29 12:24:45] INFO Ghost is running in production...
[2022-12-29 12:24:45] INFO Your site is now available on http://localhost:2368/
[2022-12-29 12:24:45] INFO Ctrl+C to shut down
[2022-12-29 12:24:45] INFO Ghost server started in 21.608s
[2022-12-29 12:24:50] ERROR connect ECONNREFUSED 172.31.0.2:3306

connect ECONNREFUSED 172.31.0.2:3306

"Unknown database error"

Error ID:
    500

Error Code:
    ECONNREFUSED

----------------------------------------

Error: connect ECONNREFUSED 172.31.0.2:3306
    at /var/lib/ghost/versions/5.26.3/node_modules/knex-migrator/lib/database.js:57:19
    at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1278:16)

[2022-12-29 12:24:50] WARN Ghost is shutting down
[2022-12-29 12:24:50] WARN Ghost has shut down
[2022-12-29 12:24:50] WARN Your site is now offline
[2022-12-29 12:24:50] WARN Ghost was running for a few seconds

My docker-compose looks like this

version: "3.7"
services: 

  ghost:
    container_name: ghost
    image: ghost:latest
    volumes:
      - ./ghost/content:/var/lib/ghost/content
    environment:
      - database__client=mysql
      - database__connection__host=mysql
      - database__connection__user=root
      - database__connection__password=${MYSQL_PSW}
      - database__connection__database=${MYSQL_DB}
    ports:
      - 2368:2368
    depends_on:
      - mysql
    restart: unless-stopped

  mysql:
    container_name: ghost-laughandgrowfat-db
    image: 'mysql:latest'
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=${MYSQL_PSW}
    restart: unless-stopped

I honestly don’t know what to do anymore, I tried so many things and yet I can’t manage to deploy succesfully.

Any help is appreciated

Hey @AlexKalopsia,

I think you’re missing some mysql environment variables namely (Need to add these under the mysql container environment section with your MYSQL_ROOT_PASSWORD environment variable):

  MYSQL_DATABASE: new_database
  MYSQL_USER: database_user
  MYSQL_PASSWORD: mysql_password

Let us know how you get on and if that works.

Cheers,

Alex.

Hey everyone — wanted to share a detailed breakdown of the troubleshooting steps I went through to get Ghost working with a MySQL-compatible database via Docker Compose. Hopefully this helps someone else hitting similar errors!

:warning: Disclaimer:
While this troubleshooting guide recommends switching to MariaDB to resolve certain connectivity issues, please note that Ghost officially supports MySQL (versions 5.7 and above) as the primary database.
MariaDB is not officially listed as a supported database in the Ghost documentation, but it is a highly compatible drop-in replacement for MySQL and works well in many real-world scenarios.
If you prefer strict adherence to officially supported configurations, it is recommended to use MySQL. However, if MariaDB fits your environment and resolves your issues, it is a practical alternative.

Summary of Issues
While deploying Ghost using Docker Compose with a MySQL backend, I ran into repeated connection issues from Ghost to the DB. The issues encountered are listed below as well as the troubleshooting steps I took. Hopefully this can help others.

  • ECONNREFUSED errors
  • caching_sha2_password plugin errors (MariaDB client unable to connect to MySQL 8+)

:hammer_and_wrench: Troubleshooting Steps:

  1. Error: MYSQL_USER="root" not allowed

    • MySQL 8 entrypoint rejects MYSQL_USER=root as it conflicts with MYSQL_ROOT_PASSWORD.
    • :white_check_mark: Fix: Removed MYSQL_USER=root and just defined MYSQL_ROOT_PASSWORD.
  2. Error: connect ECONNREFUSED

    • Happens because Ghost tries to connect before the DB is ready to accept connections.
    • To address this, I amended the docker compose to ensure the frontend won’t start until after the backend.
ghost:
    image: ghost:5-alpine
    container_name: ghost
    restart: always
    depends_on:
      - db
    ports:
      - 8080:8080
    environment:
      database__client: mysql
      database__connection__host: db
      database__connection__user: ghost
      database__connection__password: ghost_password
      database__connection__database: ghost
      url: http://ghost.domain.com:8080
    volumes:
      - ghost:/var/lib/ghost/content
    networks:
      - ghost
  1. Interactive Testing Inside Container:
    I was able to perform test inside the container using the docker exec -it containerName bash command from the server, enableing me to login to the container.

    • Verified DNS resolution:

      ping db
      

      Output: successful pings confirming hostname resolves.

    • Tested connection using MariaDB client (since mysql was aliased to MariaDB):

      mysql -h db -u ghost -p
      

      Output:

      mysql: Deprecated program name. It will be removed in a future release, use '/usr/bin/mariadb' instead
      Enter password: 
      ERROR 2026 (HY000): TLS/SSL error: self-signed certificate in certificate chain
      

      (Indicated SSL/TLS issues when connecting.)

    • Attempted disabling SSL:

      mariadb --ssl=OFF -h db -u ghost -p
      

      Output:

      ERROR 1045 (28000): Plugin caching_sha2_password could not be loaded: Error loading shared library /usr/lib/mariadb/plugin/caching_sha2_password.so: No such file or directory
      

      (Showed incompatibility between MariaDB client and MySQL 8’s default authentication plugin.)

  2. Final Decision: Switch to MariaDB

    • Switched the DB container to use mariadb:11 image instead of MySQL 8 to avoid plugin compatibility issues.
    • Configured the user and password environment variables accordingly.
    • This eliminated plugin errors and SSL issues, allowing Ghost to connect successfully.