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:
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