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

194 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лабораторная работа 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.
Для этого напишем следующий код:
```java
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*, который используется для создания образа контейнера данного приложения.
```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.
Для этого напишем следующий код:
```java
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*, который используется для создания образа контейнера данного приложения.
```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 внутри контейнера.
```dockerfile
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. Аналогично, указанные тома будут примонтированы в контейнере.
```dockerfile
worker-2:
depends_on:
- worker-1
build:
context: /worker-2
dockerfile: Dockerfile
volumes:
- .\result:/var/data
- .\result:/var/result
```
### Запуск
![Сборка docker-compose](LaunchingServices.jpg)
![Первое приложение](FirstApp.jpg)
![Второе приложение](SecondApp.jpg)
Файлы директории 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