Simple Approach using Docker with Laravel, Nginx, and MySQL Server.
I take a very simplistic approach to using Docker, and I want to share with you how we can too — without a bunch of overwhelming cruft. We can build hand-crafted Docker setups without any third party tools that contain what we need and nothing more.
Docker has become a frequently used solution for deploying applications. How it simplifies running and deploying applications in ephemeral containers.
Docker Compose has most simplified the development process by allowing developers to define their infrastructure, including application services, networks, and volumes, in a single file at docker composer
.
In this article, we will build a web application using the Laravel framework, Nginx as the web server and MySQL as the database server, all inside Docker containers.
We will define the entire stack configuration in a docker-compose file, along with configuration files for PHP, MySQL, and Nginx.
So Let’s start
1st Step:-Downloading and Installing Laravel with dependency
In 1st step, we will get the latest Laravel Project and install the dependencies for the project, including Composer, the application-level package manager for PHP.
We will install these dependencies with Docker to avoid having to install Composer globally.
1st we go to our working directory then clone the laravel project as laravel-docker
`.
For example you can make directory in desktop or root directory or any here you want.
But my case I make directory in root .
git clone https://github.com/laravel/laravel.git laravel-docker
Move into the directory laravel-docker
cd laravel-docker
Next we install composer globally and our project using this command
docker run --rm -v $(pwd):/app composer install
In here we using the -v
and - -rm
flags with docker run to creates an ephemeral container that will be bind-mounted to our current directory before being removed. It’s will copy the contents of ~/laravel-docker
directory to the container and also ensure that the vendor folder Composer creates inside the container is copied to our current or working directory.
2nd step:-Create Docker compose file
Building our applications with Docker Compose simplifies the process of setting up and versioning our infrastructure. To set up our Laravel application, we will write a docker-compose file that defines our web server, database, and application services which configuration initialise and write code docker composer.
Open our favourite terminal and run the command to create docker-compose.yml
sudo vim ~/laravel-docker/docker-compose.yml
This command make new file `docker-composer.yml` in our working directory and save with exit.
In this Docker composer file we are initialling our Different service. In our application we use three service these are `app`, `webserver`,`database server`.This 3 service initialising with other configuration in `docker-composer.yml`.
In docker-compose
file, define a volume called lbdata
under the db
service definition to persist the MySQL database:
#MySQL Servicedb: volumes:
- lbdata:/var/lib/mysql networks:
- app-network
The volume lbdata
persists the contents of the /var/lib/mysql
directory present inside the container. It allows to stop and restart the db
service without losing data.
At the bottom of the file(docker-composer.yml), add the definition for the lbdata
volume:
#Volumes volumes:
lbdata:
driver: local
Now we are able to use the volume anywhere across the application.
Now add the db service mysql configuration in docker-composer.yml
#MySQL Servicedb:
volumes:
- lbdata:/var/lib/mysql
- ./mysql/my.cnf:/etc/mysql/my.cnf
Finally, add the following bind mounts to the app
service for the application code and configuration files:
#PHP Serviceapp:
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini networks:
- app-network
Finally, Docker Composer file look like and copy and paste bellow code in `docker-compose.yml`
version: '1.1'
services:#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: php_service
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
volumes:
- ./:/var/www
- ./php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- app-network#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "88:80"
- "443:443"
volumes:
- ./:/var/www
- ./nginx/conf.d/:/etc/nginx/conf.d/
networks:
- app-network#MySQL Service
db:
image: mysql:5.7.22
container_name: db
restart: unless-stopped
tty: true
ports:
- "1306:3306"
environment:
MYSQL_DATABASE: laravel
MYSQL_ROOT_PASSWORD: root
SERVICE_TAGS: dev
SERVICE_NAME: mysql
volumes:
- lbdata:/var/lib/mysql/
- ./mysql/my.cnf:/etc/mysql/my.cnf
networks:
- app-network#Docker Networks
networks:
app-network:
driver: bridge
#Volumes
volumes:
lbdata:
driver: local
3rd step:-Creating Docker file
Docker allows us to specify the environment inside of individual containers with a Dockerfile. Dockerfile enables to create custom images that we can use to install software required by our application and configure settings based on our requirements.
Now we create Docker file in our working directory
Sudo vim ~/laravel-docker/Dockerfile
In Dockerfile we will set the base image and specify necessary command and instruction to build the Laravel application.
Copy the code and paste in Dockerfile
FROM php:7.2-fpm# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/# Set working directory
WORKDIR /var/www# Install dependencies
RUN apt-get update && apt-get install -y \
build-essential \
mysql-client \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
unzip \
git \
curl# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*# Install extensions
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-png-dir=/usr/include/
RUN docker-php-ext-install gd# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www# Copy existing application directory contents
COPY . /var/www# Copy existing application directory permissions
COPY --chown=www:www . /var/www# Change current user to www
USER www# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
Dockerfile creates an image on top of the php:7.2-fpm
Docker image. It’s Debian-based image that has the PHP FastCGI implementation PHP-FPM installed.
It’s also installs the prerequisite packages for Laravel: mcrypt
, pdo_mysql
, mbstring
, and imagick
with composer
. It’s not mandatory.If anyone wants can avoided this part in docker.
The RUN
directive specifies the commands to update, install, and configure settings inside the existing container.
The WORKDIR
instruction specifies the /var/www
directory as the working directory for the application.
We have created the www user, who has read/write access to the /var/www
directory
Finally, the EXPOSE
command exposes a port in the container, 9000
, for the php-fpm
server.
CMD
specifies the command that should run once the container is created. Here, CMD
specifies "php-fpm"
, which will start the server.
4th step:-php Configuration
In this step we configuration in php infrastructure.
As purpose to create `local.ini` to over write the actual php.ini for basic changes.
So Create the php
directory:
mkdir ~/laravel-docker/php
Then, open the local.ini
file and paste the code
upload_max_filesize=40M
post_max_size=40M
max_execution_time = 180
memory_limit = 3000M
In many cases, the values you enter should get larger as you go down the list from lines one to three. The upload_max_filesize
should be the smallest while memory_limit
should be the largest. The median should be post_max_size
.That why we change the php configuration.
5th step:-nginx Configuring
With the PHP service configured, we can modify the Nginx service to use PHP-FPM as the FastCGI server to serve dynamic content. The FastCGI server is based on a binary protocol for interfacing interactive programs with a web server.
[What is FASTCGI?
FastCGI is a binary protocol for interfacing interactive programs with a web server. It is a variation on the earlier Common Gateway Interface (CGI). FastCGI’s main aim is to reduce the overhead related to interfacing between web server and CGI programs, allowing a server to handle more web page requests per unit of time.
For more information about FastCGI please visit https://en.wikipedia.org/wiki/FastCGI
]
To configure nginx, We will create an app.conf
file with the service configuration in the
So create the nginx/conf.d/
directory bellow the command
mkdir -p ~/laravel-app/nginx/conf.d
Then Create `app.conf` configuration file bellow the command
sudo vim ~/laravel-app/nginx/conf.d/app.conf
Now we add the following code to the file to specify our Nginx configuration:
server {listen 80;index index.php index.html;error_log /var/log/nginx/error.log;access_log /var/log/nginx/access.log;root /var/www/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;}}
reference:
http://nginx.org/en/docs/beginners_guide.html
6th Step:-MySql Configuration
Configure MySQL, We will make the my.cnf
file in the mysql
folder. This is the file that we bind-mounted to /etc/mysql/my.cnf
inside the container. This bind mount allows us to override the my.cnf
settings as and when required.
For Example, how it’s works, we’ll add settings to the my.cnf
file that we enable the general query log and specify the log file.
my.cnfgeneral_log = 1
general_log_file = /var/lib/mysql/general.log
7th step: — Containers Runs with Modifying Environment Settings
In before we have configured all service in docker-compose file and created all related service. So now, we will run the Container before run the container we will make copy file .env and make changes
cp .env.example .env
So Now we run Docker Container bellow the command
docker-compose up –d
when we run the command if the command is first time run that’s time its downloaded all images form docker hub into our local machine. We need to wait sometimes. The -d
flag demonises the process, running containers in background.
If we want see our running docker Container run the command
docker ps
Output:
After that we can modify our env file on the app
container to include specific details about our setup
So, Open the file using docker-compose exec
, which allows to run specific commands in containers. To modify the env using the command
docker-compose exec app sudo vim .env
And modify the necessary information. In my case I changes bellow blocks
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=roor
DB_PASSWORD=root
In your case you change only DB_DATABASE, DB_USERNAME, DB_PASSWORD.
Next, set the application key for the Laravel application with the
php artisan key:generate
command. This command will generate a key and copy it to.env
file, ensuring that user sessions and encrypted data remain secure.
Run the command output:
We have the environment settings required to run our application. To cache these settings into a file, which will boost your application’s load speed, run:
docker-compose exec app php artisan config:cache
Configuration settings will be loaded into /var/www/bootstrap/cache/config.php
on the container.
So, Finally visit http://localhost:88/ in the. We will see the page welcome page in laravel. But my case I have some modified laravel welcome page That we can see different page
we run laravel application using Docker. Now we move to mysql database connection and try to implement default auth using migration.
Let’s start.
Step 8 :— MySQL Container Access by command
To accesses MySql, execute an interactive bash shell on the db
container with docker-compose exec
command
docker-compose exec db bash
Output
We successfully login our MySql Conatiner
In login terminal run the command to login mysql database accesses.
mysql -u root –p
In this part asked authorization, the output look like
Just enter the mysql root password. By the way default password is `root`.So we type root after that we can see screen like this.
Output
Run the show databases
command to check for existing databases:
Output
Also we can run other command use <database_name>
the command changes database and show tables
it’s show list table in your database.
9th step:- Laravel Data Migrating and make auth
First, we need to test database connection to mysql by running the laravel. To check database connection we run the command
docker-compose exec app php artisan migrate
The command will migrated the default laravel table and the output will be
Output
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_000000_create_users_table
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated: 2014_10_12_100000_create_password_resets_table
After that we will make default auth in laravel. To make default auth we run the command
docker-compose exec app php artisan make:auth
Output
Finally we visit the http://localhost:88/ in browser we can see the home page like
Some Important command
[N:B Some important command of laravel in specific container. When we change in .env or other configuration that time some operation not working properly. If not working that we can run some laravel command
## Project Build Informatin-docker-compose up --build[new build see the loger in console]
-docker-compose up -d [Only run the docker server like mysql, nginx and other but service run background]-docker ps [check all running container]
-docker images [check all images in you local docker server]## Database magration using docker*docker-compose exec [name of container] <your laravel command>*
-docker-compose exec app php artisan cache:clear
-docker-compose exec app php artisan view:clear
-docker-compose exec app php artisan route:clear
-docker-compose exec app php artisan clear-compiled
-docker-compose exec app php artisan config:cache]