Docker

Docker Test Example

1. Introduction

Continuous integration and continuous deployment has become one of the most common use cases of Docker early adopters. CI/CD merges development with testing, allowing developers to build code collaboratively, submit the master branch, and check for issues.

This allows developers to not only build their code, but also test their code in any environment type and as often as possible to catch bugs early in the applications development life cycle. Since Docker can integrate with tools like Jenkins and GitHub, developers can submit code in Git Hub, test the code and automatically trigger a build using Jenkins. Once the image is completed, images can be added to Docker registries.

 
This streamlines the process, saves time on build and set up processes, all while allowing developers to run tests in parallel and automate them so that they can continue to work on other projects while tests are being run. Since Docker works on prem, in the cloud or virtual environment and supports both Linux and Windows, enterprises no longer have to deal with inconsistencies between different environments types. Perhaps one of the most widely known benefits of the Docker CaaS platform.

In this post, firstly we will create a simple flask application. We will create an image for our application. Image will use redis for storage and it will be used as a dependency application. Python application will be a simple application. It will simple print “Welcome to Docker” on page.

We will be using two containers one for redis and one python application. Next we will create a script to test our python application. An image will be created to run this test script in a container.

2. Docker

So to understand about CI you should be familiar with Docker and Docker compose. Let’s have an overview of what is Docker and Docker compose.

According to the official documentation of Docker, Docker is a platform for developers and sysadmins to develop, deploy, and run applications with containers. The use of Linux containers to deploy applications is called containerization. Containers are not new, but their use for easily deploying applications is.

2.1 Docker container

A container image is a lightweight, stand-alone, executable package of a piece of software that includes everything needed to run it: code, runtime, system tools, system libraries, settings.

Containers isolate software from its surroundings, for example, differences between development and staging environments. Also, containers help reduce conflicts between teams running different software on the same infrastructure.

2.2 Docker image

An image is an executable package that includes everything needed to run an application–the code, a runtime, libraries, environment variables, and configuration files.

And when you have a Docker image, you run the container by using the image. So in nutshell, a container is a runtime instance of an image–what the image becomes in memory when executed (that is, an image with the state, or a user process).

3. Install Docker

So this was the overview of Docker. Let’s install Docker now. Docker Community Edition (CE) is ideal for developers. Small teams are looking to get started with Docker and experiment with container-based apps. So if you are not sure you should install CE.

3.1 Installing Docker on Ubuntu using the repository

1. Update the apt package index.

sudo apt-get update

2. Install packages to allow apt to use a repository over HTTPS:

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    software-properties-common

3. Add Docker’s official GPG key:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

3.2 Use the following command to set up the stable repository

1. Update the apt package index.

sudo apt-get update

2. Install the latest version of Docker CE, or go to the next step to install a specific version. Any existing installation of Docker is replaced.

sudo apt-get install docker-ce

3. Verify that Docker CE is installed correctly by running the hello-world image.

sudo docker run hello-world

For installing Docker on other Operating systems you can follow instructions from here depending on the operating system you are using.

4. Docker compose

According to Docker compose official documentation, Compose is a tool for defining and running multi-container Docker applications. With Compose, you use a YAML file to configure your application’s services. Then, with a single command, you create and start all the services from your configuration.

Using Compose is basically a three-step process:

1. Define your app’s environment with a Dockerfile so it can be reproduced anywhere.
2. Define the services that make up your app in docker-compose.yml so they can be run together in an isolated environment.
3. Run docker-compose up and Compose starts and runs your entire app.

4.1 Installing Docker-compose

On Linux, you can download the Docker Compose binary from the Compose repository release page on GitHub. Follow the instructions from the link, which involve running the curl command in your terminal to download the binaries. These step by step instructions are also included below.

1. Run this command to download the latest version of Docker Compose:

sudo curl -L https://github.com/docker/compose/releases/download/1.20.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/Docker-compose

2. Apply executable permissions to the binary:

sudo chmod +x /usr/local/bin/docker-compose

3. Optionally, install command completion for the bash and zsh shell.

4. Test the installation.

$ docker-compose --version
docker-compose version 1.20.1, build 1719ceb

5. Creating Sample Python Application

In this section we will be creating a simple python application using flask and redis. Then we will Dockerize this application using docker-compose. I am just creating very simple application which will just print “Welcome to Docker”. So that you can focus on the process rather than the application logic.

Create a folder Dockerci for our project.

$ mkdir dockerci
$ cd dockerci

Now let’s create our python application and create a file app.py:

Python application file app.py

from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host="redis")

@app.route("/")
def hello():
    visits = redis.incr('counter')
    html = "
Welcome to Docker !
" return html.format() if __name__ == "__main__": app.run(host="0.0.0.0", port=80)

So this is a python application using Flask and redis. Application just returning “Welcome to Docker” text in HTML.
As I have mentioned our application is using Redis and Flask. So we have to define these dependencies in our application before using them.

Let’s create a file requirements.txt and add the content below in this file.

requirements.txt

Flask
Redis

5.1 Dockerizing Python Application

As I have explained in Docker image, to Dockerize an application we have to create an image for application. We will use that image to run inside our container.
Let’s create an image for our python application.

Dockerfile

FROM python:2.7

WORKDIR /app

ADD requirements.txt /app/requirements.txt
RUN pip install -r requirements.txt

ADD app.py /app/app.py

EXPOSE 80

CMD ["python", "app.py"]

Let me explain you the meaning of each line in this Dockerfile.

  1. FROM python:2.7 here we are using python(2.7) as our base image because we are creating a python application. The number after colon is the version of python we want to use for our app.
  2. WORKDIR /app we are setting our work directory to /app. Our code will reside at this location inside container.
  3. ADD requirements.txt /app/requirements.txt as our application will be using Flask and Redis dependencies. And we have defined these dependencies in requirements.txt, so adding this file too inside our work directory.
  4. RUN pip install -r requirements.txt installing application’s pip dependencies.
  5. ADD app.py /app/app.py adding application code to the image.
  6. EXPOSE 80 our application will be listening on port 80.
  7. CMD ["python", "app.py"] this is the command that will be used to start our application.

So in this Dockerfile we have mentioned all the resources that will be required by our application.

5.2 Using Docker-Compose

Now we have to create docker-compose.yml file so that we can use the image created by Dockerile.

 vi docker-compose.yml

Now add following content to this file.

docker-compose.yml

web:
  build: .
  Dockerfile: Dockerfile
  links:
    - redis
  ports:
    - "80:80"
redis:
  image: redis

So docker-compose.yml file says that it will be using two containers, as it has created two services web for our application and redis as our data store. web will be using the current folder to build the image and using Dockerfile we have created above, we will create an image for our application. It defines a link to the redis service which will use the standard redis image from Docker Hub.

5.3 Deploying and Running Python Application

We are ready with Dockerfile and docker-compose.yml. Let’s put our code into a container and run that container.
For this use the below commands:

     $ Docker-compose -f ~/javacodegeeks/dockerci/docker-compose.yml build
     $ Docker-compose -f ~/javacodegeeks/dockerci/docker-compose.yml up -d

The first command will set up all the components needed by our application and the second will up our container. Let’s see how many containers are running currently. As I explained above there should be two containers, one for our python application and one for redis.
Execute this command to check the running containers:

sudo docker ps

This should result in the below output:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                NAMES
2316c8d35133        helloworld_web      "python app.py"          About an hour ago   Up About an hour    0.0.0.0:80->80/tcp   helloworld_web_1
21c3a097b00f        redis               "Docker-entrypoint..."   2 days ago          Up About an hour    6379/tcp             helloworld_redis_1

So as I can see both of the containers are up and running. And we are good to go.

Now let’s check if our application is running or not. We will make a curl request on localhost and port 80, as this is the port we have exposed to connect to our application. Execute this command below:

curl localhost:80

And this will give us the below output:

Welcome to Docker !

So our application is up and running in a Docker container. Next, we will be Dockerzing our testing environment by creating a testing script. This script will be checking in our application if it gives us the expected response or not.

6. Creating the Testing Environment

So we will create a testing environment to test our python application. It will be a simple test script which will make a curl request to our running application and check if it’s returning “Welcome Docker” text in response.

6.1 Creating Test Script

Create a simple script testing.sh.

vi testing.sh

And add following content to this file.

sleep 5
if curl web | grep -q '
Welcome to Docker !
'; then echo "Success!" exit 0 else echo "Failed!" exit 1 fi

So this is a simple testing script just looking for “Welcome to Docker !” in the application response and it prints Success and Failed accordingly.

6.2 Creating Environment for testing

So to test our application, we will be creating a testing environment similar to the application environment.
Let’s Dockerize the testing script we have created and create a Dockerfile.test file.

vi Dockerfile.test

And add the following content to this file.

Dockerfile.test

FROM ubuntu:trusty

RUN apt-get update && apt-get install -yq curl && apt-get clean

WORKDIR /app

ADD test.sh /app/testing.sh

CMD ["bash", "testing.sh"]

So here we simply put our testing.sh into the image. In the last line is the command that will be used to run our application.
Also this image is using ubuntu:trusty as base image and this will be used to install all the curl dependencies.

Next we will connect our testing environment to our python application. We will be using docker-compose for this. Let’s create a file docker-compose.test.yml.

vi docker-compose.test

And add following content to this file.

docker-compose.test.yml

sut:
  build: .
  Dockerfile: Dockerfile.test
  links:
    - web
web:
  build: .
  Dockerfile: Dockerfile
  links:
    - redis
redis:
  image: redis

So this file define a sut container and this container will be responsible for running our integration tests. sut container is using current directory as build context and specifies the Dockerfile.test. Its linking to the web and redis services.

6.3 Testing Application

So we are ready with our application running and our testing environment to test this application is also ready.
Let’s execute the below command and see if our script is able to test that application.

Docker-compose -f ~/javacodegeeks/dockerci/docker-compose.test.yml -p ci build

So we are ready with the build and now let’s up our container.

docker-compose -f ~/javacodegeeks/dockerci/docker-compose.test.yml -p ci up -d

Now lets check the output of our container:

docker logs -f ci_sut_1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    28  100    28    0     0   1402      0 --:--:-- --:--:-- --:--:--  1473
Success!

7. Conclusion

So by using Docker and docker-compose we can Dockerize our application and we can build a testing image, to test our running application.

We can use integration testing using docker-compose.test.yml file. So Continuous integration is one of the most popular use cases for Docker. Teams looking to build and deploy their applications quickly use Docker, combined with ecosystem tools like Jenkins, to drive apps from dev, testing staging and into production without having to tweak any code. Docker and its APIs generate automated Docker image builds and make pushes to Docker registries simple, fast and automated.

8. Download the Source Code

Download
You can download the full source code of this example here: Docker Test Example

Vikas Kumar

Vikas has graduated from Information Technology Department in NIT Kurukshetra. He has expertise in full-text search and works as a search engineer.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button