Search code examples
phplaraveldocker

SQLSTATE[HY000] [2002] Connection refused web | web | web | In PDOConnection.php line 27: web | web | SQLSTATE[HY000] [2002] Connection refused


I am trying to build a laravel application using docker compose and I keep getting this error. I have tried to change the DB_HOST variable in env file from local host to 127.0.0.1 vice versa but it still doesn't work. I have also tried php artisan config:clear and php:artisan cache:clear multiple times. I have also checked that the server is running but for some reason, it keeps showing connection refused.

docker-compose.yml

services:
  web:
    image: app-name:latest
    build:
      target: web
      context: .
    env_file:
      - .env
    ports:
      - "8000:80"
    volumes:
      - .:/var/www/html
    depends_on:
      - db
  
  db:
    platform: "linux/amd64"
    image: mysql:5.7
    env_file:
      - .env
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
    ports:
      - "3307:3306"
    volumes:
      - dbdata:/var/lib/mysql

volumes:
  dbdata:

.env

APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:XQqm38kup8DjQipdfv18IZavsGd0Rvv0fSvkpe+x0HM=
APP_DEBUG=true
APP_URL=http://localhost:8000

APP_LOCALE=en
APP_FALLBACK_LOCALE=en
APP_FAKER_LOCALE=en_US

APP_MAINTENANCE_DRIVER=file
# APP_MAINTENANCE_STORE=database

PHP_CLI_SERVER_WORKERS=4

BCRYPT_ROUNDS=12

LOG_CHANNEL=stack
LOG_STACK=single
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_PORT=3307
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=secret
DB_HOST=db

SESSION_DRIVER=database
SESSION_LIFETIME=120
SESSION_ENCRYPT=false
SESSION_PATH=/
SESSION_DOMAIN=null

BROADCAST_CONNECTION=log
FILESYSTEM_DISK=local
QUEUE_CONNECTION=database

CACHE_STORE=database
# CACHE_PREFIX=

MEMCACHED_HOST=127.0.0.1

REDIS_CLIENT=phpredis
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=log
MAIL_SCHEME=null
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false

VITE_APP_NAME="${APP_NAME}"

Dockerfile

# Use PHP with Apache as the base image
FROM php:8.2-apache as web

# Install Additional System Dependencies
RUN apt-get update && apt-get install -y \
    libzip-dev \
    zip

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*

# Enable Apache mod_rewrite for URL rewriting
RUN a2enmod rewrite

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql zip

# Configure Apache DocumentRoot to point to Laravel's public directory
# and update Apache configuration files
ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# Copy the application code
COPY . /var/www/html

# Set the working directory
WORKDIR /var/www/html

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

# Install project dependencies
RUN composer install

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

Solution

  • you would need to modify both your docker-compose.yml and .env with the following:

    1. docker-compose.yml → Add netowkrs.
    networks: # add this
      backend:
        name: "mybackend"
    
    services:
      web:
        image: app-name:latest
        build:
          target: web
          context: .
        env_file:
          - .env
        ports:
          - "8000:80"
        volumes:
          - .:/var/www/html
        depends_on:
          - db
        networks: # add this
          - "backend"
      
      db:
        platform: "linux/amd64"
        image: mysql:5.7
        env_file:
          - .env
        environment:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: laravel
          MYSQL_USER: laravel
          MYSQL_PASSWORD: secret
        ports:
          - "3307:3306"
        volumes:
          - dbdata:/var/lib/mysql
        networks: # add this
          - "backend"
    
    volumes:
      dbdata:
    
    1. .env → fix your DB_PORT number.
    DB_CONNECTION=mysql
    DB_HOST=db
    DB_PORT=3306
    DB_DATABASE=laravel
    DB_USERNAME=laravel
    DB_PASSWORD=secret
    

    Explanation:

    In your db services, the ports is defined as 3307:3306 and you've written 3307 at the .env file. Since the laravel app is running in your web service, the connection between web and db would be through the docker network.

    3307 is for your host machine to connect, while 3306 is used within the docker network.

    For the networks portion, I add it just to be sure that these containers are in the same network.

    Hope this helps.

    Regards,