diff --git a/novopolcev_alexander_lab_2/.gitignore b/novopolcev_alexander_lab_2/.gitignore new file mode 100644 index 0000000..49065ec --- /dev/null +++ b/novopolcev_alexander_lab_2/.gitignore @@ -0,0 +1,10 @@ +data/ +result/ +__pycache__/ +*.py[cod] +*.env +*.venv +.env.local +venv/ +env/ +.idea/ \ No newline at end of file diff --git a/novopolcev_alexander_lab_2/README.md b/novopolcev_alexander_lab_2/README.md new file mode 100644 index 0000000..14da49f --- /dev/null +++ b/novopolcev_alexander_lab_2/README.md @@ -0,0 +1,62 @@ +# Лабораторная работа №2 - Разработка простейшего распределённого приложения + +## Задание + +1. Разработать два приложения: + - **app_one**: Ищет в каталоге /var/data файл с наибольшим количеством строк и копирует его содержимое в /var/result/data.txt. + - **app_two**: Ищет наименьшее число из файла /var/result/data.txt и сохраняет количество таких чисел из последовательности в /var/result/result.txt. +2. Разработать файлы сборки Docker для каждого приложения. +3. Собрать файл docker-compose.yml для запуска обоих приложений. +4. Настроить монтирование директорий для обмена данными между контейнерами. +5. Правильно закоммитить решение с использованием .gitignore для исключения лишних файлов. + +## Сборка и запуск: + +В директории, где находится файл docker-compose.yml, выполним команду для сборки и запуска всех контейнеров: + + +docker-compose up --build + + +Эта команда: +1. Собирает все Docker-образы для сервисов. +2. Запускает контейнеры. +3. Автоматически подготавливает данные и выполняет приложения последовательно. + +### Результаты: + +После успешного завершения работы контейнеров можно проверить результаты в папке result: +- **data.txt** — файл, полученный после выполнения первого приложения (содержит копию файла с наибольшим количеством строк из папки data). +![](lab_2.1.png "") +- **result.txt** — файл, полученный после выполнения второго приложения (содержит количество наименьших чисел из файла data.txt). +![](lab_2.2.png "") + +## Описание работы + +### Программы: + +1. **app_one/main.py**: + - Ищет файл с наибольшим количеством строк в каталоге /var/data. + - Копирует содержимое этого файла в /var/result/data.txt. + +2. **app_two/main.py**: + - Читает файл /var/result/data.txt. + - Ищет наименьшее число в файле и возводит его в третью степень. + - Сохраняет результат в файл /var/result/result.txt. + +### Генерация данных: + +Для создания случайных данных был написан скрипт generate_data.py: +- Создает несколько файлов с целыми числами в каталоге /var/data. +- Каждый файл содержит случайные числа, которые будут использоваться первым приложением. + +### Dockerfile: + +Каждое приложение имеет собственный Dockerfile, где указаны шаги для сборки Python-образов и запуска программ. + +## Вывод + +В результате лабораторной работы было создано простейшее распределенное приложение, которое использует Docker и Docker Compose для запуска двух программ, обрабатывающих данные в контейнерах. + +## Видео +https://disk.yandex.ru/i/V7k_SepqnxID5Q diff --git a/novopolcev_alexander_lab_2/app_one/Dockerfile b/novopolcev_alexander_lab_2/app_one/Dockerfile new file mode 100644 index 0000000..dab7528 --- /dev/null +++ b/novopolcev_alexander_lab_2/app_one/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app_one + +COPY main.py /app_one/ + +CMD ["python", "main.py"] diff --git a/novopolcev_alexander_lab_2/app_one/main.py b/novopolcev_alexander_lab_2/app_one/main.py new file mode 100644 index 0000000..1b2d430 --- /dev/null +++ b/novopolcev_alexander_lab_2/app_one/main.py @@ -0,0 +1,38 @@ +import os + +def get_file_with_most_lines(directory): + max_lines = 0 + target_file = "" + + for filename in os.listdir(directory): + filepath = os.path.join(directory, filename) + if os.path.isfile(filepath): + with open(filepath, 'r') as f: + line_count = sum(1 for _ in f) + if line_count > max_lines: + max_lines = line_count + target_file = filename + + return target_file + +def copy_file(src_directory, dest_directory, filename): + src_filepath = os.path.join(src_directory, filename) + dest_filepath = os.path.join(dest_directory, 'data.txt') + + os.makedirs(dest_directory, exist_ok=True) + + with open(src_filepath, 'r') as src_file: + with open(dest_filepath, 'w') as dest_file: + dest_file.write(src_file.read()) + +def main(): + src_directory = '/var/data' + dest_directory = '/var/result' + + target_file = get_file_with_most_lines(src_directory) + if target_file: + copy_file(src_directory, dest_directory, target_file) + print(f"File {target_file} copied to {dest_directory}/data.txt") + +if __name__ == "__main__": + main() diff --git a/novopolcev_alexander_lab_2/app_two/Dockerfile b/novopolcev_alexander_lab_2/app_two/Dockerfile new file mode 100644 index 0000000..8fb663a --- /dev/null +++ b/novopolcev_alexander_lab_2/app_two/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app_two + +COPY main.py /app_two/ + +CMD ["python", "main.py"] diff --git a/novopolcev_alexander_lab_2/app_two/main.py b/novopolcev_alexander_lab_2/app_two/main.py new file mode 100644 index 0000000..d7128c2 --- /dev/null +++ b/novopolcev_alexander_lab_2/app_two/main.py @@ -0,0 +1,32 @@ +import os + +def find_min_and_count(input_filepath): + if not os.path.exists(input_filepath): + raise FileNotFoundError(f"Input file {input_filepath} not found!") + + with open(input_filepath, 'r') as f: + numbers = [int(line.strip()) for line in f.readlines()] + + min_value = min(numbers) + + count = numbers.count(min_value) + + return min_value, count + +def save_result(count, output_filepath): + with open(output_filepath, 'w') as f: + f.write(str(count)) + +def main(): + input_filepath = '/var/result/data.txt' + output_filepath = '/var/result/result.txt' + + try: + min_value, count = find_min_and_count(input_filepath) + save_result(count, output_filepath) + print(f"File ({min_value}) copied to {output_filepath}: {count}") + except FileNotFoundError as e: + print(e) + +if __name__ == "__main__": + main() diff --git a/novopolcev_alexander_lab_2/data_generator/Dockerfile b/novopolcev_alexander_lab_2/data_generator/Dockerfile new file mode 100644 index 0000000..980d2ee --- /dev/null +++ b/novopolcev_alexander_lab_2/data_generator/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /data_generator + +COPY main.py /data_generator/ + +CMD ["python", "main.py"] diff --git a/novopolcev_alexander_lab_2/data_generator/main.py b/novopolcev_alexander_lab_2/data_generator/main.py new file mode 100644 index 0000000..e8f2db5 --- /dev/null +++ b/novopolcev_alexander_lab_2/data_generator/main.py @@ -0,0 +1,29 @@ +import os +import random + + +def generate_random_files(directory, num_files, num_lines_per_file, min_value, max_value): + os.makedirs(directory, exist_ok=True) + + for i in range(num_files): + file_path = os.path.join(directory, f"file_{i + 1}.txt") + with open(file_path, 'w') as f: + for _ in range(num_lines_per_file): + random_number = random.randint(min_value, max_value) + f.write(f"{random_number}\n") + print(f"Generated file: {file_path}") + + +def main(): + data_directory = '/var/data' + num_files = 10 + num_lines_per_file = 12 + min_value = 1 + max_value = 100 + + generate_random_files(data_directory, num_files, num_lines_per_file, min_value, max_value) + print(f"Generated {num_files} files in {data_directory}") + + +if __name__ == "__main__": + main() diff --git a/novopolcev_alexander_lab_2/docker-compose.yml b/novopolcev_alexander_lab_2/docker-compose.yml new file mode 100644 index 0000000..f93eb32 --- /dev/null +++ b/novopolcev_alexander_lab_2/docker-compose.yml @@ -0,0 +1,21 @@ +services: + data_generator: + build: + context: ./data_generator + volumes: + - ./data:/var/data + app_one: + build: + context: ./app_one + volumes: + - ./data:/var/data + - ./result:/var/result + depends_on: + - data_generator + app_two: + build: + context: ./app_two + volumes: + - ./result:/var/result + depends_on: + - app_one diff --git a/novopolcev_alexander_lab_2/lab_2.1.png b/novopolcev_alexander_lab_2/lab_2.1.png new file mode 100644 index 0000000..5de3c7d Binary files /dev/null and b/novopolcev_alexander_lab_2/lab_2.1.png differ diff --git a/novopolcev_alexander_lab_2/lab_2.2.png b/novopolcev_alexander_lab_2/lab_2.2.png new file mode 100644 index 0000000..e50e7d9 Binary files /dev/null and b/novopolcev_alexander_lab_2/lab_2.2.png differ