Sign up for free

or sign up with

Thanks for teaming up with Buddy

Check your inbox and click the verification link to let your code flow.

Introduction to Docker

This guide will explain you how to use Docker in everyday work and move on with continuous development.

Objectives of this guide

This guide will:

  • Explain you the basics of Docker.
  • Show you how to use Docker throughout the development process.
  • Illustrate the automation of the application deployment process with Buddy and Docker.

The contents of this guide requires basic Git knowledge—you can learn Git here.

Why should you care about Docker?

As a developer you probably know that before you can run an application (for example a website) on your machine you need to configure its environment first. The list of tasks required to do that may be pretty long and include:

  • Installing database version xx.xxx
  • Installing file server version yy.yyy
  • Installing package a version xy.zzz
  • and so on …

Environment management is cumbersome and expensive


Every change in the environment, like database version change for example, adding a new package or any other dependency means that:

  • Every developer has to introduce this particular change to his machine
  • Upon release all the changes have to be introduced to the production server

It’s hard to keep track of dependencies without proper tools. And still, with or without them, configuration-related problems tend to emerge unexpectedly and are hard to debug and fix. This is why over the years we’ve tested various methods of ruling them out.

Current tools may be slow and complicated

We used virtual machines and configuration management tools, such as Vagrant, Ansible or Puppet. However, virtual machines are very resource-consuming and the amount of time required to start and stop them is so huge that it slows down work progress. Dealing with configuration management tools is also pretty time-consuming and requires specialized knowledge.

The Docker Solution

How can Docker help you deal with the above problems?
Let’s start with the definition from Docker itself.

Docker containers wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries – anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment.

To make the message clearer:

  • Docker is a faster and less resource-consuming equivalent of the virtual machine.
  • In a few minutes you can run Docker on any server, using any operating system.

Do you think Docker sounds cool and want to give it a try? Read the next section to see how easy it is.

Docker in the development process

Let’s assume we’ve just hired you as our developer, responsible for the website. To start working you need to get access to:

  • Application code: the source code itself.
  • Documentation: will tell you what components you’re supposed to install on your machine and how to configure them in order to run the application locally… Wait a minute… Documentation… There is NO DOCUMENTATION—in most cases there’s no something like that.

While working with Docker we rule out the stickiest problems of dealing with configuration:

  • Working out what components need to be installed.
  • Picking up the correct version for each component.
  • Configuring the components properly in order to run the application locally.

Let’s move to a straightforward example that proves Docker can really do this.

Follow these steps to check out how Docker works

Install Docker

First of all you need to install Docker according to the guidelines on the supplier’s website:

  • For Mac click here.
  • For Linux click here.
Download sample files

Download sample files and let’s have some Docker fun together. Unzip them and place in any directory.

Get Docker running

Run the terminal, go to the directory where you unzipped the files and execute docker-compose up command:

cd unzipped_directory
$docker-compose up 

Marvel the results

You’re done—your development environment is running—you can view the website at http://localhost:8080.

Remember: all you’ve just done was installing Docker—no HTTP server installation, no dependencies to deal with. You didn’t have to configure one single component. Yet, you are ready to work. Awesome, huh? So let’s get busy!

Change the code—Blue is the new Black

Using your favorite IDE open index.html file. Change anything you like about that file, for example change

<body class="bg-black"> 

to

<body class="bg-blue">
Enjoy your new background

Save the changes and refresh the site. The background is blue—your changes are visible right away! What’s the conclusion? Introducing you to our team was fast and easy and you did your job very well!

What about the other sample files?

You’ve probably noticed index.html is not the only file. Let’s take a closer look at the contents of our project, which includes:

  • index.html, with the source code of the website.
  • nginx.conf, with the nginx server configuration.
  • docker-compose.yml, with all the information on the environment.

As we’ve already made some changes in index.html and you know the file very well, we’ll have a closer look at the other two.

nginx.conf

This is a very basic configuration of the nginx server. All it says is that the server is supposed to serve files from /www directory.

server {
    index index.html;
    root /www;
}
docker-compose.yml

Docker-compose.yml contains the definition of the application environment. The syntax of the file might be a bit scary at first glance, but don’t worry—we’ll clarify all the necessary issues.

version: “2”

services:
web:
 image: nginx
 ports:
  - "8080:80"
 volumes:
  - .:/www
  - ./nginx.conf:/etc/nginx/conf.d/default.conf

And here come the explanations we’ve promised:

version: “2“  

⟶ Determines the syntax used throughout the file. There are two versions of the docker-compose file format—version 1 (the legacy format, which doesn’t support volumes or networks) and version 2 (most up-to-date).

services

⟶ This section defines the containers. In this particular file we’re defining only one container named web. The container is defined in the following lines:

image: nginx

⟶ Means the container will be created on the basis of the nginx image. Images are stored in Docker registry. You can pick one of the ready-to-use images or create your own image.

ports:
  - "8080:80"

⟶ This section redirects the ports from local host to the container.

Port number 8080 on local host will be mapped to port number 80 in the container. Port number 80 is the port where the nginx server is listening. Thanks to this we are able to view the site at http://localhost:8080.

volumes:
 - .:/www
 - ./nginx.conf:/etc/nginx/conf.d/default.conf

⟶ This section is about mounting discs to the container.

In this example it says that the directory where the docker-compose up command is executed must be available at /www path.

This part of the file ensures that the project files that accompany docker-compose.yml file are placed in /www folder and our nginx configuration file overwrites the one in the container.

If you need any further explanations, please contact us at support@buddy.works, but we’re pretty sure you don’t need our assistance.

How to extend the Docker image with more services

Up till now, as our new employee, you didn’t have to worry about the configuration of the environment. Since you’re pretty relaxed, it's time to assign you a new task. It’s pretty straightforward: you have to add current date and time below the “hello-world” sentence on our website.

To do this, you're going to need the PHP. By default the nginx server is not handling PHP files, but we can configure it to deal with them. This means completing two tasks:

  • Configuring the nginx sever file to process PHP files.
  • Installing PHP server.

Configure nginx srver to process PHP files

Configuring nginx server means simply updating the nginx.conf file:

server {
        index index.php;
        root /www;

        location ~ \.php$ {
                fastcgi_pass php:9000;
                include fastcgi_params;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                        }
       }

The above changes indicate that all PHP files are supposed to be interpreted by the PHP service on port number 9000.

Install the PHP server

Next thing we need is the PHP server. We’ll add another container, responsible for interpreting PHP files. This might sound confusing, but in fact is hassle-free. Just wait a second and you’ll find out.

What do you have to do? Simply add another service to your docker-compose.yml file (the PHP one, besides the web one), run it on the basis of the official PHP version 7 image and with links command order that the nginx service should be available for web service.

If you got something like that, it’s cool. If not, just copy the below syntax and paste it into your docker-compose file (and save it).

version: "2"

services:
 web:
  image: nginx
  ports:
    - "8080:80"
  volumes:
    - .:/www
    - ./nginx.conf:/etc/nginx/conf.d/default.conf
  links:
   - php
php:
 image: php:7-fpm
 volumes:
  - .:/www

Please note one more detail. The disc with our repository is mounted at the /www path for both services. This is necessary for the PHP server to interpret the files sent by the nginx service.

All right, enough details for now. We are ready. So is the configuration. Time to move on to serious development and work on our index.html file. Want to display date and time on the website? Complete the following steps:

  • Change the filename to index.php
  • Add the line displaying the current date and time:

    <?php
    echo "<p>".date("F j, Y, g:i a")."</p>";
     ?>
    

Relaunch the Docker container

Now we need to take care of Docker. We want Docker to launch the new configuration, so that we can check if the date and time are really displayed on our website. To do this, run the following commands from the terminal:

Docker-compose down
Docker-compose up

Now you can refresh your website. And? How is it? Is it working? We're sure it is.

With the above instructions you can add another services, like MySQL, MongoDB, PostgreSQL and so on to your docker-compose.yml file. And what’s the most important with every push to the Git repository the changes you made will be available for other team members. Nobody needs to configure anything—all they have to do is run the docker-compose up command and the environment will be launched, regardless of the local operating system or the PHP server installation.

Automating deployment with Buddy and Docker

Till now we’ve been working on the website locally, using the local development environment. But how can we actually streamline the deployment with Docker? The answer is pretty obvious: install Docker Compose on the production server, upload new source files there and execute the docker-compose down and docker-compose up commands on the server.

Sounds easy, but when you have to do this manually a couple of times a day, it’s annoying. Every change in the repository that you want to deliver requires connecting the server, uploading the files there, logging in and running necessary commands (docker-compose down and up)—this is very time-consuming and error-prone. And you probably have more than one project and more than one delivery to deal with every day.

It would be really nice to automate the process. How? You can use Buddy—Continuous Deployment Platform equipped with pipelines. All you need is:

  • An account in Buddy - Sign up now if don't have one yet.
  • A server with Docker: your own, but in case you don’t have one, we recommend DigitalOcean. Make sure to apply Buddy10 promo code when signing up to receive $10 credit (if you have trouble applying the code, drop a line to support@buddy.works and we'll help you out!)

Set up a Buddy project with a free Git repository included

Working with Buddy in based on projects, so we need to set one. To do this, complete the following tasks:

  • Add a new project.
  • Pick Buddy as your Git hosting provider.
  • Import the repository we’ve been working on previously to Buddy.
Setting Up a Project in Buddy
Setting Up a Project in Buddy

Create your first Buddy pipeline to automate your daily development workflow

Now we’ll take care of the pipelines—delivery automation tools.

Add a pipeline

First, add a pipeline that will automatically deploy changes introduced to the repository to the production server.

Adding a Pipeline
Adding a Pipeline
Let Buddy upload the website for you on every change

Add an action that will upload the source files of your application to the server. In Buddy you can choose from numerous uploading options, like FTP, FTPS or SCP. In this example we’ll use SFTP. We need to enter the authorization data and the upload path.

Adding SFTP action
Adding SFTP action
Let Buddy relaunch the Docker container

Add an ssh action that will run docker-compose down and docker-compose up commands. This action requires authorization data and defining methods to be executed in working directory. Working directory must be the same as the one for the upload action, so that docker-compose up command is run in the folder where the source files are placed.

Adding an SSH action
Adding an SSH action
Your pipeline is ready

With such setup every change in the repository will automatically be pushed to the server and visible in the production environment. This concerns the configuration and the source code as well.

You can manually check how the pipeline works—simply hit Run button on the right side of the pipeline name. Now open the page (server IP:8080) and check your site on live server.

Manual triggering of the pipeline
Manual triggering of the pipeline

See how easy it is to setup a pipeline to ensure Dev-Test equivalance

And now we have one more, final trick for you. During the development process we recommend using the staging server. This is the place where the changes undergo testing prior to release. With Docker and Buddy configuring this machine will be easy—just follow the steps listed below.

Create a Staging branch

Add a new branch to your repository (stage branch). What is a branch? It’s a way of organizing the work on a given project. Git branches let you work on multiple disparate features at once, without having to deal with project dependencies or synchronization of changes. If you’re not familiar with Git, check out our Git guide.

Adding a Branch
Adding a Branch
Add a delivery pipeline for the Staging server

Add a new pipeline that will be dealing with the staging server. This pipeline will execute exactly the same tasks as the production server pipeline, but for another branch. To streamline the work, you can clone the existing pipeline. After that you need to modify it a little bit:

  • Change the branch name from production to staging
Adding another pipeline
Adding another pipeline
  • Edit the action responsible for uploading files: change the path so that it points to your staging server (staging application files must be placed in a different directory than live application files)
  • Edit ssh action:

    • Change the execution path to the one you’ve just set for the upload action (see above)
    • Change the docker compose up command to docker-compose run -d -p 8081:80 web (we are doing this to run staging application on a different port than the live application is running).
    Editing actions
    Editing actions

If you want to learn more about pipelines and their possible applications, check out this guide.

Play with it

Now your live and staging applications are running on the same server:

  • Live application at server IP:8080
  • Staging application server IP:8081
Live & Stage pipeline
Live & Stage pipeline

They may use different configurations and no changes in staging application will affect your live environment, as both applications are running in separate containers and are isolated from each other.

Summary

Let’s try to recap: we’ve just learned how to deal with Docker and use docker-compose.yml file to set up the application environment in a very short time. We’ve managed to introduce two simple changes into the application code and review them. Later, we used Buddy and Docker to automate the process of delivering the application to the server.

Thanks to Docker, we got you up and running in no time. All you had to do was to install Docker, pull the files from the repository and you were able to commit code in no time and provide value for our company. You also know how to perform the same operations on the server and how to use Buddy and its pipelines to automate your work.

This is just a brief summary of what Buddy offers regarding Docker. If you are interested in our solution, you can read more about Buddy in other guides.

If you have any further questions, don’t hesitate to contact us at support@buddy.works or simply register for the trial version and have a look at Buddy.

Thanks for reading!

Start with a free account if you don’t have an account yet

Join our development automation movement!

Download On-Premises Installation