Docker says "SQLSTATE[HY000] [2002] Connection refused"

Hello,
I have a Laravel project and I want to run it in a container.
The startup.sh file is:

#!/bin/sh
set -e

echo "Waiting for the database to be ready..."
while ! nc -z db 3306; do
  sleep 1
done
echo "Database is ready!"

composer install --no-dev --no-scripts

php artisan package:discover

# Start PHP-FPM
exec php-fpm

The Dockerfile is:

FROM php:fpm-alpine3.20

WORKDIR /var/www/html

RUN apk update && apk add --no-cache \
    libzip-dev \
    zip \
    unzip \
    libpng-dev \
    libjpeg-turbo-dev \
    freetype-dev \
    oniguruma-dev \
    curl \
    git \
    mysql-client \
    autoconf \
    dpkg-dev \
    dpkg \
    file \
    g++ \
    gcc \
    libc-dev \
    make \
    re2c

RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd pdo_mysql zip mbstring

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

COPY . .

COPY startup.sh /usr/local/bin/startup.sh

RUN chmod +x /usr/local/bin/startup.sh

RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

EXPOSE 9000

ENTRYPOINT ["startup.sh"]

The docker-compose.yml is:

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: laravel_app
    restart: unless-stopped
    volumes:
      - .:/var/www/html
    networks:
      - laravel_network
    depends_on:
      - db
    environment:
      DB_CONNECTION: mysql
      DB_HOST: db
      DB_PORT: 3306
      DB_DATABASE: laravel_db
      DB_USERNAME: laravel_user
      DB_PASSWORD: secret

  db:
    image: mysql:latest
    container_name: laravel_db
    restart: unless-stopped
    environment:
      MYSQL_DATABASE: laravel_db
      MYSQL_USER: laravel_user
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: rootsecret
      TZ: UTC  
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - laravel_network

    deploy:
      resources:
        limits:
          memory: 1G  # Increase memory limit
          cpus: '1.0'  # Allocate CPU

  phpmyadmin:
    image: phpmyadmin:latest
    container_name: laravel_phpmyadmin
    restart: unless-stopped
    ports:
      - "8081:80"
    environment:
      PMA_HOST: db
      MYSQL_ROOT_PASSWORD: rootsecret
    depends_on:
      - db
    networks:
      - laravel_network

volumes:
  mysql_data:
    driver: local

networks:
  laravel_network:
    driver: bridge

And the .env file contains the following section:

DB_CONNECTION=mysql
   DB_HOST=db
   DB_PORT=3306
   DB_DATABASE=laravel_db
   DB_USERNAME=laravel_user
   DB_PASSWORD=secret

When I run the containers I get the following error:

Installing dependencies from lock file
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating optimized autoload files
55 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
In Connection.php line 825:
  SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select *
   from `permissions` where `permissions`.`deleted_at` is null)
In Connector.php line 67:
  SQLSTATE[HY000] [2002] Connection refused
Installing dependencies from lock file
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating optimized autoload files
55 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
In Connection.php line 825:
  SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select *
   from `permissions` where `permissions`.`deleted_at` is null)
In Connector.php line 67:
  SQLSTATE[HY000] [2002] Connection refused
Installing dependencies from lock file
Verifying lock file contents can be installed on current platform.
Nothing to install, update or remove
Generating optimized autoload files
55 packages you are using are looking for funding.
Use the `composer fund` command to find out more!
In Connection.php line 825:
  SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select *
   from `permissions` where `permissions`.`deleted_at` is null)
In Connector.php line 67:
  SQLSTATE[HY000] [2002] Connection refused

Why?

Thank you.

Because this bit it checking of MySQL is running in the current container, i.e. the PHP container, which it isn’t, because it’s running in the MySQL container.

while ! nc -z db 3306; do
  sleep 1
done

Honestly, I wouldn’t run composer or artisan in a startup script at all. Just run them through docker compose exec once everything is up and running and prevents nasty timing issues.

Hi,
Thank you so much for your reply.
Can you be more clear? If possible, edit the Dockerfile and docker-compose.yml files.

Looking more closely that doesn’t seem to be the problem after all. Are you sure Laravel is configured correctly to use the database credentials passed from docker-compose.yaml?

Hello,
The problem can be solved by adding a my.cnf file with the following contents:

$ cat mysql/my.cnf
[mysqld]
#
# * Basic Settings
#
pid-file        = /var/run/mysqld/mysqld.pid

Then, change the docker-compose.yml file to the following:

...
  db:
    image: mysql:latest
    container_name: db
    restart: unless-stopped
    tty: true
    environment:
      MYSQL_DATABASE: laravel_db
      MYSQL_USER: laravel_user
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: rootsecret
      TZ: UTC
    volumes:
      - dbdata:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
...

Hello,
I changed compose file and database engine (MariaDB). The docker-compose.yml file looks like this:

services:
  backend:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: Backend
    ports:
      - "9000:9000"
    environment:
      - APP_ENV=local
      - APP_DEBUG=true
      - DB_CONNECTION=mysql
      - DB_HOST=db
      - DB_PORT=3306
      - DB_DATABASE=laravel_db
      - DB_USERNAME=laravel_user
      - DB_PASSWORD=secret
    depends_on:
      - db
    networks:
      - app_network
    # restart: unless-stopped

  db:
    image: mariadb:latest
    container_name: db
    ports:
      - "3306:3306"
    environment:
      MARIADB_ROOT_PASSWORD: rootsecret
      MARIADB_DATABASE: laravel_db
      MARIADB_USER: laravel_user
      MARIADB_PASSWORD: secret
    volumes:
      - mariadb_data:/var/lib/mysql
      - ./mysql/my.cnf:/etc/mysql/my.cnf
      # - ./p.sql:/docker-entrypoint-initdb.d/p.sql
    networks:
      - app_network
    # restart: unless-stopped

networks:
  app_network:
    driver: bridge

volumes:
  mariadb_data:

And Dockerfile looks like this:

# Stage 1: Composer
FROM composer:2.7 AS composer
WORKDIR /app
COPY . .
RUN composer install \
    --ignore-platform-reqs \
    --no-interaction \
    --no-scripts \
    --optimize-autoloader
# Stage 2: Node.js
FROM node:23-alpine AS node
WORKDIR /app
COPY --from=composer /app .
RUN npm install && npm run build
# Stage 3: PHP-FPM (Fixed)
FROM php:8.3-fpm-alpine
RUN apk add --no-cache \
    bash \
    git \
    libzip-dev \
    libpng-dev \
    && docker-php-ext-install \
    pdo_mysql \
    zip \
    gd \
    bcmath
COPY --from=composer /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html
COPY --from=composer /app .
COPY --from=node /app/public/build ./public/build
RUN chown -R www-data:www-data /var/www/html/storage \
    && chmod -R 775 /var/www/html/storage \
    && chmod +x /var/www/html/artisan
COPY ./entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
CMD ["php-fpm"]

And entrypoint.sh looks like this:

#!/bin/sh
set -e
# Run Artisan commands (migrations, cache, etc.)
php artisan optimize:clear
php artisan optimize
php artisan view:cache
# Start PHP-FPM (or other services via supervisor if needed)
exec "$@"

The .env file is as follows:

DB_CONNECTION=mysql
 DB_HOST=db
 DB_PORT=3306
 DB_DATABASE=laravel_db
 DB_USERNAME=laravel_user
 DB_PASSWORD=secret

I have imported the p.sql file into the container. When I run the containers, the following error is shown:

# docker logs Backend
In Connection.php line 825:
  SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select *
   from `permissions` where `permissions`.`deleted_at` is null)
In Connector.php line 66:
  SQLSTATE[HY000] [2002] Connection refused

Please guide me on how I can troubleshoot this problem.

Thank you.