Dockerizing Laravel with Nginx MySQL and Docker Compose on Ubuntu 18.04 LTS
This tutorial exists for these OS versions
- Ubuntu 22.04 (Jammy Jellyfish)
- Ubuntu 18.04 (Bionic Beaver)
On this page
Laravel is a free and open source PHP framework that implements the MVC (Model-View-Controller) design pattern. It's designed with ease of use and allows developers to create both simple and complex applications within no time. Laravel was created by Taylor Otwell in 2011, as an attempt to provide an advanced alternative to the CodeIgniter (CI) framework. In 2011, Laravel released version 1 and version 2, and the latest version 5.6 comes with more and improved features like Command-Line (CLI) support named 'artisan', support for different database systems, Route improvements, etc.
In this guide, we're going to show you how to Dockerize the Laravel project with PHP-FPM, MySQL database, and the Nginx web server using the Docker Compose on the Ubuntu Server 18.04. We're going to create a new docker image for the Laravel Project, and then create the docker-compose.yml script that contains some services including, the App/Laravel itself, Nginx web server, and MySQL database.
Prerequisites
- Ubuntu 18.04
- Root privileges
What we will do:
- Install Docker and Docker Compose
- Download Laravel and Install Dependencies
- Dockerizing the Laravel Project
- Define Laravel App Service
- Define Nginx HTTP Service
- Define MySQL Database Service
- Create Nginx Virtual Host for Laravel
- Create Dockerfile for Laravel App
- Build the Laravel Project
- Laravel Post-Installation
Step 1 - Install Docker and Docker Compose
Firstly, we're going to install Docker and Docker Compose packages to the Ubuntu system. And we will be using Docker packages from the Official Ubuntu repository.
Before going any further, we need to update repositories on the Ubuntu system. Simply by running the following command.
sudo apt update
Now install Docker and Docker Compose packages using the apt command below.
sudo apt install docker.io -y
sudo apt install docker-compose -y
The Docker and Docker Compose packages should now installed on the system, check it using the following commands.
docker version
docker-compose version
As a result, you will get the version of Docker and Docker Compose on the system.
Next, we need to assign the non-root user to the docker group in order to run the Docker container for non-root users.
For this case, we're going to add the user called 'hakase' to the docker group by running the following command.
usermod -a -G docker hakase
And after that, log in to the 'hakase' user shell and run the docker 'hello-world' command.
su - hakase
docker run hello-world
Now you will be displayed the 'Hello World' message from Docker, and the Docker installation has been completed.
Step 2 - Download Laravel and Install Dependencies
In this step, we're going to download Laravel web-framework to the 'hakase' home directory and then install Laravel dependencies using the PHP 'composer' docker image. So, ensure that you're logged in to the server as a non-root user.
Download Laravel project to the 'myapp' directory and go into it.
git clone https://github.com/laravel/laravel.git myapp/
cd myapp/
Now run the following docker command in order to install Laravel dependencies.
docker run --rm -v $(pwd):/app composer install
With the command above, we're going to run a new temporary docker container and mount the 'myapp' project directory to the '/app' directory on the container. The container based on the 'composer' docker image, and we're installing Laravel dependencies using the 'composer' command inside that temporary container.
Once the Laravel dependencies installation is finished, we must change the owner of 'myapp' directory to our own user using sudo command below.
sudo chown -R $USER:$USER ~/myapp
Step 3 - Dockerizing the Laravel Project
After downloading the Laravel and installing its dependencies, we're going to create a new docker-compose.yml script and create a new Dockerfile for the Laravel project.
cd myapp/
vim docker-compose.yml
- Define the Laravel App Service
Firstly, we're going to define the Laravel project itself and build the docker image for the Laravel project using the Dockerfile.
Paste the docker compose script into it.
version: '3'
services:
#Laravel App
app:
build:
context: .
dockerfile: Dockerfile
image: hakase-labs/laravel
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www/html
volumes:
- ./:/var/www/html
networks:
- mynet
Details of the Laravel container service:
- The Laravel container service will be named as 'app'. It's based on our custom docker image that will be created with our 'Dockerfile', and the new image will be named as 'hakase-labs/laravel'.
- We want to mount the 'myapp' project directory to the '/var/www/html' inside the container service.
- We're using the custom docker network for our setup, the network will be named as 'mynet'.
- Define Nginx HTTP Service
Now we will define the nginx container service.
Paste the following configuration after the 'app' container service line.
#Nginx Service
nginx:
image: nginx:alpine
container_name: nginx
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www/html
- ./nginx/conf.d/:/etc/nginx/conf.d/
- ./nginx/ssl/:/etc/nginx/ssl/
networks:
- mynet
Configuration details of the nginx container service:
- We want to create a new container named 'nginx' based on the docker image 'nginx:alpine'.
- The container service will open the HTTP and HTTPS ports.
- The container will mount three different volumes. The 'myapp' project directory to the '/var/www/html' directory, the nginx virtual host configuration 'nginx/conf.d/' to the '/etc/nginx/conf.d' directory, and mount certificate files 'nginx/ssl/' to the '/etc/nginx/ssl' directory on the container.
- The container service will be using the same network called 'mynet'.
- Define MySQL Database Service
And the last, we define the MySQL database service.
Paste the following configuration after the 'nginx' container service line.
#MySQL Service
db:
image: mysql:5.7
container_name: db
restart: unless-stopped
tty: true
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laraveldb
MYSQL_USER: laravel
MYSQL_PASSWORD: laravelpassworddb
MYSQL_ROOT_PASSWORD: rootpasswordmysql
volumes:
- mysqldata:/var/lib/mysql/
networks:
- mynet
#Docker Networks
networks:
mynet:
driver: bridge
#Volumes
volumes:
mysqldata:
driver: local
Save and close the configuration.
Details MySQL container service:
- The MySQL container service will be named as 'db', based on the 'mysql:5.7' docker image.
- The 'db' service will open the default MySQL port '3306'.
- The Laravel project will be using the database, user, and the password based on the environment variable of the 'db' service.
- The MySQL 'db' service will mount the volume named 'mysqldata', and have the same network 'mynet'.
- And we define the custom network 'mynet' with the 'bridge' driver, and the 'mysqldata' volume will be using the 'local' driver.
Below is the completed 'docker-compose.yml' configuration:
version: '3' services: #Laravel App app: build: context: . dockerfile: Dockerfile image: hakase-labs/laravel container_name: app restart: unless-stopped tty: true environment: SERVICE_NAME: app SERVICE_TAGS: dev working_dir: /var/www/html volumes: - ./:/var/www/html networks: - mynet #Nginx Service nginx: image: nginx:alpine container_name: nginx restart: unless-stopped tty: true ports: - "80:80" - "443:443" volumes: - ./:/var/www/html - ./nginx/conf.d/:/etc/nginx/conf.d/ - ./nginx/ssl/:/etc/nginx/ssl/ networks: - mynet #MySQL Service db: image: mysql:5.7 container_name: db restart: unless-stopped tty: true ports: - "3306:3306" environment: MYSQL_DATABASE: laraveldb MYSQL_USER: laravel MYSQL_PASSWORD: laravelpassworddb MYSQL_ROOT_PASSWORD: rootpasswordmysql volumes: - mysqldata:/var/lib/mysql/ networks: - mynet #Docker Networks networks: mynet: driver: bridge #Volumes volumes: mysqldata: driver: local
- Create Nginx Virtual Host for Laravel
Within the 'myapp' project directory, create a new directory named 'nginx' that will contain two other directories 'conf.d' and 'ssl'. Then create a new nginx virtual host configuration 'laravel.conf' inside the 'conf.d' directory.
Run the following command.
mkdir -p nginx/{conf.d,ssl}
vim nginx/conf.d/laravel.conf
server { listen 80; server_name laravel.hakase-labs.io; return 301 https://laravel.hakase-labs.io$request_uri; } server { listen 443 ssl http2; server_name laravel.hakase-labs.io; ssl_certificate /etc/nginx/ssl/fullchain.pem; ssl_certificate_key /etc/nginx/ssl/privkey.pem; # Log files for Debug error_log /var/log/nginx/error.log; access_log /var/log/nginx/access.log; # Laravel web root directory root /var/www/html/public; index index.php index.html; location / { try_files $uri $uri/ /index.php?$query_string; gzip_static on; } # Nginx Pass requests to PHP-FPM 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; } }
Save and close.
After that, copy your ssl certificate file to the 'nginx/ssl/' directory.
sudo cp /path/to/ssl/fullchain.pem nginx/ssl/
sudo cp /path/to/ssl/privkey.pem nginx/ssl/
- Create Dockerfile for the Laravel App
Next, create a new Dockerfile for the Laravel project.
Run the following command.
vim Dockerfile
Paste configuration below.
# Set master image FROM php:7.2-fpm-alpine # Copy composer.lock and composer.json COPY composer.lock composer.json /var/www/html/ # Set working directory WORKDIR /var/www/html # Install Additional dependencies RUN apk update && apk add --no-cache \ build-base shadow vim curl \ php7 \ php7-fpm \ php7-common \ php7-pdo \ php7-pdo_mysql \ php7-mysqli \ php7-mcrypt \ php7-mbstring \ php7-xml \ php7-openssl \ php7-json \ php7-phar \ php7-zip \ php7-gd \ php7-dom \ php7-session \ php7-zlib # Add and Enable PHP-PDO Extenstions RUN docker-php-ext-install pdo pdo_mysql RUN docker-php-ext-enable pdo_mysql # Install PHP Composer RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer # Remove Cache RUN rm -rf /var/cache/apk/* # Add UID '1000' to www-data RUN usermod -u 1000 www-data # Copy existing application directory permissions COPY --chown=www-data:www-data . /var/www/html # Change current user to www USER www-data # Expose port 9000 and start php-fpm server EXPOSE 9000 CMD ["php-fpm"]
Save and close the configuration.
And we're ready to build the 'myapp' Laravel project and run container services that we've defined.
Step 4 - Build Laravel with Nginx and MySQL Services
Build the custom docker image for our Laravel project using the following command.
docker-compose build
Then run again the following command.
docker-compose up -d
It will download all docker images as we need and then build container services based on the 'docker-compose.yml' configuration.
When it's complete, verify using the docker-compose command below.
docker-compose ps
And as a result, you will get the three container services are up and running. The 'app' that is running on default port '9000' PHP-FPM, the service 'nginx' is on the HTTP and HTTPS ports, and the MySQL 'db' service on the default MySQL port '3306'.
After that, verify again all available docker image and the open ports on the system.
docker-compose images
netstat -plntu
You will get the custom docker image 'hakase-labs/laravel' on the list, and the HTTP and HTTPS port are on the 'LISTEN' state.
Step 5 - Laravel Post-Installation
Until this stage, the Laravel project is up and running as a Docker container. And now we're going to create a new '.env' file, generate the key and migrate the Laravel data using the Laravel command line 'artisan'.
Copy the example of '.env' file and edit it inside the container.
cp .env.example .env
docker-compose exec app vim .env
Change the database configuration as below.
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laraveldb
DB_USERNAME=laravel
DB_PASSWORD=laravelpassworddb
Save and close.
Next, generate the Laravel application key and clear the cache configuration.
docker-compose exec app php artisan key:generate
docker-compose exec app php artisan config:cache
After that, migrate the database using the following command.
docker-compose exec app php artisan migrate
Ensure there is no error.
Now open your web browser and type the domain name of your project.
http://laravel.hakase-labs.io/
And you will be redirected to the secure HTTPS connection and will be displayed the default Laravel home page as below.
Finally, the Dockerizing of Laravel project with Nginx web server and MySQL database has been completed successfully.