Docker Compose Guide for Beginners

The author of the article, which we are publishing today, says that it is intended for those developers who want to learn Docker Compose and are on their way to creating their first client-server application using Docker. It is assumed that the reader of this material is familiar with the basics of Docker. If this is not the case, you can take a look at this series of materials this a post covering the basics of Docker along with the basics of Kubernetes, and this article for beginners.

Docker Compose Guide for Beginners

What is Docker Compose?

Docker Compose is a tool included with Docker. It is designed to solve problems related to the deployment of projects.

While learning the basics of Docker, you may have come across the creation of the simplest applications that work autonomously, not depending, for example, on external data sources or on certain services. In practice, such applications are rare. Real projects usually involve a whole set of collaborative applications.

How do you know if you need to use Docker Compose when deploying a project? Actually, it's very simple. If you're using multiple services to run this project, then Docker Compose might come in handy. For example, in a situation where you create a website that, in order to perform user authentication, needs to connect to a database. Such a project may consist of two services - one that ensures the operation of the site, and one that is responsible for supporting the database.

Docker Compose technology, if you describe it in a simplified way, allows you to start many services with a single command.

Difference between Docker and Docker Compose

Docker is used to manage the individual containers (services) that make up an application.

Docker Compose is used to manage multiple containers that are part of an application at the same time. This tool offers the same features as Docker, but allows you to work with more complex applications.

Docker Compose Guide for Beginners
Docker (single container) and Docker Compose (multiple containers)

Typical Docker Compose use case

Docker Compose is, in the right hands, a very powerful tool that allows you to quickly deploy applications with complex architectures. Now we will look at an example of the practical use of Docker Compose, the analysis of which will allow you to evaluate the benefits that the use of Docker Compose will give you.

Imagine that you are the developer of a web project. This project includes two websites. The first allows business people to create, with just a few clicks, online stores. The second is aimed at customer support. These two sites interact with the same database.

Your project is becoming more and more popular, and it turns out that the capacity of the server on which it works is no longer enough. As a result, you decide to transfer the entire project to another machine.

Unfortunately, you haven't used something like Docker Compose. Therefore, you will have to migrate and reconfigure services one at a time, hoping that you will not forget anything in the process of this work.

If you are using Docker Compose, then migrating your project to a new server is an issue that can be solved by running a few commands. To complete the transfer of the project to a new location, you only need to make some settings and upload a backup copy of the database to the new server.

Developing a client-server application using Docker Compose

Now that you know what we're going to be using Docker Compose for, it's time to create your first client/server application using this tool. Namely, we are talking about the development of a small website (server) in Python, which can produce a file with a text fragment. This file is requested from the server by a program (client), also written in Python. After receiving the file from the server, the program displays the text stored in it on the screen.

Please note that we are assuming that you have the basics of Docker and that you already have the Docker platform installed.

Let's start working on the project.

▍1. Create a project

In order to build your first client/server application, I suggest you start by creating a project folder. It should contain the following files and folders:

  • File docker-compose.yml. This is a Docker Compose file that will contain the instructions needed to start and configure the services.
  • Folder server. It will contain the files necessary to make the server work.
  • Folder client. This is where the client application files will be located.

As a result, the contents of the main folder of your project should look like this:

.
├── client/
├── docker-compose.yml
└── server/
2 directories, 1 file

▍2. Server creation

Here we, in the process of creating a server, will touch on some basic things regarding Docker.

2a. Creating Files

Go to folder server and create the following files in it:

  • File server.py. It will contain the server code.
  • File index.html. This file will contain a piece of text that the client application should display.
  • File Dockerfile. This is the Docker file that will contain the instructions needed to create the server environment.

This is what the contents of your folder should look like server/:

.
├── Dockerfile
├── index.html
└── server.py
0 directories, 3 files

2b. Editing a Python file.

Add to file server.py the following code:

#!/usr/bin/env python3

# Импорт системных библиотек python.
# Эти библиотеки будут использоваться для создания веб-сервера.
# Вам не нужно устанавливать что-то особенное, эти библиотеки устанавливаются вместе с Python.

import http.server
import socketserver

# Эта переменная нужна для обработки запросов клиента к серверу.

handler = http.server.SimpleHTTPRequestHandler

# Тут мы указываем, что сервер мы хотим запустить на порте 1234. 
# Постарайтесь запомнить эти сведения, так как они нам очень пригодятся в дальнейшем, при работе с docker-compose.

with socketserver.TCPServer(("", 1234), handler) as httpd:

    # Благодаря этой команде сервер будет выполняться постоянно, ожидая запросов от клиента.

   httpd.serve_forever()

This code allows you to create a simple web server. He will give clients a file index.html, whose content will later be displayed on the web page.

2c. Editing an HTML file

To file index.html add the following text:

Docker-Compose is magic!

This text will be sent to the client.

2d. Editing the Dockerfile

Now we will create a simple file Dockerfile, which will be responsible for organizing the runtime environment for the Python server. As the basis of the created image, we will use in an official way, designed to run programs written in Python. Here is the contents of the Dockerfile:

# На всякий случай напоминаю, что Dockerfile всегда должен начинаться с импорта базового образа.
# Для этого используется ключевое слово 'FROM'.
# Здесь нам нужно импортировать образ python (с DockerHub).
# В результате мы, в качестве имени образа, указываем 'python', а в качестве версии - 'latest'.

FROM python:latest

# Для того чтобы запустить в контейнере код, написанный на Python, нам нужно импортировать файлы 'server.py' и 'index.html'.
# Для того чтобы это сделать, мы используем ключевое слово 'ADD'.
# Первый параметр, 'server.py', представляет собой имя файла, хранящегося на компьютере.
# Второй параметр, '/server/', это путь, по которому нужно разместить указанный файл в образе.
# Здесь мы помещаем файл в папку образа '/server/'.

ADD server.py /server/
ADD index.html /server/

# Здесь мы воспользуемся командой 'WORKDIR', возможно, новой для вас.
# Она позволяет изменить рабочую директорию образа.
# В качестве такой директории, в которой будут выполняться все команды, мы устанавливаем '/server/'.

WORKDIR /server/

Now let's work on the client.

▍3. Create a client

While creating the client side of our project, we will recall some Docker basics along the way.

3a. Creating Files

Go to your project folder client and create the following files in it:

  • File client.py. This is where the client code will be.
  • File Dockerfile. This file plays the same role as a similar file in the server folder. Namely, it contains a statement that describes how to create an environment for executing client code.

As a result, your folder client/ At this stage it should look like this:

.
├── client.py
└── Dockerfile
0 directories, 2 files

3b. Editing a Python File

Add to file client.py the following code:

#!/usr/bin/env python3

# Импортируем системную библиотеку Python.
# Она используется для загрузки файла 'index.html' с сервера.
# Ничего особенного устанавливать не нужно, эта библиотека устанавливается вместе с Python.

import urllib.request

# Эта переменная содержит запрос к 'http://localhost:1234/'.
# Возможно, сейчас вы задаётесь вопросом о том, что такое 'http://localhost:1234'.
# localhost указывает на то, что программа работает с локальным сервером.
# 1234 - это номер порта, который вам предлагалось запомнить при настройке серверного кода.

fp = urllib.request.urlopen("http://localhost:1234/")

# 'encodedContent' соответствует закодированному ответу сервера ('index.html').
# 'decodedContent' соответствует раскодированному ответу сервера (тут будет то, что мы хотим вывести на экран).

encodedContent = fp.read()
decodedContent = encodedContent.decode("utf8")

# Выводим содержимое файла, полученного с сервера ('index.html').

print(decodedContent)

# Закрываем соединение с сервером.

fp.close()

Thanks to this code, the client application can download data from the server and display it on the screen.

3c. Editing the Dockerfile

As in the case of the server, we create for the client a simple Dockerfile, responsible for shaping the environment in which the Python client application will run. Here is the client code Dockerfile:

# То же самое, что и в серверном Dockerfile.

FROM python:latest

# Импортируем 'client.py' в папку '/client/'.

ADD client.py /client/

# Устанавливаем в качестве рабочей директории '/client/'.

WORKDIR /client/

▍4. Docker Compose

As you can see, we have created two different projects: server and client. Each of them has its own file Dockerfile. So far, everything that happens does not go beyond the basics of working with Docker. Now we get to work with Docker Compose. To do this, refer to the file docker-compose.ymllocated in the root folder of the project.

Please note that here we do not aim to cover absolutely all the commands that can be used in docker-compose.yml. Our main goal is to break down a practical example that gives you basic knowledge of Docker Compose.

Here is the code to put in the file docker-compose.yml:

# Файл docker-compose должен начинаться с тега версии.
# Мы используем "3" так как это - самая свежая версия на момент написания этого кода.

version: "3"

# Следует учитывать, что docker-composes работает с сервисами.
# 1 сервис = 1 контейнер.
# Сервисом может быть клиент, сервер, сервер баз данных...
# Раздел, в котором будут описаны сервисы, начинается с 'services'.

services:

  # Как уже было сказано, мы собираемся создать клиентское и серверное приложения.
  # Это означает, что нам нужно два сервиса.
  # Первый сервис (контейнер): сервер.
  # Назвать его можно так, как нужно разработчику.
  # Понятное название сервиса помогает определить его роль.
  # Здесь мы, для именования соответствующего сервиса, используем ключевое слово 'server'.

  server:
 
    # Ключевое слово "build" позволяет задать
    # путь к файлу Dockerfile, который нужно использовать для создания образа,
    # который позволит запустить сервис.
    # Здесь 'server/' соответствует пути к папке сервера,
    # которая содержит соответствующий Dockerfile.

    build: server/

    # Команда, которую нужно запустить после создания образа.
    # Следующая команда означает запуск "python ./server.py".

    command: python ./server.py

    # Вспомните о том, что в качестве порта в 'server/server.py' указан порт 1234.
    # Если мы хотим обратиться к серверу с нашего компьютера (находясь за пределами контейнера),
    # мы должны организовать перенаправление этого порта на порт компьютера.
    # Сделать это нам поможет ключевое слово 'ports'.
    # При его использовании применяется следующая конструкция: [порт компьютера]:[порт контейнера]
    # В нашем случае нужно использовать порт компьютера 1234 и организовать его связь с портом
    # 1234 контейнера (так как именно на этот порт сервер 
    # ожидает поступления запросов).

    ports:
      - 1234:1234

  # Второй сервис (контейнер): клиент.
  # Этот сервис назван 'client'.

  client:
    # Здесь 'client/ соответствует пути к папке, которая содержит
    # файл Dockerfile для клиентской части системы.

    build: client/

    # Команда, которую нужно запустить после создания образа.
    # Следующая команда означает запуск "python ./client.py".
 
    command: python ./client.py

    # Ключевое слово 'network_mode' используется для описания типа сети.
    # Тут мы указываем то, что контейнер может обращаться к 'localhost' компьютера.

    network_mode: host

    # Ключевое слово 'depends_on' позволяет указывать, должен ли сервис,
    # прежде чем запуститься, ждать, когда будут готовы к работе другие сервисы.
    # Нам нужно, чтобы сервис 'client' дождался бы готовности к работе сервиса 'server'.
 
    depends_on:
      - server

▍5. Project build

After in docker-compose.yml all the necessary instructions have been made, the project needs to be assembled. This step of our work resembles the use of the command docker build, but the corresponding command is related to several services:

$ docker-compose build

▍6. Launch of the project

Now that the project is built, it's time to run it. This step of our work corresponds to the step at which, when working with individual containers, the command is executed docker run:

$ docker-compose up

After executing this command, the text loaded by the client from the server should appear in the terminal: Docker-Compose is magic!.

As already mentioned, the server uses the computer port 1234 to serve customer requests. Therefore, if you go in the browser to the address http://localhost:1234/, it will display a page with text Docker-Compose is magic!.

Useful Commands

Let's take a look at some of the commands that you might find useful when working with Docker Compose.

This command allows you to stop and delete containers and other resources created by the command docker-compose up:

$ docker-compose down

This command prints the service logs:

$ docker-compose logs -f [service name]

For example, in our project it can be used in this form: $ docker-compose logs -f [service name].

With this command, you can display a list of containers:

$ docker-compose ps

This command allows you to execute a command in a running container:

$ docker-compose exec [service name] [command]

For example, it might look like this: docker-compose exec server ls.

This command allows you to display a list of images:

$ docker-compose images

Results

We have covered the basics of working with Docker Compose technology, the knowledge of which will allow you to use this technology and, if desired, begin to study it in more depth. Here repository with the project code, which we considered here.

Dear Readers, Do you use Docker Compose in your projects?

Docker Compose Guide for Beginners

Source: habr.com

Add a comment