Laravel Development Environment with Docker and Docker Compose: A Step-by-Step Tutorial

murilolivorato

Murilo livorato dos santos

Posted on January 29, 2024

Laravel Development Environment with Docker and Docker Compose: A Step-by-Step Tutorial

Image description

Laravel, the PHP web application framework, and Docker, the containerization platform, are a match made in heaven for developers seeking scalability, efficiency, and ease of deployment. In this extensive guide, we’ll delve deep into the integration of Laravel with Docker, exploring the intricacies of setting up a robust environment and establishing seamless communication between two Laravel projects.

Here’s a list of the services we’ll be creating in our Docker environment —

  • PHP — 8.2-fpm-alpine
  • Nginx — nginx:stable-alpine
  • MySQL — mysql:8.0.1
  • Mailhog
  • PhpMyAdmin

Step 1 — Download & Install Docker

Prerequisites:
Before you begin, ensure that your system meets the following requirements:
• A compatible operating system (Linux, macOS, or Windows)
• Administrative privileges (for installation)
• Internet connection to download Docker

Download Docker:
Visit the official Docker website to download the Docker Desktop application. Navigate to https://www.docker.com/get-started and click on the “Download for [Your OS]” button.

Install Docker:
Once the download is complete, follow these steps for your specific operating system:

For Windows:
• Run the installer you downloaded.
• Follow the on-screen instructions to install Docker Desktop.
• During installation, you may be asked to enable Hyper-V. Allow this to ensure proper functioning of Docker containers on Windows.

For macOS:
• Open the downloaded .dmg file.
• Drag the Docker icon to the Applications folder.
• Open Docker from the Applications folder and follow any additional prompts to complete the installation.

For Linux:
• Refer to the Docker documentation for instructions tailored to your Linux distribution: https://docs.docker.com/install/

Verify Installation:

After the installation is complete, verify that Docker is running correctly:
• Open a terminal or command prompt.
• Type the following command and press Enter:

```Docker --version




This should display the installed Docker version, confirming a successful installation.
• To ensure Docker is running, enter:



```Docker run hello-world
Enter fullscreen mode Exit fullscreen mode

Docker run hello-world
If everything is set up correctly, you will see a message indicating that your Docker installation is working.

Step 2 — Setting Up Laravel Projects in Docker File

Docker Compose Configuration

Start by creating a Dockerfile in the root directory of your Laravel project. This file will contain instructions for building a Docker image.

Configure the Nginx Server in DockerFile

services:
  server:
    build:
      context: .
      dockerfile: dockerfiles/nginx.dockerfile
    ports:
      - 8080:80
    volumes:
      - ./src:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
      - redis
      - mysql
      - mailhog
    container_name: laravel_enviroment_server
    networks:
      - laravel_enviroment
Enter fullscreen mode Exit fullscreen mode

These settings do the following:

build: This configuration tells Docker Compose to build a local image for the app service, using the specified path (context) and Dockerfile for instructions. The arguments user and uid are injected into the Dockerfile to customize user creation commands at build time.

image: The name that will be used for the image being built..

ports: Defines a port redirection that will allow external access through port 8000 to the web server running on port 80, inside the container.

volumes: Creates a shared volume that will synchronize contents from the current directory to /var/www/html inside the container. Notice that this is not your document root, since that will live in the nginx container.

networks: Sets up this service to use a networkname mysql_laravel_enviroment.

These settings do the following:

• build: This configuration tells Docker Compose to build a local image for the app service, using the specified path (context) and Dockerfile for instructions. The arguments user and uid are injected into the Dockerfile to customize user creation commands at build time.

• image: The name that will be used for the image being built..

• ports: Defines a port redirection that will allow external access through port 8000 to the web server running on port 80, inside the container.

• volumes: Creates a shared volume that will synchronize contents from the current directory to /var/www/html inside the container. Notice that this is not your document root, since that will live in the nginx container.

• networks: Sets up this service to use a networkname mysql_laravel_enviroment.

Setting /nginx/default.conf

FROM nginx:stable-alpine

 WORKDIR /etc/nginx/conf.d

 COPY nginx/default.conf .

 RUN mv default.conf default.conf

 WORKDIR /var/www/html

 COPY src .
Enter fullscreen mode Exit fullscreen mode

Setting nginx.conf

server {
    listen 80;
    index index.php index.html;
    server_name localhost;
    root /var/www/html/public;
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}
Enter fullscreen mode Exit fullscreen mode

These settings do the following:

• listen: This directive defines the port on which the server will listen to incoming requests.
• root: This directive sets the root folder path, forming the complete path to any requested file on the local file system.

Setting PHP

php:
    build:
      context: .
      dockerfile: dockerfiles/php.dockerfile
    volumes:
      - ./src:/var/www/html:delegated
    container_name: php_laravel_enviroment
    networks:
      - laravel_enviroment
Enter fullscreen mode Exit fullscreen mode

Setting php.dockerfile

FROM php:8.2-fpm-alpine

WORKDIR /var/www/html

COPY src .
# Instalando extensões necessárias do PHP
RUN apk add --no-cache mysql-client msmtp perl wget procps shadow libzip libpng libjpeg-turbo libwebp freetype icu

RUN apk add --no-cache --virtual build-essentials \
    icu-dev icu-libs zlib-dev g++ make automake autoconf libzip-dev \
    libpng-dev libwebp-dev libjpeg-turbo-dev freetype-dev && \
    docker-php-ext-configure gd --enable-gd --with-freetype --with-jpeg --with-webp && \
    docker-php-ext-install gd && \
    docker-php-ext-install mysqli && \
    docker-php-ext-install pdo_mysql && \
    docker-php-ext-install intl && \
    docker-php-ext-install bcmath && \
    docker-php-ext-install opcache && \
    docker-php-ext-install exif && \
    docker-php-ext-install zip && \
    apk del build-essentials && rm -rf /usr/src/php*

RUN apk add --no-cache pcre-dev $PHPIZE_DEPS \
        && pecl install redis \
        && docker-php-ext-enable redis.so

RUN addgroup -g 1000 laravel && adduser -G laravel -g laravel -s /bin/sh -D laravel

RUN chown -R laravel /var/www/html

USER laravel
first the Dockerfile creates an image on top of the php:8.2-fpm-alpine .
Enter fullscreen mode Exit fullscreen mode

The file also installs the prerequisite packages for Laravel: pdo_mysql, mbstring, mcrypt , gd, mysqli , and imagick with composer.

The RUN directive specifies the commands to update, install, and configure settings inside the container, including creating a dedicated user and group called www/html .

The WORKDIR instruction specifies the /var/www/html directory as the working directory for the application.

Creating a dedicated user and group called laravel , with restricted permissions mitigates the inherent vulnerability when running Docker containers, which run by default as root.

Setting Mysql

mysql:
    image: mysql:8.0.1
    restart: unless-stopped
    tty: true
    container_name: mysql_laravel_enviroment
    env_file:
      - mysql/.env
    ports:
      - 3306:3306
    networks:
      - laravel_enviroment
    volumes:
      - /opt/mysql_data:/var/lib/mysql
Enter fullscreen mode Exit fullscreen mode

• Defines the Docker image that should be used for this container. In this case, we’re using a MySQL 8.0.1 image from Docker Hub.

• container_name: Sets up the container name for this service: travellist-db.
• restart: Always restart this service, unless it is explicitly stopped.

volumes: Creates a volume to share a .sql database dump that will be used to initialize the application database. The MySQL image will automatically import .sql files placed in the /var/lib/mysq directory inside the container.
• networks: Sets up this service to use a networkname mysql_laravel_enviroment.
Setting Mysql .env

MYSQL_USER=homestead
MYSQL_PASSWORD=secret
MYSQL_ROOT_PASSWORD=secret
Enter fullscreen mode Exit fullscreen mode

MYSQL_DATABASE will be the database.
• MYSQL_USER will be the username you will use for your database. In this case, we will use .
• MYSQL_PASSWORD will be the secure password you would like to use for this user account.
• MYSQL_ROOT_PASSWORD will be the mysql root password .

Setting composer

composer:
    build:
      context: ./dockerfiles
      dockerfile: composer.dockerfile
    volumes:
      - ./src:/var/www/html
    depends_on:
      - php
    networks:
      - laravel_enviroment
Enter fullscreen mode Exit fullscreen mode

Setting All composer.dockerfile

FROM composer:latest

RUN addgroup -g 1000 laravel && adduser -G laravel -g laravel -s /bin/sh -D laravel

USER laravel

WORKDIR /var/www/html

ENTRYPOINT [ "composer", "--ignore-platform-reqs" ]



version: "3.9"

networks:
  laravel_enviroment:

services:
  server:
    build:
      context: .
      dockerfile: dockerfiles/nginx.dockerfile
    ports:
      - 8080:80
    volumes:
      - ./src:/var/www/html
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - php
      - redis
      - mysql
      - mailhog
    container_name: laravel_enviroment_server
    networks:
      - laravel_enviroment
  php:
    build:
      context: .
      dockerfile: dockerfiles/php.dockerfile
    volumes:
      - ./src:/var/www/html:delegated
    container_name: php_laravel_enviroment
    networks:
      - laravel_enviroment
  mysql:
    image: mysql:8.0.1
    restart: unless-stopped
    tty: true
    container_name: mysql_laravel_enviroment
    env_file:
      - mysql/.env
    ports:
      - 3306:3306
    networks:
      - laravel_enviroment
    volumes:
      - /opt/mysql_data:/var/lib/mysql
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    restart: always
    container_name: phpmyadmin_laravel_enviroment
    depends_on:
      - mysql
    ports:
      - '8891:80'
    environment:
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=secret
    networks:
      - laravel_enviroment
  redis:
    image: redis:alpine
    container_name: redis_laravel_enviroment
    restart: unless-stopped
    ports:
      - 6379:6379
    networks:
      - laravel_enviroment
    command: redis-server --appendonly yes --replica-read-only no

  composer:
    build:
      context: ./dockerfiles
      dockerfile: composer.dockerfile
    volumes:
      - ./src:/var/www/html
    depends_on:
      - php
    networks:
      - laravel_enviroment
  artisan:
    build:
      context: .
      dockerfile: dockerfiles/php.dockerfile
    volumes:
      - ./src:/var/www/html
    entrypoint: ["php", "/var/www/html/artisan"]
      #depends_on:
    #- mysql
    networks:
      - laravel_enviroment
  scheduler:
    build:
      context: .
      dockerfile: dockerfiles/php.dockerfile
    container_name: scheduler_laravel_enviroment
    volumes:
      - ./src:/var/www/html
    working_dir: /var/www/html
    entrypoint: [ "php", "artisan", "schedule:work" ]
    networks:
      - laravel_enviroment
  mailhog:
    image: mailhog/mailhog:latest
    container_name: mailhog_laravel_enviroment
    ports:
      - 1025:1025
      - 8025:8025
    networks:
      - laravel_enviroment
Enter fullscreen mode Exit fullscreen mode

The extructure will be like this

Image description

Step 3 — Run those Containers

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

Image description

Image description

Step 4— Create Laravel Project and Set Database

docker-compose run --rm composer create-project laravel/laravel .
Enter fullscreen mode Exit fullscreen mode

Access PHP My Admin

Image description
Image description

Access phpmyadmin and create the Db -laravel_db ( the same name that is on mysql.env — MYSQL_DATABASE=laravel_db )

Set Laravel .env

DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=root
DB_PASSWORD=secret

Enter fullscreen mode Exit fullscreen mode

DB_host with must be the same name of the configuration in dockerfile

Clear the config cache

docker-compose run --rm artisan config:cache

Enter fullscreen mode Exit fullscreen mode

Migrate Database

docker-compose run  --rm artisan migrate
Enter fullscreen mode Exit fullscreen mode

Image description

Step 5 — Access the Project

Access the url — localhost:8080
The url with the same name of the configuration server in dockerfile -

Image description

Image description

Conclusion:

Congratulations! You’ve successfully set up a Laravel development environment using Docker and Docker Compose. This approach ensures consistency across different development machines and simplifies the process of managing dependencies. As you continue developing your Laravel application, you can extend and customize this setup to suit your specific project requirements. Happy coding!

Git Hub Code -

https://github.com/murilolivorato/laravel_docker_enviroment

Thanks a lot for reading till end. Follow or contact me via:
Github:https://github.com/murilolivorato
LinkedIn: https://www.linkedin.com/in/murilo-livorato-80985a4a/
Youtube : https://www.youtube.com/@murilolivorato1489

💖 💪 🙅 🚩
murilolivorato
Murilo livorato dos santos

Posted on January 29, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related