DAS_2023_1/kochkareva_elizaveta_lab_2/README.md
2024-01-19 11:35:58 +04:00

7.8 KiB
Raw Blame History

Лабораторная работа 2.

Задание

Цель: изучение техники создания простого распределённого приложения.

Задачи:

  • Разработать два приложения такие, что результат первого является исходными данными для второго.
  • Изучить файлы сборки образов docker и разработать их для созданных приложений.
  • Собрать файл docker-compose.yml для запуска приложений.
  • Разобраться с монтированием каталогов из хост-системы.

Вариант:

  • Ищет в каталоге /var/data файл с самым коротким названием и перекладывает его в /var/result/data.txt.
  • Сохраняет произведение первого и последнего числа из файла /var/data/data.txt в /var/result/result.txt.

Как запустить лабораторную работу

В директории с файлом характеристик docker-compose.yaml выполнить команду:

docker-compose -f docker-compose.yaml up

Описание лабораторной работы

Входные данный

В качестве входных данных представлены следующие файлы с соответствующим содержанием:

deadlock - file1: 9 5 0 1
diamond - file2: 3 5 8
himera - file3: 4 6 6
kjjuriositi - file4: 3 5 3
nitric-oxide - file5: 3 1 7
V3001TH - file6: 7 2 6
za - file7: 2 4 4

Первое приложение

Первое приложение выполняет задачу: Ищет в каталоге /var/data файл с самым коротким названием и перекладывает его в /var/result/data.txt.

Для этого напишем следующий код:

File dataDir = new File("/var/data");
File resultDir = new File("/var/result");
// Получаем все файлы в каталоге /var/data
File[] files = dataDir.listFiles();
if (files != null && files.length > 0) {
    // Ищем файл с самым коротким названием
    File shortestFileName = files[0];
    for (File file : files) {
        if (file.getName().length() < shortestFileName.getName().length()) {
            shortestFileName = file;
        }
    }
    // Перекладываем файл в /var/result/data.txt
    File destination = new File(resultDir, "data.txt");
    try {
        Files.move(shortestFileName.toPath(), destination.toPath(), StandardCopyOption.REPLACE_EXISTING);
        System.out.println("Файл успешно перемещен.");
    } catch (IOException e) {
        System.out.println("Ошибка при перемещении файла: " + e.getMessage());
    }
} else {
    System.out.println("В каталоге /var/data нет файлов.");
}

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

# Используем образ Java для компиляции и запуска кода
FROM openjdk:11
# Создание директорий для файлов
RUN ["mkdir", "/var/data"]
RUN ["mkdir", "/var/result"]
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем исходный код в контейнер
COPY src/Main.java .
# Компилируем исходный код
RUN javac Main.java
# Устанавливаем команду запуска приложения
CMD ["java", "Main"]

Второе приложение

Второе приложение выполняет задачу: Сохраняет произведение первого и последнего числа из файла /var/data/data.txt в /var/result/result.txt.

Для этого напишем следующий код:

String inputFile = "/var/result/data.txt";
String outputFile = "/var/result/result.txt";

try (BufferedReader reader = new BufferedReader(new FileReader(inputFile));
    BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) {

    String line;
    while ((line = reader.readLine()) != null) {
        String[] numbers = line.split("\\s+");

        if (numbers.length > 0) {
            int firstNumber = Integer.parseInt(numbers[0]);
            int lastNumber = Integer.parseInt(numbers[numbers.length - 1]);
            int result = firstNumber * lastNumber;

            writer.write(String.valueOf(result));
            writer.newLine();
        }
    }
} catch (IOException e) {
    e.printStackTrace();
}

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

# Используем образ Java для компиляции и запуска кода
FROM openjdk:11
# Создание директорий для файлов
RUN ["mkdir", "/var/data"]
RUN ["mkdir", "/var/result"]
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем исходный код в контейнер
COPY src/Main.java .
# Компилируем исходный код
RUN javac Main.java
# Устанавливаем команду запуска приложения
CMD ["java", "Main"]

Разворачивание сервисов

Создадим файл docker-compose.yml, который определяет настройки для запуска нескольких сервисов в Docker с использованием Docker Compose.

Первый блок будет определять первый сервис worker-1. Он будет создан на основе контекста сборки /worker-1 и файла Dockerfile. Затем, указанные тома (volumes) будут примонтированы в контейнере. В данном случае, директория .\data на хосте будет примонтирована в /var/data внутри контейнера, а директория .\result на хосте будет примонтирована в /var/result внутри контейнера.

  worker-1:
    build:
      context: /worker-1
      dockerfile: Dockerfile
    volumes:
      - .\data:/var/data
      - .\result:/var/result

Второй блок будет определять второй сервис worker-2. Он зависит от сервиса worker-1, поэтому worker-1 будет запущен перед worker-2. Затем, он также будет создан на основе контекста сборки /worker-2 и файла Dockerfile. Аналогично, указанные тома будут примонтированы в контейнере.

  worker-2:
    depends_on:
      - worker-1
    build:
      context: /worker-2
      dockerfile: Dockerfile
    volumes:
      - .\result:/var/data
      - .\result:/var/result

Запуск

Сборка docker-compose

Первое приложение

Второе приложение

Файлы директории data:

deadlock - file1: 9 5 0 1
diamond - file2: 3 5 8
himera - file3: 4 6 6
kjjuriositi - file4: 3 5 3
nitric-oxide - file5: 3 1 7
V3001TH - file6: 7 2 6
za - file7: 2 4 4

Файлы директории result:

data: 2 4 4
result: 8

Видео

https://disk.yandex.ru/i/dFIB-vOqlAip9g