Docker is an software program which is used for operating system level virtualization. It is also called containerization. PHP applications are mostly composed by a web server, language interpreter and a DBMS (Database) In this tutorial we will be using a complete PHP stack using docker. We will orchestrate containers for Nginx (the web-server), MySQL ( database system) and PHP language itself.
For this tutorial we will create a simple application that takes a list of cities from the database and displays it on the web page. This will help in the understanding and demonstrating the complete working.
Prerequisites
- Docker CE Installed
- Minimal working knowledge of docker
- Knowledge about containerization
Step 1: Configuring the work environment
A basic docker based application is composed of multiple containers. It is difficult to manage all these manually. To solve this problem we use docker-compose, it helps manage multiple containers using a configuration file.
Use the following commands to install docker-compose
$ curl -L https://github.com/docker/compose/releases/download/1.19.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose
We will create a folder to save all the files here. Then cd into it and it will be used as our working directory.
$ mkdir ~/docker $ cd ~/docker
Create more folder using this command
$ mkdir php nginx app
In php folder we will have our custom php image, ngnix will have custom ngix image and the app folder will have source code and configuration files.
Step 2: Configure the PHP container
We will use php-fpm to connect to Nginx webserver. Inside the php folder create a file named Dockerfile and put the following contents into it.
FROM php:7.1-fpm-alpine3.4 RUN apk update--no-cache && apk add--no-cache $PHPIZE_DEPS && apk add--no-cache mysql-dev && docker-php-ext-install pdo pdo_mysql
We are using the Alpine version here. Alpine is a small distribution which targets the containers.
$ docker build -t name-php php/
As mentioned above about the docker-compose yml configuration file, lets create the file
$ touch app/docker-compose.yml
Put the following configurations into the file
version: '2' services: php: image: vultr-php volumes: -./:/app working_dir: /app
Version is the version of docker-compose.yml used here. Note that every service has a specific key inside the services block. The name specified here will be used to reference this specific container later. We also define a volume mapping.
volumes: - ./:/app
This tells docker-compose to map the current directory (./) to the /app directory inside the container. The last line will make sure that the commands will be executed from this folder i.e ./app
Orchestrate the containers using following commands
$ cd ~/docker/app $ docker-compose up -d
To check that the php container executed. Use the following command:
$ docker ps
Step 3: Executing Commands inside the container
Use the following docker-compose command, make sure you are still inside the app folder.
$ docker-compose exec [service] [command]
The service placeholder refers to service key.
Run the following command in the docker-compose to check php version.
$ docker-compose exec php php -v
You will see the following message:
PHP 7.1.14 (cli) (built: Feb 7 2018 00:40:45) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.1.0, Copyright (c) 1998-2018 Zend Technologies
Step 4: Configuring the Nginx container
Like before we will create a custom image for Nginx. Use the following commands to do it.
$ cd ~/docker $ touch nginx/Dockerfile
Put the following configurations into the Dockerfile
FROM nginx:1.13.8-alpine COPY ./default.conf /etc/nginx/conf.d/default.conf
On this Docker file we simply copy a configuration file into our application setup.
$ touch nginx/default.conf
Now add the following configurations to the file
server { listen80 default_server; listen [::]:80 default_server ipv6only=on; root /app; index index.php; #server_name server_domain_or_IP; location / { try_files$uri$uri/ /index.php?$query_string; } location~ .php$ { try_files$uri /index.php =404; fastcgi_split_path_info ^(.+.php)(/.+)$; fastcgi_pass php:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }
Internally docker-compose creates a network and assigns the service name as the host name to each of the services defined. Build the Nginx image.
$ docker build -t name-nginx nginx/
Now docker-compose.yml file with following configurations:
version: '2' services: php: image: vultr-php volumes: -./:/app working_dir: /app web: image: vultr-nginx volumes: -./:/app depends_on: -php ports: -80:80
Create a file called index.php using the following command
$ <?php phpinfo();
Before running these commands below make sure that port 80 is up and working
$ cd ~/docker/app $ docker-compose up -d
Step 5: Configuration the MySQL container
Update the file ~/docker/app/docker-compose.yml using the following configurations
version: '2' services: php: image: name-php volumes: -./:/app working_dir: /app web: image: name-nginx volumes: -./:/app depends_on: -php ports: -80:80 mysql: image: mysql:5.7.21 volumes: -./:/app - dbdata:/var/lib/mysql environment: -MYSQL_DATABASE=world -MYSQL_ROOT_PASSWORD=root working_dir: /app volumes: dbdata:
Now lets download the sample MySQL database using the following command inside the app folder
$ curl -L http://downloads.mysql.com/docs/world.sql.gz -o world.sql.gz $ gunzip world.sql.gz
Now orchestrate the container using the following command
$ docker-compose up -d
Now populate the world database
$ docker-compose exec -T mysql mysql -uroot -proot world < world.sql
Now let’s check that the data has successfully populated in the database. For that access the MySQL prompt in the container. Use the following command.
$ docker-compose exec mysql mysql -uroot -proot world
Inside the prompt, run the following query
select * from city limit10;
A list of data inside the database, in this case cities will be shown. Quit the prompt using following command.
mysql> exit
Step 6: Build PHP application
The containers are running, now lets create the PHP application. Go to the app/index.php file, and paste the following code in it.
<?php $pdo = new PDO('mysql:host=mysql;dbname=world;charset=utf8', 'root', 'root'); $stmt = $pdo->prepare(" select city.Name, city.District, country.Name as Country, city.Population from city left join country on city.CountryCode = country.Code order by Population desc limit 10 "); $stmt->execute(); $cities = $stmt->fetchAll(PDO::FETCH_ASSOC); ?> <!doctype html> <html> <head> <meta charset="UTF-8"> <title>Vultr Rocks!</title> </head> <body> <h2>Most Populous Cities In The World</h2> <table> <thead> <tr> <th>Name</th> <th>Country</th> <th>District</th> <th>Population</th> </tr> </thead> <tbody> <?phpforeach($cities as $city): ?> <tr> <td><?=$city['Name']?></td> <td><?=$city['Country']?></td> <td><?=$city['District']?></td> <td><?=number_format($city['Population'], 0)?></td> </tr> <?phpendforeach?> </tbody> </table> </body> </html>
Now if you access the IP address in your browser, you will see the list of cities that are most popular. Congratulations you have successfully deployed a PHP application using docker.
Check out these top 3 Cloud hosting services:
- Want info about best web hosting? Clicking this link can be of great help.