Setting up a development environment with Docker Compose

in #software7 years ago

In this article we look at how you can get started with Docker in order to set up a development environment for, for example, the development and deployment of a web application.
Then you can use the written yml file to quickly activate this environment on a Kinamo cloud server using the Docker Engine.

If you want more information on how to install Docker Engine on a Kinamo cloud server, be sure to read our article on CentOS 7 and Docker containers !

Container? Or virtual machine?
Docker uses "images" to start containers. An image contains a minimal linux environment and usually performs one specific function: a web server, database server ...

With Docker Engine you can run Docker "Containers".
A docker container is in many ways similar to a "ready-made" virtual machine: you can create, delete and modify files. However, there is a big - and not unimportant - difference: once you stop a docker container , the adjustments are lost .
With a virtual machine, after a "power off" you can simply restart with the last "state" of your modifications.
Where you start to install a virtual machine from an ISO, installation cd, ... you can easily use a docker image as a starting point for building a docker container.

Docker images are thus a kind of templates with which you can get started. On the basis of these images you can build a docker environment .
In order to ensure that the data in your database or the configuration of your web server is maintained, you must link volumes to your containers from the host .
There are official docker images for many software, frameworks or programming languages. All you have to do is add your own data or code to quickly start your project.

When you use multiple containers within a project, it is not always easy to get the entire docker driven environment working. The configuration of each individual container, the linking of volumes to your container, etc., becomes a cumbersome task.

To solve this problem, there is Docker Compose .
With Docker Compose you can define a multi-container application. With one command you can then start the necessary services and set up the whole environment!

In this article, we look at how you can easily build a work environment with Docker Compose.

Starting with Docker Compose
In this article we use Docker Compose to set up an environment with two docker containers: a web server with Apache and PHP and a database server with MySQL. This is a frequent recurring scenario and opens the door for numerous experiments with Wordpress, PHP frameworks etc. We use the official images of the Docker Hub for our installations .

The project below can be performed on Windows, Mac or Linux. The installation of Docker on Linux can be consulted here .
If you prefer Windows or Mac, Docker toolbox offers a solution.

The web server container
We start by setting up a container for the web server. As an image for the web server we use one of the official PHP images "php: 5.6-apache".
This is a handy choice because Apache is also installed in the image.

Unfortunately, not all php extensions have been installed that we need, with out-of-the-box images this can often happen. In order to be able to connect to the database soon, we need the mysqli extension. We can add these by building our own image based on the image from the Docker Hub . In other words, we use the image from the Docker Hub as the starting point for our own image.

As a first step, we create a folder in which we will place all files for the web server. We name the folder "php" because it is a php image.
In this folder we create a new file with the name "Dockerfile".

A "Docker file" is a text file containing the commands to build a Docker image. In the dockerfile for our php image we put the following:

FROM php:5.6-apache

RUN docker-php-ext-install mysqli
When FROMwe give to the image we want to use as a base.

With RUNwe perform a command that will ensure that the mysqli extension is installed. This command is a feature of the php base image, which makes it possible to activate more extensions in a simple way. Always read the documentation of the images that you wish to use, often with their own commands to extend the basic image.

For the test our web server we also create a PHP info page. Create a new folder in the 'php' folder with the name 'www'. In this folder we place all files that have to be offered by the web server.

Create a new file with the name index.phpand insert the following code:

<?php
phpinfo();
?>
Finally, we will create our new image and run the container. For this we use Docker Compose. 
Create a file with the name in the top folder of the project docker-compose.yml. This may include:

version: '2'

services:
  php:
    build: php
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./php/www:/var/www/html

On the first line we write the name for our container 'php'.

At build we write the name of the image that we are going to use. We wish to build a new image on the basis of our newly developed Docker file.
We write 'php' here. This is the folder containing the Docker file that must be used for the image.

Under 'ports' we place the mapping of the ports. For our web server we want to make ports 80 and 443 available. We connect the ports of the container to those of the host, for example "host port: container port". A concrete example: if the firewall allows traffic on port 80 for the cloud server, then the host port is "80" and you can map it in the docker container on, for example, port 80.

The last step, but one of the most important: we link a volume to the container.
The line './php/www:/var/www/html' specifically means that we link the "/ php / www" folder on the host to the folder "/ var / www / html" in our container. Without this step you will lose ALL data in the docker container, if you restart it, because there would be no location outside the container for the docker container to physically store files.

If we now docker-compose upexecute the command , the image will be built and then executed. If we then use a browser to surf to the IP address of the Kinamo cloud server with docker engine, we get to see the phpinfo page.

The database container
The MySQL base image that we are going to use from the Docker Hub does not require any additional configuration. So we do not have to create a new image.

It is enough to add the necessary parameters to it docker-compose.yml.
Add the following lines after the definition of the php container.

  db:
    image: mysql:5.7
    volumes:
     - /var/lib/mysql
    environment:
     - MYSQL_ROOT_PASSWORD=hunter2
     - MYSQL_DATABASE=database

With the MySQL container we also link a volume for the MySQL data. Instead of linking a folder to the container, we now use a Docker volume. The performance of this is better.
To create a Docker volume, we only provide the folder of the container for which the volume has to be made.
In human language: the folder "/ var / lib / mysql" in the container will be linked with a default folder that the docker will allocate on the host.
By means of the docker inspectcommand you can localize the volume on the host.

The parameters specified in "environment" are image dependent, in this case there are some variables that determine which value is passed to the docker container, for example the root password for the database, and the database name.

Bringing it all together
In order to ensure that the PHP container and the MySQL container can communicate, we will link them together.
We do this with a small adjustment docker-compose.yml.

version: '2'

services:
  php:
    build: php
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./php/www:/var/www/html
    links:
      - db

  db:
    image: mysql:5.7
    volumes:
     - /var/lib/mysql
    environment:
     - MYSQL_ROOT_PASSWORD=hunter2
     - MYSQL_DATABASE=database

In the configuration for the PHP container we add the part 'links'.
We state that a connection must be made with the MySQL container.

To test the connection we adapt our index.phpfile.

<?php

mysqli_connect("db", "root", "hunter2") or die(mysqli_error());
echo "Connected to MySQL<br />";

?>

If we now docker-compose upcarry out the two containers will be started and linked to each other. When we now surf to the web server we get the message 'Connected to MySQL'.

If you want the environment to continue to run in the background, you will do it docker-compose up -d.

Ready for the real thing!
Now you can get started with the development environment.
You can develop an application by adding code in the 'www' folder. The volume mapping ensures that that data is also saved on the host in the folder "/ php / www".
Thanks to Docker Compose, your work environment can easily be set up on other machines and ultimately also in a production environment ... And since the environment is made up of insulated containers, there are no problems due to differences in configuration or software versions!