Wednesday, 16 November 2016

Laravel Application with Docker

Build Laravel application with docker

METHOD 3
In the previous post i already have discussed about building  hello world php application with docker .
Now in this tutorial i will build  Laravel Application using docker-compose.yml file.

According to official docs
The Compose file is a YAML file defining services, networks and volumes. The default path for a Compose file is ./docker-compose.yml.

We will create two services in docker-compose.yml file. Each service contain some definition in docker-compose.yml file.
  1. web
  2. mysql

A service definition contains configuration which will be applied to each container started for that service, much like passing command-line parameters to docker run. Likewise, network and volume definitions are analogous to docker network create and docker volume create.


Difference Between Dockerfile And docker-compose file

Dockerfile is used only to build the image and install all software dependency and packages where as docker-compose.yml file is used to configure the image like mounting the volume from the localhost, mapping the ports etc.

One Dockerfile involves in building only one image where as One docker-compose.yml file 
is involved in configuring the multiple images.

Why docker-compose.yml file?

docker-compose.yml file simplifies the configuration of multiple images in one single file.
docker-compose is a tool which is used to run this docker-compose.yml file and make a configured docker containers from it. We can run our Whole application with the single command  of docker-compose tool which is very awesome.
The main objective of docker compose tool is to manage the multiple container app on the single Node. This tool is not used to scale our multiple container app on different node for that we have docker swarm .


Overview about this laravel project


I have developed an application which provide api for the members/students. We can hit the api and get response as a  list of members/student in json format. All the records will be stored on mysql database.this project is uploaded to the github  
link


This web application will only expose two api
  1. /api/v1/getAllMember
  2. /api/v1/getMemberById/{id}

First api will return all member in json format stored in members table
Second api will return a particular member detail in json format

For the sake of simplicity i only have worked with these files only

Controller used :  MemberController.php
Model Used :     Member.php
Migration class:   2016_11_01_135853_create_member_table.php
Environment file  .env
Explore these class to have better understanding about project




If u explore the .env file u will find mysql configuration as follow
DB_CONNECTION=mysql  
DB_HOST=mysql_laravel  //container name where mysql will be running
DB_PORT=3306  // default port
DB_DATABASE=laravel_db //this is the database name automatically created when we run docker-compose.yml file
DB_USERNAME=root
DB_PASSWORD=hrhk

I will explain about this configuration later in this post but for now that’s all about laravel project



Root Directory of Project

In the root directory of project there is two main file for making containers of this laravel application

  1. Dockerfile.txt
  2. docker-compose.yml

Dockerfile.tx

Dockerfile.txt
FROM nimmis/apache-php5
MAINTAINER Syed Moinuddin Shibli

We already have built a hello world php app using Dockerfile.txt in method 1. Please refer for detail


Docker-compose.yml

docker-compose.yml
web:
build: .
container_name: laravel_container
volumes:
 - .:/var/www/html/app
ports:
   - "80:80"
links:
 - mysql
mysql:
image: mysql:latest
container_name: mysql_laravel
ports:
- "3306:3306"
environment:
   MYSQL_ROOT_PASSWORD: hrhk
   MYSQL_DATABASE: laravel_db



Note:
There are two versions of the Compose file format – version 1 (the legacy format, which does not support volumes or networks) and version 2 (the most up-to-date). For more information, see the Versioning section.



I will try to explain each and every line of docker-compose.ym file

Line 1)
Web: Microservice you can name it whatever you want

Line 2)
build: . This will tell docker engine to build an image from dockerfile located in current directory

Line 3)
container_name: laravel_container Providing the custom name to docker container

Line 4)
Volumes: this directive is used for mounting the host files to container

Line 5)
 - .:/var/www/html/app mount every thing of current directory into /var/www/html/app

Line 6)
Ports: this directive is used to map a host machine port with docker container port

Line 7)
   - "80:80" on port 80 of localhost our docker container is running which mapped with port 80
inside the  docker container where our apache is running

Line 8)
Links: this directive is used to create a link between microservice

Line 9)
- mysql here i am linking my web microservice with mysql micro service

Line 10)
mysql:  this is micro service for mysql database

Line 11)
image: mysql:latest Using official mysql image to build mysql container

Line 12)
container_name: mysql_laravel providing custom name for the mysql container
This is the same name which i have configured in the the .env file  as
DB_HOST=mysql_laravel. This database will be automatically created in mysql.you do not have to manually create it.


Note
You must have to set in .env file for mysql host container setting as localhost will not work in our case i have setted it up as DB_HOST=mysql_laravel


Line 13)
Ports: configuring the port

Line 14)
- "3306:3306" localhostport:mysqlport running inside the mysql container

Line 15)
Environment:   setting up the environment variable for the mysql

Line 16)
   MYSQL_ROOT_PASSWORD: hrhk

Line 17)
   MYSQL_DATABASE: laravel_db



Now everything is configured it’s time to run over application

Open terminal and clone the project anywhere you want. I am cloning it to var directory


cd /var




cd laravel-docker-app


sudo docker-compose up -d

Note:
  1. docker-compose is a tool not shipped with docker. We have install it manually google it
  2. Make sure u have stopped apache2 and mysql if they are running on the host machine
         sudo service apache2 stop
         sudo service mysql stop

If no error occurred then successfully two docker container was deployed. We can check by following command


sudo docker ps


CONTAINER ID         IMAGE         COMMAND      CREATED             STATUS             PORTS              NAMES

1de243a968a2   laraveldockerapp_web   "/my_init"    7 seconds ago   Up 5 seconds        0.0.0.0:80->80/tcp       laravel_container

6edcb67281ba   mysql:latest   "docker-entrypoint.sh"  8 seconds ago  Up 7 seconds  0.0.0.0:3306->3306/tcp   mysql_laravel


Two container are running

1)laravel_container
2)mysql_laravel : mysql database is running inside this container


We will insert 250 records in our database table using laravel default faker


You can assume each container as a separate virtual operating system which is using host linux kernel .

Now we will enter inside the container and will run some php artisan command

sudo docker exec -it laravel_container bash

Note:
We can also use container id instead of name to enter into container


Inside the container just move to the directory where we have mounted our code. See docker-compose file volume configuration section
cd /var/www/html/app


Gives permission to storage

chmod -R 777 storage


We still haven’t created our database table we can migrate our migration class for respective database tables. Run the following command.

php artisan migrate


Output will be as follow
**************************************
*     Application In Production!     *
**************************************

Do you really wish to run this command? (yes/no) [no]:
> y

Migration table created successfully.
Migrated: 2014_10_12_000000_create_users_table
Migrated: 2014_10_12_100000_create_password_resets_table
Migrated: 2016_11_01_135853_create_member_table






Now We will use command line tool known as tinker  to insert fake records in database table.
php artisan tinker


Here we are using factory method to generate 250  fake records  into mysql table. See app/database/ModelFactory to know how to factory model class works
$members=factory(App\Member::class,250)->create();

After inserting the 250 fake record into database table from tinker type “exit” without quotes to exit from the php artisan tinker
exit



We have configured everything for laravel application in  our laravel container and mysql container. These two container are up and  running but still our application in laravel_container is not running.

For local environment we may simply use artisan server to run our application
For Production environment we must use fully featured server like apache and nginx


We will use both server one by one to run our laravel application

First we will see how to run laravel application with artisan server

In docker-compose.yml file web microservice will be run on port 80 inside the container which is mapped with port 80 of localhost. But on port 80 in the laravel container  apache server is running by default . so we must have to stop it first then we will run artisan server on port 80.

Run the following command from inside the laravel container. It will stop apache server running inside the laravel container.
sudo service apache2 stop

Run the following command from inside the laravel container
php artisan serve --port 80 --host 0.0.0.0

Note:
Make sure you run following command in /var/www/html/app


Now we have successfully hosted our laravel docker application  using artisan web server on the localhost.
check the following URL URL 1) localhost/api/v1/getAllMember
URL 2) localhost/api/v1/getMemberById/10


Warning This artisan web server was designed to aid application development. It may also be useful for testing purposes or for application demonstrations that are run in controlled environments. It is not intended to be a full-featured web server. It should not be used on a public network.
The web server runs a only one single-threaded process, so PHP applications will stall if a request is blocked.


if we want to run our laravel application in laravel container by apache in our local host.
For that we need to configure apache configuration file and map the root directory to /var/www/html/app/public.


Scaling our laravel application

what if our application become successful  and  grown to  such an extent that it have millions of users interaction per day ,  then definitely our app will not be able to handle the request these heavy request may cause our application to crash.
we can easy handle such situation with docker by horizontally scaling our application.
Click here to see the next post in which i have described about Scaling the web application.






















No comments:

Post a Comment