Laravel Development Environment with Docker and Docker Compose: A Step-by-Step Tutorial
Murilo livorato dos santos
Posted on January 29, 2024
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
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
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 .
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;
}
}
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
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 .
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
• 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
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
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
The extructure will be like this
Step 3 — Run those Containers
docker-compose up -d
Step 4— Create Laravel Project and Set Database
docker-compose run --rm composer create-project laravel/laravel .
Access PHP My Admin
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
DB_host with must be the same name of the configuration in dockerfile
Clear the config cache
docker-compose run --rm artisan config:cache
Migrate Database
docker-compose run --rm artisan migrate
Step 5 — Access the Project
Access the url — localhost:8080
The url with the same name of the configuration server in dockerfile -
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
Posted on January 29, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.