How To Dockerize Laravel Application

In this tutorial, we are going to dockerize a sample Laravel application using Docker-compose, Nginx-PHP and MySQL on the ubuntu server.

What are docker and docker-compose?

Docker blogs Visit our docker blogs section to get more understanding of docker containers.

What is Laravel?

Laravel is a free and open-source PHP web framework, Laravel is based on the Model-View-Controller (MVC) architectural pattern and utilizes a templating engine called Blade. It also supports a variety of databases, including MySQL, PostgreSQL, and SQLite.
When you’re finished, you’ll have a demo Laravel application running on three separate service containers:

An app service running PHP-fpm 8.0.t item
A DB service which is running MySQL.List item
An Nginx service will server PHP code using the app service from the Laravel application.

Prerequisites:

Must have a ubuntu server with docker and docker-compose installed if you still didn’t have installed both kindly follow our previous blogs

How to install docker in ubuntu 20.04

How to install and configure docker-compose on ubuntu 20.04

I will show you how to make a Laravel 8. x application work locally using Docker. Here we are creating 3 containers an app container in which one website files reside one MySQL database container one container to run the Nginx webserver.

Step 1: Install docker and docker-compose

You need to install both docker and docker-compose on your machine.

Step 2: Create a laravel dockerfile

Create a docker-compose file in the root directory of your project. Using vi editor
Here we are defining 3 services on the docker-compose file one for our application, one for our database and one for web server Nginx.

vi docker-compose.yaml

version: "3.8"
services:
  app:
    container_name: app
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    expose:
      - 9000
    volumes:
      - .:/usr/src/app
      - ./public:/usr/src/app/public
    depends_on:
      - db
    networks:
      - app_network

  blog_nginx:
    container_name: nginx_webserver
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    volumes:
    - ./public:/usr/src/app/public
    ports:
      - 8000:80
    depends_on:
      - app
    environment:
      NGINX_FPM_HOST: app
      NGINX_ROOT: /usr/src/app/public
    networks:
      - app_network

  db:
    container_name: db
    image: mysql:8.0.20
    restart: always
    volumes:
      - ./storage/db-data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: Data
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: root123
      MYSQL_PASSWORD: root123
    networks:
      - app_network

networks:
  app_network:
    driver: bridge

Now Let us define each of the services separately
1:The app service

First, we are defining the app service which holds our Laravel application files.

blog:
    container_name: app
    build:
      context: .
      dockerfile: ./docker/php/Dockerfile
    expose:
      - 9000
    volumes:
      - .:/usr/src/app
      - ./public:/usr/src/app/public
    depends_on:
      - blog_db
    networks:
      - app_network

The app service is built using the image created from the docker file which we are going to create.
All the website files are copied to the location /usr/src/app inside the container also the /public folder is copied to /usr/src/app/public inside the container.
We are exposing port 9000 and defining a network for our container to run inside. This service is dependent on our database service so it will start after our DB container starts.

Now we are going to create the docker file which is mentioned above using this docker file we are going to build our app service image and run it as a container. You must be inside the website root directory ie the directory which holds the website files.

mkdir -p docker/php && vi docker/php/Dockerfile

FROM php:8.0-fpm

# Install dockerize so we can wait for containers to be ready
ENV DOCKERIZE_VERSION 0.6.1

RUN curl -s -f -L -o /tmp/dockerize.tar.gz https://github.com/jwilder/dockerize/releases/download/v$DOCKERIZE_VERSION/dockerize-linux-amd64-v$DOCKERIZE_VERSION.tar.gz \
    && tar -C /usr/local/bin -xzvf /tmp/dockerize.tar.gz \
    && rm /tmp/dockerize.tar.gz

# Install Composer
ENV COMPOSER_VERSION 2.1.5

RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer --version=$COMPOSER_VERSION

# Install nodejs
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        libz-dev \
        libpq-dev \
        libjpeg-dev \
        libpng-dev \
        libssl-dev \
        libzip-dev \
        unzip \
        zip \
        nodejs \
    && apt-get clean \
    && pecl install redis \
    && docker-php-ext-configure gd \
    && docker-php-ext-configure zip \
    && docker-php-ext-install \
        gd \
        exif \
        opcache \
        pdo_mysql \
        pdo_pgsql \
        pgsql \
        pcntl \
        zip \
    && docker-php-ext-enable redis \
    && rm -rf /var/lib/apt/lists/*;

COPY ./docker/php/laravel.ini /usr/local/etc/php/conf.d/laravel.ini

WORKDIR /usr/src/app
RUN Chmod -R 777 /usr/src/app/public
RUN chown -R www-data:www-data .

In this docker file, we are installing PHP and the necessary dependencies for our laravel project to run. PHP-FPM, COMPOSER,

Create a laravel.ini file inside the folder

vi docker/php/laravel.ini

date.timezone=UTC
display_errors=Off
log_errors=On

memory_limit=256M
upload_max_filesize=20M
post_max_size=20M
max_execution_time=600
default_socket_timeout=3600
request_terminate_timeout=600

This configuration file will be copied to the PHP conf directory so that we can use our customized PHP values for our project.

Now our app service configurations are completed let’s move on to the next service defined

2:Service Nginx web server
blog_nginx:
    container_name: nginx_webserver
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    volumes:
    - ./public:/usr/src/app/public
    ports:
      - 8000:80
    depends_on:
      - app
    environment:
      NGINX_FPM_HOST: app
      NGINX_ROOT: /usr/src/app/public
    networks:
      - app_network

Here we are creating a docker file in the /docker/nginx/ directory which is used to create the custom Nginx image.
Opening port 8000 to map with the container port 80 in which Nginx runs on default.
This service is dependent on our app service so it only starts when our app container gets started.

Create a docker file in the Nginx directory and add the following code.

mkdir -p docker/nginx && vi docker/nginx/Dockerfile

FROM nginx:latest

ENV NGINX_ROOT /usr/src/app/public
ENV NGINX_FPM_HOST localhost
ENV NGINX_FPM_PORT 9000

RUN rm -f /etc/nginx/conf.d/default.conf

COPY ./docker/nginx/nginx.conf /etc/nginx/conf.d

EXPOSE 80

ENTRYPOINT ["entrypoint.sh"]

Here we are pulling the latest Nginx image from docker-hub and passing the environment variables required for our project and also removing the default.conf file and copy a virtual host conf file which is created below to the /etc/nginx/conf,d directory and create our own image.

Vi docker/nginx/nginx.conf


server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /usr/src/app/public;
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
}

Create a .env file for your project

cp .env.example .env
vi .env

Modify the following values similar to those shown below

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=Data
DB_USERNAME=root123
DB_PASSWORD=root123

3:The Database service

The next service defined is for the database to run. Here we are using the MySQL image from the docker hub and also mapping the folder storage to /var/lib/mysql inside the container.
The port defined is the default port for the database and also the database credentials are defined here.

  db:
    container_name: db
    image: mysql:8.0.20
    restart: always
    volumes:
      - ./storage/db-data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: Data
      MYSQL_ROOT_PASSWORD: root
      MYSQL_USER: root123
      MYSQL_PASSWORD: root123
    networks:
      - app_network

Now we are going to deploy the laravel application for that we are using docker-compose.

docker-compose up -d

Wait until the process completes and after that, you will be able to see the container runnings as shown below.

We have created our laravel docker image and deployed it as a container in our host.

Now you can see that 3 of our containers are running now exec into the app container using the command.

docker exec -ti app /bin/bash

verify that you are on the /usr/src/app directory and Install all composer packages included in composer.json

composer install

Install all npm packages included in package.json

npm install

Run all the mix tasks

npm run dev

Create a .env file from the existing .env.example

cp .env.example .env

Generate a Laravel App Key.

php artisan key:generate

Modify the following fields in your .env file to use the values specified in the database container.

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=Data
DB_USERNAME=root123
DB_PASSWORD=root123

Change the permission of the public folder.

chmod -R 777 public/

Run the database migrations after using the below command.

php artisan migrate

Now all the configurations are completed now you can access the application using port 8000 check the installation is successful using a browser you will be able to see the default laravel page

You can clone our git hub repo in order to get the complete configuration files for learning purposes.

https://github.com/Linuxlearninghub/Laravel_demo_project.

Summary:

In this blog, we have learned how to dockerize Laravel applications.In a very easy way

Leave a Reply

Your email address will not be published. Required fields are marked *