Не получается подключиться к базе при выполнении тестов на Laravel

Использую docker со следующим docker-compose файлом

services:
    database:
        container_name: database
        image: mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: a_library
            MYSQL_USER: laravel
            MYSQL_PASSWORD: laravel
        ports:
            - '4306:3306'
        volumes:
            - ./.docker/database/mysql:/var/lib/mysql

    test_database:
        container_name: test_database
        image: mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: test
            MYSQL_USER: laravel
            MYSQL_PASSWORD: laravel
        ports:
            - '8011:8001'
        volumes:
            - ./.docker/database/test_mysql:/var/lib/mysql

phpunit.xml вообще не трогал.

<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
         bootstrap="vendor/autoload.php"
         colors="true"
>
    <testsuites>
        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>
    </testsuites>
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">./app</directory>
        </include>
    </coverage>
    <php>
        <server name="APP_ENV" value="testing"/>
        <server name="BCRYPT_ROUNDS" value="4"/>
        <server name="CACHE_DRIVER" value="array"/>
        <!-- <server name="DB_CONNECTION" value="sqlite"/> -->
        <!-- <server name="DB_DATABASE" value=":memory:"/> -->
        <server name="MAIL_MAILER" value="array"/>
        <server name="QUEUE_CONNECTION" value="sync"/>
        <server name="SESSION_DRIVER" value="array"/>
        <server name="TELESCOPE_ENABLED" value="false"/>
    </php>
</phpunit>

Так же есть следующий .env.testing:

APP_NAME=Laravel
APP_ENV=testing
APP_DEBUG=true
APP_URL=http://localhost

LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug

DB_CONNECTION=mysql
DB_HOST=test_database
DB_PORT=8011
DB_DATABASE=test
DB_USERNAME=laravel
DB_PASSWORD=laravel

BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DRIVER=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120

MEMCACHED_HOST=127.0.0.1

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=null
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

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

Пробовал разные конфигурации, но постоянно выдает одну и туже ошибку:

SQLSTATE[HY000] [2002] Connection refused (SQL: SHOW FULL TABLES WHERE table_type = 'BASE TABLE')

Не могу понять, где я ошибся. Пробовал разные конфигурации, настраивал по разному config/database.php, но все одно.

Причем если подебажить подключение в папке vendor, то вроде все ровно выглядит

Illuminate\Database\Connection->__construct(Closure Object (), test, , Array (
  [driver] => mysql,
  [host] => test_database,
  [port] => 8011,
  [database] => test,
  [username] => laravel,
  [password] => laravel,
  [unix_socket] => ,
  [charset] => utf8mb4,
  [collation] => utf8mb4_unicode_ci,
  [prefix] => ,
  [prefix_indexes] => 1,
  [strict] => 1,
  [engine] => ,
  [options] => Array (),
  [name] => mysql
))

Если попробовать зайти в контейнер через docker exec -it, то все ок.

Да и с контейнерами все ок. docker ps




Благодаря добрым людям тут удалось решить эту проблему. docker-compose.yml теперь выглядит следующим образом:

version: '3.8'

services:
    database:
        container_name: dev_database
        image: mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: library
            MYSQL_USER: user
            MYSQL_PASSWORD: password
        volumes:
            - ./.docker/database/test_mysql:/var/lib/mysql

    test_database:
        container_name: test_database
        image: mysql:8.0
        command: --default-authentication-plugin=mysql_native_password
        environment:
            MYSQL_ROOT_PASSWORD: secret
            MYSQL_DATABASE: test
            MYSQL_USER: test
            MYSQL_PASSWORD: test
        volumes:
            - ./.docker/database/test_mysql:/var/lib/test_mysql

    php:
        container_name: dev_php
        build:
            context: ./.docker/php
        ports:
            - '9000:9000'
        volumes:
            - ./:/var/www/laravel-docker
            - ./.docker/php/conf.d/xdebug.ini:/usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
            - ./.docker/php/conf.d/error_reporting.ini:/usr/local/etc/php/conf.d/error_reporting.ini
        environment:
            PHP_IDE_CONFIG: "serverName=Docker"
        depends_on:
            - dev_database
            - test_database

    nginx:
        container_name: dev_nginx
        image: nginx:stable-alpine
        ports:
            - '8080:80'
        volumes:
            - ./:/var/www/laravel-docker
            - ./.docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - php
            - test_database
            - database

Спасибо большое!


Ответы (1 шт):

Автор решения: Aleksey Vaganov

Я не вижу чтобы в контейнер test_database прокидывался какой-то кастомный конфиг. При этом дефолтный для mysql порт 3306.

Т.к. база данных и остальные контейнеры у вас в одной сети, то для подключения к БД используйте имя сервиса test_database и порт 3306.

Если не планируете открывать порты БД во вне, то прокидывать порты - '4306:3306' не нужно.

→ Ссылка