diff --git a/kadyrov_aydar_lab_2/.gitignore b/kadyrov_aydar_lab_2/.gitignore new file mode 100644 index 0000000..49065ec --- /dev/null +++ b/kadyrov_aydar_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/kadyrov_aydar_lab_2/README.md b/kadyrov_aydar_lab_2/README.md new file mode 100644 index 0000000..0bd615d --- /dev/null +++ b/kadyrov_aydar_lab_2/README.md @@ -0,0 +1,78 @@ +# Лабораторная работа №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 для исключения лишних файлов. + +## Варианты задания: + +1. **app_one**: + - Ищет файл с наибольшим количеством строк в каталоге /var/data. + - Копирует содержимое этого файла в /var/result/data.txt. + +2. **app_two**: + - Читает файл /var/result/data.txt. + - Ищет наименьшее число и сохраняет его третью степень в /var/result/result.txt. + +### Требования: +1. **Docker**: Платформа для контейнеризации приложений. +2. **Docker Compose**: Инструмент для управления многоконтейнерными приложениями на основе файла docker-compose.yml. + +### Сборка и запуск: + +В директории, где находится файл docker-compose.yml, выполним команду для сборки и запуска всех контейнеров: + + +docker-compose up --build + + +Эта команда: +1. Собирает все Docker-образы для сервисов. +2. Запускает контейнеры. +3. Автоматически подготавливает данные и выполняет приложения последовательно. + +### Результаты: + +После успешного завершения работы контейнеров можно проверить результаты в папке result: +- **data.txt** — файл, полученный после выполнения первого приложения (содержит копию файла с наибольшим количеством строк из папки data). +- **result.txt** — файл, полученный после выполнения второго приложения (содержит третью степень наименьшего числа из файла data.txt). + +## Описание работы + +### Программы: + +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://vk.com/video64471408_456239205?list=ln-nzLhpgninZdZBOzarw \ No newline at end of file diff --git a/kadyrov_aydar_lab_2/app_one/Dockerfile b/kadyrov_aydar_lab_2/app_one/Dockerfile new file mode 100644 index 0000000..5378828 --- /dev/null +++ b/kadyrov_aydar_lab_2/app_one/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_2/app_one/main.py b/kadyrov_aydar_lab_2/app_one/main.py new file mode 100644 index 0000000..1b2d430 --- /dev/null +++ b/kadyrov_aydar_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/kadyrov_aydar_lab_2/app_two/Dockerfile b/kadyrov_aydar_lab_2/app_two/Dockerfile new file mode 100644 index 0000000..5378828 --- /dev/null +++ b/kadyrov_aydar_lab_2/app_two/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "main.py"] diff --git a/kadyrov_aydar_lab_2/app_two/main.py b/kadyrov_aydar_lab_2/app_two/main.py new file mode 100644 index 0000000..4c2f88e --- /dev/null +++ b/kadyrov_aydar_lab_2/app_two/main.py @@ -0,0 +1,25 @@ +import os + +def get_largest_number_from_file(filepath): + with open(filepath, 'r') as f: + numbers = [int(line.strip()) for line in f.readlines()] + return max(numbers) + +def save_square_of_number(number, output_filepath): + result = number ** 2 + with open(output_filepath, 'w') as f: + f.write(str(result)) + +def main(): + input_filepath = '/var/result/data.txt' + output_filepath = '/var/result/result.txt' + + if os.path.exists(input_filepath): + largest_number = get_largest_number_from_file(input_filepath) + save_square_of_number(largest_number, output_filepath) + print(f"Largest number squared: {largest_number}^2 saved to {output_filepath}") + else: + print(f"Input file {input_filepath} not found!") + +if __name__ == "__main__": + main() diff --git a/kadyrov_aydar_lab_2/data_generator/Dockerfile b/kadyrov_aydar_lab_2/data_generator/Dockerfile new file mode 100644 index 0000000..b98495c --- /dev/null +++ b/kadyrov_aydar_lab_2/data_generator/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /app + +COPY . /app + +CMD ["python", "generate_data.py"] diff --git a/kadyrov_aydar_lab_2/data_generator/generate_data.py b/kadyrov_aydar_lab_2/data_generator/generate_data.py new file mode 100644 index 0000000..e8f2db5 --- /dev/null +++ b/kadyrov_aydar_lab_2/data_generator/generate_data.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/kadyrov_aydar_lab_2/docker-compose.yml b/kadyrov_aydar_lab_2/docker-compose.yml new file mode 100644 index 0000000..872c5fd --- /dev/null +++ b/kadyrov_aydar_lab_2/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3' +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