Streamlining Containerization: Converting Laravel and MySQL Dockerfiles to a Unified docker-compose.yml Configuration

Let’s convert the Dockerfiles for both Laravel and MySQL into a docker-compose.yml file.

The docker-compose.yml file is a YAML-formatted configuration file used to define and run multi-container Docker applications. Let’s break down the various sections of the docker-compose.yml file and explain their purpose:

  1. Version:
    • The version key specifies the Docker Compose file format version. This indicates which features and syntax are supported in the file. The version number helps Docker Compose interpret the structure of the file correctly.
  2. Services:
    • The services key defines the individual services or containers that make up the application. Each service represents a containerized component of the application, such as a web server, database, cache, etc.
    • Under the services key, you define one or more services with their configurations, including the Docker image, environment variables, ports, volumes, networks, and other settings.
  3. Volumes:
    • The volumes key defines named volumes that can be used to persist data generated by containers. Volumes provide a way to store and share data between containers or between a container and the host machine.
    • In the docker-compose.yml file, volumes are defined using the volumes key followed by a list of named volumes. Each named volume corresponds to a directory or location on the host machine where data can be stored.
  4. Networks:
    • The networks key defines named networks that can be used to connect containers and facilitate communication between them.
    • Networks provide a way to isolate container communication and control network traffic between containers.
    • Similar to volumes, networks are defined using the networks key followed by a list of named networks.

Now, let’s examine the specific configurations within the services section of the docker-compose.yml file:

  • laravel Service:
    • build: Specifies the build context and Dockerfile for building the Docker image for the Laravel service.
    • ports: Maps container ports to host ports, allowing external access to the service. In this example, port 80 of the Laravel container is mapped to port 8000 on the host machine.
    • volumes: Mounts volumes to the container.
      • A volume was named laravel_html and mounted it to /var/www/html in the Laravel service. This ensures that the contents of the html directory in the Laravel container are persisted even after the container is stopped or removed.
      • Another volume was named laravel_storage and mounted it to /var/www/html/storage . This volume mount is typically used to persist Laravel application storage files, such as logs, cache, and session data.
    • networks: Specifies the network(s) the container should connect to. In this example, the Laravel container is connected to the laravel_network network.
  • mysql Service:
    • image: Specifies the Docker image to use for the MySQL service. In this example, the latest version of the MySQL image is pulled from the Docker Hub.
    • environment: Sets environment variables for configuring the MySQL container, such as the root password, database name, and user credentials.
    • ports: Maps container ports to host ports, allowing external access to the service. In this example, port 3306 of the MySQL container is mapped to port 3306 on the host machine.
    • volumes: Mounts volumes to the container. In this example, the mysql_data volume is mounted to /var/lib/mysql in the MySQL container to persist the database files.
    • networks: Specifies the network(s) the container should connect to. In this example, the MySQL container is also connected to the laravel_network network.

Overall, the docker-compose.yml file defines the configuration for running a multi-container application consisting of Laravel and MySQL services. It specifies how the containers are built, configured, connected to networks, and how data is persisted using volumes.

Here’s how you can do it:

docker-compose.yml

version: '3.8'

services:
  laravel:
    build:
      context: .
      dockerfile: Dockerfile.laravel
    ports:
      - "8000:80"
    volumes:
      - laravel_html:/var/www/html
      - laravel_storage:/var/www/html/storage
    networks:
      - laravel_network

  mysql:
    image: mysql:latest
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: laravel_db
      MYSQL_USER: laravel_user
      MYSQL_PASSWORD: laravel_password
    ports:
      - "3306:3306"
    volumes:
      - mysql_data:/var/lib/mysql
    networks:
      - laravel_network

volumes:
  laravel_html:
  laravel_storage:
  mysql_data:

networks:
  laravel_network:

In this docker-compose.yml file:

  • We define two services: laravel and mysql.
  • For the laravel service:
    • We use the build key to specify the context and Dockerfile (Dockerfile.laravel) for building the image.
    • Port mapping is defined to expose port 8000 on the host to port 80 in the container.
    • Two volumes are mounted to persist Laravel storage. laravel_storage:/var/www/html/storage and laravel_html:/var/www/html
    • The service is connected to the laravel_network network.
  • For the mysql service:
    • We use the image key to specify the MySQL image.
    • Environment variables are provided for MySQL configuration.
    • Port mapping is defined to expose port 3306 on the host to port 3306 in the container.
    • A volume is mounted to persist MySQL data.
    • The service is also connected to the laravel_network network.
  • Two volumes are defined: laravel_storage for Laravel storage and mysql_data for MySQL data.
  • A network named laravel_network is defined to connect the services.
A NOTE about mounting a second Laravel Volume:

The laravel_storage:/var/www/html/storage volume mount is typically used to persist Laravel application storage files, such as logs, cache, and session data. If your Laravel application doesn't generate or use any storage files, you might not need this volume.

However, it's a common practice to include this volume mount to ensure that any storage-related data generated by the Laravel application is persisted across container restarts or recreations. It helps maintain data consistency and ensures that your application behaves as expected, especially in production environments.

If you're certain that your Laravel application doesn't generate or use any storage files, you can omit this volume mount. Otherwise, it's recommended to include it to ensure proper functionality and data persistence for your Laravel application.

Dockerfile.laravel

# Use the official PHP image with Apache
FROM php:latest

# Update package lists and install dependencies
RUN apt-get update && \
    apt-get install -y libpng-dev libjpeg-dev libfreetype6-dev zip unzip && \
    docker-php-ext-configure gd --with-freetype --with-jpeg && \
    docker-php-ext-install gd pdo_mysql && \
    a2enmod rewrite

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Set working directory
WORKDIR /var/www/html

# Install the latest version of Laravel
RUN composer create-project --prefer-dist laravel/laravel .

# Set permissions
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

# Generate autoload files and cache
RUN composer dump-autoload && \
    php artisan cache:clear && \
    php artisan config:cache && \
    php artisan route:cache

# Expose port 80 to the outside world
EXPOSE 80

# Define a volume for Laravel storage
VOLUME /var/www/html/storage

Make sure to replace Dockerfile.laravel with the actual name of your Laravel Dockerfile.

Once you have the docker-compose.yml file ready, you can use the docker-compose up command to build and run the services defined in the file.