Минобрнауки России Федеральное государственное бюджетное образовательное учреждение высшего образования «Волгоградский государственный технический университет» Факультет_________________________________________________________ Электроники и вычислительной техники Кафедра___________________________________________________________ Электронно-вычислительные машины и системы ПОЯСНИТЕЛЬНАЯ ЗАПИСКА к курсовой работе (проекту) по дисциплине______________________________________________________ Программное обеспечение инфокоммуникационных систем на тему____________________________________________________________ Создание сетевого клиент-серверного приложения работы с _____________________________________________________________ сервисной службой интернет-провайдера _____________________________________________________________ _____________________________________________________________ Колосов Евгений Юрьевич Студент___________________________________________________________ (фамилия, имя, отчество) Группа________________________ ЭВМ – 1.2 Руководитель работы (проекта) __________________ ___________________ (подпись и дата подписания) (инициалы и фамилия) Члены комиссии: _____________________ (подпись и дата подписания) (инициалы и фамилия) _____________________ (подпись и дата подписания) ____________________________ (инициалы и фамилия) _____________________ (подпись и дата подписания) ____________________________ ____________________________ (инициалы и фамилия) Нормоконтролер ______________________ ___________________________ (подпись, дата подписания) Волгоград 2020 г. (инициалы и фамилия) Минобрнауки России Федеральное государственное бюджетное образовательное учреждение высшего образования «Волгоградский государственный технический университет» Факультет _________________________________________________________ Электроники и вычислительной техники Направление (специальность)_________________________________________ Информатика и вычислительная техника Кафедра ___________________________________________________________ Электронно-вычислительные машины и системы Дисциплина________________________________________________________ Программное обеспечение инфокоммуникационных систем Утверждаю Зав. кафедрой_________________ «_______» ____________20 ___ г. ЗАДАНИЕ на курсовую работу (проект) Студент___________________________________________________________ Колосов Евгений Юрьевич (фамилия, имя, отчество) ЭВМ – 1.2 Группа________________________ 1. Тема: ___________________________________________________________ Создание сетевого клиент-серверного приложения работы с _____________________________________________________________ сервисной службой интернет-провайдера _____________________________________________________________ _____________________________________________________________ Утверждена приказом от «_____» ______________ 20___ г. № _________ 2. Срок представления работы (проекта) к защите «___»_______________20__ г. 3. Содержание расчетно-пояснительной записки: ________________________ 1 ИСПОЛЬЗУЕМЫЕ И ПОЛЕЗНЫЕ ТЕХНОЛОГИИ 2 РЕАЛИЗАЦИЯ __________________________________________________________________ ПРИЛОЖЕНИЯ __________________________________________________________________ __________________________________________________________________ __________________________________________________________________ 4. Перечень графического материала: __________________________________ __________________________________________________________________ __________________________________________________________________ 5. Дата выдачи задания «_____» ____________________20 ___ г. Руководитель работы (проекта)______________________ ________________ подпись, дата инициалы и фамилия Задание принял к исполнению_______________________ ________________ подпись, дата инициалы и фамилия СОДЕРЖАНИЕ ВВЕДЕНИЕ .............................................................................................................. 4 1 ИСПОЛЬЗУЕМЫЕ И ПОЛЕЗНЫЕ ТЕХНОЛОГИИ .................................... 6 1.1 ASP.NET ...................................................................................................... 6 1.2 Docker........................................................................................................... 8 1.3 Сокеты.......................................................................................................... 9 1.4 Squid ........................................................................................................... 11 1.5 2 Выводы ...................................................................................................... 12 РЕАЛИЗАЦИЯ ПРИЛОЖЕНИЯ ................................................................... 13 2.1 Клиент-серверное взаимодействие ............................................................ 13 2.2 Реализация приложения .............................................................................. 16 2.3 Выводы .......................................................................................................... 24 ЗАКЛЮЧЕНИЕ ..................................................................................................... 24 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ........................................... 25 3 ВВЕДЕНИЕ Сегодня практически все компьютеры (настольные и мобильные) подключены к сети Интернет и в основном используют один из ее сервисов – World Wide Web (Всемирную Паутину, web-сеть). Первоначально данный сервис (web-сеть) использовался только для связывания и предоставления статической информации. Однако в настоящее время он стал платформой для удаленного использования специальных прикладных программ – web-приложений. Если ранее, прежде чем использовать приложение на локальном компьютере, требовалось его устанавливать, то сейчас приложение можно запускать с помощью web- браузера (Интернет-обозревателя), просто указав его адрес. При этом само приложение выполняется на удаленном компьютере (сервере), а пользователь может работать с ним на своем компьютере с помощью web-браузера. Архитектура «клиент-сервер» определяет общие принципы организации взаимодействия в сети, где имеются серверы, узлы-поставщики некоторых специфичных функций (сервисов) и клиенты, потребители этих функций. Практические реализации такой архитектуры называются клиентсерверными технологиями. Каждая технология определяет собственные или использует имеющиеся правила взаимодействия между клиентом и сервером, которые называются протоколом обмена (протоколом взаимодействия). Обычно клиентское приложение взаимодействует с пользователем, а серверное приложение предоставляет доступ к некоторому совместно используемому ресурсу. Чаще всего обменом данными с одним или несколькими серверными процессами занимается несколько клиентских процессов. Клиент и сервер могут находиться на одном и том же ведущем компьютере или на отдельных хостах, соединенных по сети. Для взаимного обмена сообщениями клиент и сервер используют IPC-механизмы. 4 Клиент-серверные приложения активно применяются в бизнесе, на предприятиях и других организациях для обеспечения рабочего процесса, наделения сотрудников удобными рабочими инструментами, и, как следствие, повышения отдачи от труда. Целью данной работы является разработка веб-приложения для работы с сервисной службой интернет-провайдера. Необходимо реализовать клиентсерверное взаимодействие и разработку приложения. Для достижения поставленной цели работы необходимы: Определить используемый стек технологий; Описать веб-приложение и реализовать его. В первой главе рассмотрены технологии, для реализации приложения и приведено описание их преимуществ для использования в данной области. Во второй главе показан непосредственно процесс разработки и реализации приложения. 5 1 ИСПОЛЬЗУЕМЫЕ И ПОЛЕЗНЫЕ ТЕХНОЛОГИИ 1.1 ASP.NET Платформа ASP.NET Core представляет технологию от компании Microsoft, предназначенную для создания различного рода веб-приложений: от небольших веб-сайтов до крупных веб-порталов и веб-сервисов [1]. С одной стороны, ASP.NET Core является продолжением развития платформы ASP.NET. Но с другой стороны, это не просто очередной релиз. Выход ASP.NET Core фактически означает революцию всей платформы, ее качественное изменение. Разработка над платформой началась еще в 2014 году. Тогда платформа условно называлась ASP.NET vNext. В июне 2016 года вышел первый релиз платформы. А в декабре 2019 года вышла версия ASP.NET Core 3.1. ASP.NET Core теперь полностью является opensource-фреймворком. Все исходные файлы фреймворка доступны на GitHub. ASP.NET Core может работать поверх кросс-платформенной среды .NET Core, которая может быть развернута на основных популярных операционных системах: Windows, Mac OS, Linux. И таким образом, с помощью ASP.NET Core мы можем создавать кросс-платформенные приложения. И хотя Windows в качестве среды для разработки и развертывания приложения до сих пор превалирует, но теперь уже мы не ограничены только этой операционной системой. То есть мы можем запускать веб-приложения не только на ОС Windows, но и на Linux и Mac OS. А для развертывания веб-приложения можно использовать традиционный IIS, либо кросс-платформенный веб-сервер Kestrel. Благодаря модульности фреймворка все необходимые компоненты вебприложения могут загружаться как отдельные модули через пакетный менеджер Nuget. Кроме того, в отличие от предыдущих версий платформы нет необходимости использовать библиотеку System.Web.dll. 6 ASP.NET Core включает в себя фреймворк MVC, который объединяет функциональность MVC, Web API и Web Pages [2]. В предыдущих версии платформы данные технологии реализовались отдельно и поэтому содержали много дублирующей функциональности. Сейчас же они объединены в одну программную модель ASP.NET Core MVC. А Web Forms полностью ушли в прошлое. Кроме объединения вышеупомянутых технологий в одну модель в MVC был добавлен ряд дополнительных функций. Одной из таких функций являются тэг-хелперы (tag helper), которые позволяют более органично соединять синтаксис html с кодом С#. ASP.NET Core характеризуется расширяемостью. Фреймворк построен из набора относительно независимых компонентов. И мы можем либо использовать встроенную реализацию этих компонентов, либо расширить их с помощью механизма наследования, либо вовсе создать и применять свои компоненты со своим функционалом. Также было упрощено управление зависимостями и конфигурирование проекта. Фреймворк теперь имеет свой легковесный контейнер для внедрения зависимостей, и больше нет необходимости применять сторонние контейнеры, такие как Autofac, Ninject. Хотя при желании их также можно продолжать использовать. В качестве инструментария разработки мы можем использовать последние выпуски Visual Studio, начиная с версии Visual Studio 2015. Кроме того, мы можем создавать приложения в среде Visual Studio Code, которая является кросс-платформенной и может работать как на Windows, так и на Mac OS X и Linux. Для обработки запросов теперь используется новый конвейер HTTP, который основан на компонентах Katana и спецификации OWIN. А его модульность позволяет легко добавить свои собственные компоненты. 7 1.2 Docker Docker (Докер) — программное обеспечение с открытым исходным кодом, применяемое для разработки, тестирования, доставки и запуска вебприложений в средах с поддержкой контейнеризации (Рисунок 1) [4]. Он нужен для более эффективного использование системы и ресурсов, быстрого развертывания готовых программных продуктов, а также для их масштабирования и переноса в другие среды с гарантированным сохранением стабильной работы. Docker представляет собой систему управления контейнерами. Она позволяет «упаковать» приложение или веб-сайт со всем его окружением и зависимостями в контейнер, которым в дальнейшем можно легко и просто управлять: переносить на другой сервер, масштабировать, обновлять. Рисунок 1 – архитектура Docker Docker был написан на языке программирования Go и выпущен в 2013 году. Изначально он работал только с Linux-системами, однако на данный момент его можно использовать также в Windows и macOS. Несмотря на то, 8 что проект является относительно новым, Докер широко используется многими специалистами и продолжает завоевывать популярность. Важной частью экосистемы Docker является Docker Hub – открытый репозиторий образов контейнеров. В нем можно найти десятки готовых приложений от официальных разработчиков. Среди них – nginx, MySQL, Apache, Gitlab, Redmine, Elasticsearch, Jenkins и другие. Образы Docker — это шаблоны в формате «только чтение», из которых запускаются Docker контейнеры. Каждый образ состоит из последовательности слоев. Docker использует union file systems для объединения этих слоев в единый образ. Union FS позволяет файлам и директориям отдельных файловых систем известным как ветки (branches) быть прозрачно наложенными друг на друга, чтобы образовать единую связную файловую систему. Образ определяется в Dockerfile. Каждый образ начинается с основного образа (base image), такого как ubuntu (основного образа ОС Ubuntu) или fedora (основного образа ОС Fedora). 1.3 Сокеты Веб-сокеты - новый путь для клиентов, чтобы связываться с сервером и наоборот без лишних http заголовков. Веб-сокеты используют свой собственный протокол, который был определен IETF. Последняя версия - RFC 6455. Предыдущие версии протокола доказали, что он имеет некоторые проблемы безопасности, поэтому он был реализован в некоторых браузерах, как Opera, но не был включен по умолчанию. Помимо своего протокола, веб-сокеты также имеют свой API, который может быть использован в веб-приложениях, чтобы открыть или закрыть соединение и посылать/получать сообщения. Он называется WebSockets API и определен в спецификации W3C. 9 С веб-сокетами можно использовать двунаправленную полную дюплексную связь между сервером и клиентом с минимальными накладными расходами по сравнению с обычным http. Веб-сокеты обещают быструю, более масштабируемую и более прочную высокую производительность приложений в реальном времени. На самом деле, по некоторым анализам Kaazing корпорации, это может уменьшить размер трафика заголовков http от 500:1 до 1000:1 и уменьшить задержки в сети до 3:1. Это приводит к серьезному повышению производительности, особенно для приложений, требующих быстрого обновления в реальном времени. Принцип работы такой, что до того, как клиент и сервер начнут обмениваться сообщениями, они должны установить соединение. Это делается установкой "рукопожатия" (Рисунок 2), где клиент и сервер посылают запрос на соединение, и, если сервер хочет этого, то он пошлет ответ, подтверждающий соединение. Спецификация протокола дает понять, что одно из проектных решений этого протокола было обеспечить, чтобы оба, основанных на http клиентов и основанных на websocket, могли использовать один порт [3]. Рисунок 2 – "рукопожатие" сервера с различными клиентами 10 1.4 Squid Squid - это полнофункциональное приложение кэширующего прокси сервера, которое предоставляет сервисы кэширования и прокси для HTTP (Рисунок 3), FTP и других популярных сетевых протоколов. Squid может осуществлять кэширование и проксирование SSL запросов и кэширование результатов DNS поиска, а также выполнять прозрачное кэширование. Squid также поддерживает широкий набор кэширующих протоколов, таких как ICP (кэширующий интернет протокол), HTCP (гипертекстовый кэширующий протокол), CARP (протокол кэширования маршрутизации) и WCCP (кэширующий протокол перенаправления контента). Рисунок 3 – фильтрация HTTP и HTTPS трафика squid proxy Прокси сервер Squid - это великолепное решение широких требований к кэширующему и прокси серверу, которое масштабируется для сетей от уровня регионального офиса до корпорации, когда обеспечивается расширяемый разделяемый механизм контроля доступа и отслеживания критических параметров через протокол SNMP. При выборе компьютерной системы для использования в качестве Squid прокси или кеширующего сервера, нужно 11 убедиться, что система оснащена большим количеством оперативной памяти, поскольку поддерживает Squid кэш в памяти для увеличения производительности. Используется в UNIX-like системах и в ОС семейства Windows NT. Имеет возможность взаимодействия с Active Directory Windows Server путём аутентификации через LDAP, что позволяет использовать разграничения доступа к интернет ресурсам пользователей, которые имеют учётные записи на Windows Server, также позволяет организовать «нарезку» интернет трафика для различных пользователей. Используется вместе с движками Mediawiki на wiki хостингах. Использование кэширующего прокси-сервера становится выгодно примерно с 2000 посетителей в сутки. Сервер Squid развивается в течение уже многих лет. Обеспечивает совместимость с большинством важнейших протоколов Интернета, а также с операционными системами. 1.5 Выводы В результате рассмотрения и анализа данных технологий можно прийти к выводу, что данные технологии позволят создать современное, динамическое и реактивное одностраничное веб-приложение, которое бы удовлетворяло всем требованиям к прогрессивному веб-приложению. 12 2 РЕАЛИЗАЦИЯ ПРИЛОЖЕНИЯ 2.1 Клиент-серверное взаимодействие Клиент-серверное взаимодействие один из главных моментов в изучении дисциплины веб-дизайн. Любой сайт, размещённый в сети Интернет, основывается на связке «клиент-сервер». И это не только электронные формы. Даже простое «перелистывание» страниц некоторого сайта в Интернете – пример клиент-серверного взаимодействия, ведь странички хранятся не на вашем личном компьютере, а подгружаются извне. Рассмотрим основные понятия, которые предполагает эта глава: Клиент — достаточно широкое понятие, начиная от некоторого физического лица и заканчивая некоторой программой на компьютере (например, почтовый клиент). В нашем случае это компьютер, оснащённый специальным программным обеспечением, которое позволяет пользователю задать запрос к другой машине и получить ответ. Код, выполняемый на стороне клиента, чаще всего называют клиентским кодом. Он обеспечивает создание пользовательского интерфейса. Здесь, когда речь заходит о браузере, важную роль играет JavaScript и библиотеки расширения (в нашем случае jQuery). Сервер — это компьютер, оснащённый специальным программным обеспечением, которое позволяет решить задачи предоставления пользователю доступа к некоторым услугам и ресурсам, которыми владеет и управляет данный сервер. Код, выполняемый на стороне сервера, чаще всего называют серверным кодом (серверным сценарием). Он обеспечивает обработку данных. Здесь важную роль играют серверные языки программирования. Примером таких языков являются PHP и Python. Клиент-серверное взаимодействие — это обмен данными между клиентом и сервером. Браузер не единственное программное обеспечение, которое позволяет осуществлять клиент-серверное взаимодействие. 13 Почтовые клиенты, программы обмена мгновенными сообщениями, игровые многопользовательские приложения – пример программного обеспечения, которое осуществляет клиент-серверное взаимодействие. Принципы взаимодействия для таких приложений во многом похожи. Схематически его можно описать следующим образом (Рисунок 4): Рисунок 4 – Клиент-серверное взаимодействие Для реализации был выбран C#. Сервер разработан на языке программирования C#, с использованием библиотеки .Net Core 3.1. Клиент-серверное взаимодействие строится с помощью протокола TCP. Протокол TCP (Transmission Control Protocol) – это сетевой протокол, который «заточен» под соединение. Иными словами, прежде, чем начать обмен данными, данному протоколу требуется установить соединение между двумя хостами. Данный протокол имеет высокую надежность, поскольку позволяет не терять данные при передаче, запрашивает подтверждения о получении от принимающей стороны и в случае необходимости отправляет данные повторно. При этом отправляемые пакеты данных сохраняют порядок отправки, то есть можно сказать, что передача данных упорядочена. Минусом данного протокола является относительно 14 низкая скорость передачи данных, за счет того, что выполнение надежной и упорядоченной передачи занимает много времени. Также были задействованы сокеты. Для ответа они не нуждается в ваших повторяющихся запросах. Сокет в сети работает таким образом, что достаточно лишь один раз выполнить запрос, а потом ждать отклика. И вы можете спокойно «слушать» сервер, который отправит сообщения по мере готовности. На рисунке 5 изображено взаимодействие клиента с сервером без сокетов. Рисунок 5 – Взаимодействие клиент-сервера без сокета Рисунок 6 иллюстрирует всё то же взаимодействие, но уже с сокетом. 15 Рисунок 6 – Взаимодействие клиент-сервера с сокетом 2.2 Реализация приложения Сервер работает по протоколу TCP, с помощью сокетов (Рисунок 7): Рисунок 7 - Общая схема работы серверного сокета TCP 16 Сначала создаём сокет: Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); После создания сокета связываем его с локальной точкой методом Bind: listenSocket.Bind(ipPoint); Сокет будет прослушивать подключения по 8005 порту на локальном адресе 127.0.0.1. То есть клиент должен будет подключаться к локальному адресу и порту 8005. Далее начинаем прослушивание: listenSocket.Listen(10); Метод Listen вызывается только после метода Bind. В качестве параметра он принимает количество входящих подключений, которые могут быть поставлены в очередь сокета. После вызова метода Listen начинается прослушивание входящих подключений, и если подключения приходят на сокет, то их можно получить с помощью метода Accept: Socket handler = listenSocket.Accept(); Метод Accept извлекает из очереди ожидающих запрос первый запрос и создает для его обработки объект Socket. Если очередь запросов пуста, то метод Accept блокирует вызывающий поток до появления нового подключения. Для обработки запроса сначала в цикле do..while получаем данные с помощью метода Receive: do { bytes = handler.Receive(data); builder.Append(Encoding.Unicode.GetString(data, 0, bytes)); } while (handler.Available > 0); 17 Метод Receive в качестве параметра принимает массив байтов, в который считываются полученные данные, и возвращает количество полученных байтов. Если отсутствуют данные, доступные для чтения, метод Receive блокирует вызывающий поток до тех пор, пока не станут доступны данные, если не было установлено значение тайм-аута путем использования объекта Socket.ReceiveTimeout. Если значение тайм-аута было превышено, объект Receive выдаст исключение SocketException. Чтобы отследить наличие данных в потоке, используется свойство Available. После получения данных клиенту посылается ответное сообщение с помощью метода Send, который в качестве параметра принимает массив байтов: handler.Send(data); В конце обработки запроса надо закрыть связанный с ним сокет: handler.Shutdown(SocketShutdown.Both); handler.Close(); Вызов метода Shutdown() перед закрытием сокета гарантирует, что не останется никаких необработанных данных. Ниже представлен код класса Program, который является входной точкой при запуске сервера (Рисунок 8). using System; using System.Text; using System.Net; using System.Net.Sockets; namespace Kolosov { class Program { static int port = 8005; // порт для приема входящих запросов 18 static void Main(string[] args) { // получаем адреса для запуска сокета IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), port); // создаем сокет Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { // связываем сокет с локальной точкой, по которой будем принимать данные listenSocket.Bind(ipPoint); // начинаем прослушивание listenSocket.Listen(10); Console.WriteLine("Сервер запущен. Ожидание подключений..."); while (true) { Socket handler = listenSocket.Accept(); // получаем сообщение StringBuilder builder = new StringBuilder(); int bytes = 0; // количество полученных байтов byte[] data = new byte[256]; // буфер для получаемых данных do 19 { bytes = handler.Receive(data); builder.Append(Encoding.Unicode.GetString(data, 0, bytes)); } while (handler.Available > 0); Console.WriteLine(DateTime.Now.ToShortTimeString() + ": " + builder.ToString()); // отправляем ответ string message = "ваше сообщение доставлено"; data = Encoding.Unicode.GetBytes(message); handler.Send(data); // закрываем сокет handler.Shutdown(SocketShutdown.Both); handler.Close(); } } catch (Exception ex) { Console.WriteLine(ex.Message); } } } } 20 Рисунок 8 – Запуск сервера Общая схема работы клиента на сокетах (Рисунок 9): Рисунок 9 – Общая схема работы клиента Для клиента характерно все то же самое, только теперь после создания сокета вызывается метод Connect(), в который передается адрес сервера: IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(address), port); socket.Connect(ipPoint); Клиентская часть написана также на языке C#. using System; using System.Text; 21 using System.Net; using System.Net.Sockets; namespace SocketTcpClient { class Program { // адрес и порт сервера, к которому будем подключаться static int port = 8005; // порт сервера static string address = "127.0.0.1"; // адрес сервера static void Main(string[] args) { try { IPEndPoint ipPoint = new IPEndPoint(IPAddress.Parse(address), port); Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // подключаемся к удаленному хосту socket.Connect(ipPoint); Console.Write("Введите сообщение:"); string message = Console.ReadLine(); byte[] data = Encoding.Unicode.GetBytes(message); socket.Send(data); // получаем ответ data = new byte[256]; // буфер для ответа StringBuilder builder = new StringBuilder(); int bytes = 0; // количество полученных байт 22 do { bytes = socket.Receive(data, data.Length, 0); builder.Append(Encoding.Unicode.GetString(data, 0, bytes)); } while (socket.Available > 0); Console.WriteLine("ответ сервера: " + builder.ToString()); // закрываем сокет socket.Shutdown(SocketShutdown.Both); socket.Close(); } catch(Exception ex) { Console.WriteLine(ex.Message); } Console.Read(); } } } На рисунке 9 отображён полный цикл запроса-ответа клиент-серверного приложения. 23 Рисунок 9 – результат работы программы 2.3 Выводы В результате проделанной работы в данной главе были описаны основные взаимодействия и архитектура клиент-серверного взаимодействия на базе сокетов. Описан процесс взаимодействие клиентского приложения и сервера сервисной службы интернет-провайдера. Представлены диаграммы взаимодействия и последовательности выполнения некоторых запросов. ЗАКЛЮЧЕНИЕ В результате проделанной работы было разработано веб-приложение взаимодействия клиента и сервисной службы интернет провайдера. Подробно рассмотрены процесс разработки приложения, получены навыки и опыт, которые, безусловно, являются ключевыми в динамически развивающейся сфере технологий. 24 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ 1 Эспозито, Дино Microsoft ASP.NET 2.0. Базовый курс / Дино Эспозито. - М.: Русская Редакция, Питер, 2007. - 688 c. 2 Dominick, Baier Developing More–Secure Microsoft ASP.NET 2.0 Applications / Dominick Baier. - Москва: Наука, 2006. - 480 c. 3 Исследование эффективности сетевых протоколов в клиент-серверных приложениях [Электронный ресурс] – http://masters.donntu.org/2017/fknt/sirant/diss/index.htm Режим (дата доступа: обращения: 29.06.2020). 4 Руководство по docker-compose.yml файл [Электронный ресурс] Режим доступа: https://dker.ru/docs/docker-compose/compose-file-reference/ (дата обращения: 23.06.2020). 25