Mysql on docker gives "Connection refused" error

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

MySQL on Docker Gives "Connection Refused": A Deep Dive into Docker Networking Issues

As developers leveraging Docker and Docker Compose for local development environments—especially with frameworks like Laravel—we often encounter frustrating connectivity errors. The specific issue you’re facing, SQLSTATE[HY000] [2002] Connection refused, when trying to connect a PHP application inside a container to a MySQL database also running in another container, is almost always a networking configuration problem, not an error in the SQL syntax or the credentials themselves.

This post will dissect why this happens in a Docker setup and provide the definitive solution.

Understanding the "Connection Refused" Error in Docker

When you run php artisan migrate inside your PHP container, it attempts to connect to the MySQL server using the host specified in your .env file (in your case, DB_HOST=127.0.0.1). The error "Connection refused" means that the operating system successfully found an address on that IP (127.0.0.1), but there was no service actively listening on that port (3306) to accept the connection request.

In a standard Docker Compose setup, containers are isolated environments. They do not share the host machine's localhost by default in the way you might expect when running commands inside them. A container must communicate with another container using the service name defined in the docker-compose.yml file as the hostname, leveraging Docker’s internal networking bridge.

Analyzing Your Configuration: The Networking Mismatch

Let's look closely at the configuration you provided to pinpoint the exact discrepancy:

Your .env File Snippet:

DB_HOST=127.0.0.1
DB_PORT=3306
# ... other variables

Your MySQL Service in docker-compose.yml:
The service is named db. Docker Compose automatically sets up a network where containers can resolve each other using their service names.

When the PHP container tries to connect to 127.0.0.1:3306, it is attempting to connect to a MySQL server running inside the PHP container itself, not the separate db container. This connection fails because the intended MySQL database is listening on the network bridge, not on the PHP container's loopback interface.

The Solution: Using Service Names for Host Addressing

The correct way for containers within the same Docker Compose network to communicate is by using the service name defined in the docker-compose.yml file as the hostname. Since your MySQL service is named db, the PHP container must address it as db.

Step 1: Correcting the .env File

You need to change the DB_HOST to use the service name (db) instead of a host IP address that refers to the container itself (127.0.0.1).

Corrected .env File:

DB_CONNECTION=mysql
DB_HOST=db          # <-- CHANGE THIS: Use the service name defined in docker-compose.yml
DB_PORT=3306
DB_DATABASE=fhblog
DB_USERNAME=fhblog
DB_PASSWORD=root

Step 2: Ensuring Proper Network Setup

For this to work seamlessly, ensure that both your PHP application service and your MySQL service are part of the same network. Your provided snippet suggests you are using a custom network (app-network), which is good practice. Ensure your docker-compose.yml explicitly links all services to this shared network.

Here is how a typical working setup looks:

version: '3.8'

services:
  db:
    image: mysql:5.7.22
    container_name: mysql
    restart: unless-stopped
    environment:
      MYSQL_ROOT_USER: root
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: fhblog
      MYSQL_USER: fhblog
      MYSQL_PASSWORD: root
    ports:
      - "3306:3306"
    volumes:
      - ./docker/mysql/db:/var/lib/mysql
      - ./docker/mysql/my.cnf:/etc/mysql/my.cnf
    networks:
      - app-network # <-- Connect to the shared network

  app:
    build: .
    container_name: laravel_app
    depends_on:
      - db # Ensures MySQL starts before the application tries to connect
    environment:
      # These environment variables should align with your .env file pointing to 'db'
      DB_CONNECTION: mysql
      DB_HOST: db 
      DB_PORT: 3306
      DB_DATABASE: fhblog
      DB_USERNAME: fhblog
      DB_PASSWORD: root
    volumes:
      - .:/var/www/html

networks:
  app-network:
    driver: bridge

Conclusion

The "Connection refused" error in a Dockerized Laravel setup is almost always solved by understanding container networking. Stop relying on 127.0.0.1 when connecting services across containers. Instead, adopt the principle of service discovery: use the service name defined in your docker-compose.yml (e.g., db) as the hostname for database connections within your application's environment variables. This approach ensures that your Laravel application correctly interacts with the MySQL server running in its isolated container, adhering to best practices for container orchestration shown by platforms like those supported by Laravel Company. Happy coding!