A docker based setup for testing with Laravel

I experienced some annoying issues while running integration tests in a Laravel app. The official MySQL docker image will create a user and a database for you which is very convenient, but that user does not have permission to create new databases. I configure my applications to use a separate database for testing, usually with a _testing suffix and so just hit a brick wall.

The solution was to mount an entrypoint script, basically, some SQL statements I want to execute when the container is created. The script will create all of the necessary databases I need.

The file: config/create-databases.sql

CREATE DATABASE IF NOT EXISTS app DEFAULT CHARACTER SET = utf8;
CREATE DATABASE IF NOT EXISTS app_testing DEFAULT CHARACTER SET = utf8;
GRANT ALL PRIVILEGES ON app.* TO 'admin'@'%';
GRANT ALL PRIVILEGES ON app_testing.* TO 'admin'@'%';
FLUSH PRIVILEGES;

My docker-compose.yml

services:
    db:
        image: mysql/mysql-server:8.0.28
        environment:
            MYSQL_ROOT_PASSWORD: root
            MYSQL_DATABASE: app
            MYSQL_USER: admin
            MYSQL_PASSWORD: password
        cap_add:
            - SYS_NICE
        ports:
            - "127.0.0.1:3306:3306"
        volumes:
            - db:/var/lib/mysql
            - ./config/create-databases.sql:/docker-entrypoint-initdb.d/create-databases.sql
volumes:
    db:

Then into .env.testing I set DB_DATABASE=app_testing and now I can setup the test database and execute tests.

APP_ENV=testing php artisan migrate
php artisan test

Success!