Use docker-compose to create a dev environment for Laravel 6, 7 and 8

Apr 29, 2024 by Thibault Debatty | 779 views

Laravel Docker PHP

https://cylab.be/blog/336/use-docker-compose-to-create-a-dev-environment-for-laravel-6-7-and-8

Setting up a Laravel environment requires to install and configure multiple components: the correct PHP version, of course, but also a database, node server, probably queue worker and scheduler. To get you quickly started, here is how to deploy a dev environment for Laravel with docker compose.

containers.jpg

Foreword

For this blog post, we assume your project is using Laravel 7, 8 or 9.

Docker compose

The first step consists in creating a file docker-compose.yaml with the following content.

In this file we create 7 containers:

  • web will run the web application with apache
  • queue will run a queue worker
  • scheduler will run scheduled commands
  • node will run the npm server
  • mailhog will allow us to check emails sent by the application
  • mysql and redis run the corresponding databases

Also, the containers will run as the current user user: "${UID}:${GID}" so we avoid file permission problems...

#
# docker-compose.yaml
#
# to create a development environment with docker-compose
# https://cylab.be/blog/336/use-docker-compose-to-create-a-dev-environment-for-laravel
#

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.dev
    # defined in .env
    user: "${UID}:${GID}"
    depends_on:
      - redis
      - mysql
    ports:
      - 8080:80
    volumes:
      - .:/var/www/html
    env_file: .env
    environment:
      WAIT_HOSTS: mysql:3306
      APACHE_RUN_USER: "#${UID}"
      APACHE_RUN_GROUP: "#${GID}"

  queue:
    build:
      context: .
      dockerfile: Dockerfile.dev
    # defined in .env
    user: "${UID}:${GID}"
    depends_on:
      - web
    volumes:
      - .:/var/www/html
    command: ["/queue.sh"]
    env_file: .env
    environment:
      WAIT_HOSTS: web:80

  scheduler:
    build:
      context: .
      dockerfile: Dockerfile.dev
    # defined in .env
    user: "${UID}:${GID}"
    depends_on:
      - web
    volumes:
      - .:/var/www/html
    command: ["/scheduler.sh"]
    env_file: .env
    environment:
      WAIT_HOSTS: web:80

  node:
    image: node:16.15.0-alpine
    # defined in .env
    user: "${UID}:${GID}"
    working_dir: /app
    volumes:
      - .:/app
    entrypoint: /bin/sh -c "npm install && npm run watch-poll"

  redis:
    image: redis:4-alpine
    volumes:
      - ./volumes/redis:/data

  mysql:
    image: mysql:5.7
    volumes:
      - ./volumes/mysql:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: laravel

  mailhog:
    image: mailhog/mailhog
    ports:
      - 1025:1025
      - 8025:8025

Env file

As you may have noticed, the containers will use the environment file .env, so this is where we must define appropriate configuration directives, including the UID and GID of the current user (you).

You can find these with id -u and id -g respectively.

As usual, the .env file should not be committed in your repository, but you should instead create an example env.dev

#
# .env
#
# to create a development environment with docker-compose
# https://cylab.be/blog/336/use-docker-compose-to-create-a-dev-environment-for-laravel
#
#

# UID and GID for running containers
# see docker-compose.yaml
# you can find these with 
# id -u
UID=1000

# and
# id -g
GID=1000

APP_NAME=App
APP_ENV=dev
APP_KEY=base64:ezEe4jH/6EUM2fMWLnco3kuMz1OMStq/XfV456ZwMhc=
APP_DEBUG=true
APP_URL=http://localhost:8080

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=root

BROADCAST_DRIVER=log
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

# MailHog
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null

Dockerfile

Also, the web, queue and scheduler images are built using the 'recipe' in Dockerfile.dev. The trick here is to start from the image cylab/laravel-dev:7.4 that already has a lot of preinstalled tools (composer) and PHP modules. But you can also add your own tools if needed:

#
# Dockerfile.dev
#
# used to build the development containers
# see docker-compose.yml
# https://cylab.be/blog/336/use-docker-compose-to-create-a-dev-environment-for-laravel-6-7-and-8
#

FROM cylab/laravel-dev:7.4

# If you modifify this file, don't forget to
# docker compose up --build

# Add your dependencies. For example:

# Install php-imagick
#RUN apt-get update && apt-get install -y libmagickwand-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
#RUN printf "\n" | pecl install imagick
#RUN docker-php-ext-enable imagick

# Install PHP GD
#RUN apt-get update && apt-get install -y  libfreetype6-dev libmcrypt-dev libpng-dev libjpeg-dev libpng-dev --no-install-recommends && rm -rf /var/lib/apt/lists/*
#RUN docker-php-ext-configure gd --with-jpeg --with-freetype
#RUN docker-php-ext-install -j$(nproc) gd

You can find the base Docker file of cylab/laravel-dev at https://gitlab.cylab.be/cylab/docker/laravel-dev

Usage

You are now ready to deploy your dev stack:

docker compose up

After a few seconds, your web application will be available at http://127.0.0.1:8080

docker.png

Also, the stack will deploy mailhog at http://127.0.0.1:8025 You can use it to check the emails sent by your application.

mailhog.png

Finally, you can run any artisan (or other) command in the web container with

docker compose exec web <command>

Here are a few examples to give you ideas

docker compose exec web php artisan migrate
docker compose exec web php artisan make:model Post
docker compose exec web vendor/bin/phpunit

Happy coding!

This blog post is licensed under CC BY-SA 4.0