From adac0967263c202380a96f087cefa9e9b669fb9d Mon Sep 17 00:00:00 2001 From: igors <igors-2011@mail.ru> Date: Sat, 14 Dec 2024 22:45:25 +0400 Subject: [PATCH] / --- .idea/misc.xml | 5 ++- melnikov_igor_lab_2/README.md | 44 +++++++++++++++++++ melnikov_igor_lab_2/app_1/Dockerfile | 13 ++++++ melnikov_igor_lab_2/app_1/app.py | 28 ++++++++++++ melnikov_igor_lab_2/app_2/Dockerfile | 8 ++++ melnikov_igor_lab_2/app_2/app.py | 27 ++++++++++++ melnikov_igor_lab_2/docker-compose.yml | 27 ++++++++++++ melnikov_igor_lab_2/generator/Dockerfile | 7 +++ .../generator/generate_files.py | 31 +++++++++++++ 9 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 melnikov_igor_lab_2/README.md create mode 100644 melnikov_igor_lab_2/app_1/Dockerfile create mode 100644 melnikov_igor_lab_2/app_1/app.py create mode 100644 melnikov_igor_lab_2/app_2/Dockerfile create mode 100644 melnikov_igor_lab_2/app_2/app.py create mode 100644 melnikov_igor_lab_2/docker-compose.yml create mode 100644 melnikov_igor_lab_2/generator/Dockerfile create mode 100644 melnikov_igor_lab_2/generator/generate_files.py diff --git a/.idea/misc.xml b/.idea/misc.xml index ae8ddd2..c023adf 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <project version="4"> - <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.9 (tukaeva_alfiya_lab_4)" project-jdk-type="Python SDK" /> + <component name="Black"> + <option name="sdkName" value="Python 3.12 (DAS_2024_1)" /> + </component> + <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.12 (DAS_2024_1)" project-jdk-type="Python SDK" /> </project> \ No newline at end of file diff --git a/melnikov_igor_lab_2/README.md b/melnikov_igor_lab_2/README.md new file mode 100644 index 0000000..563d182 --- /dev/null +++ b/melnikov_igor_lab_2/README.md @@ -0,0 +1,44 @@ +# Лабораторная работа №2 - Разработка простейшего распределённого приложения + +## Задание + +* Разработать два приложения такие, что результат первого является исходными данными для второго. +* Изучить файлы сборки образов ```docker``` и разработать их для созданных приложений и правильно закоммитить решение +* Собрать файл ```docker-compose.yml``` для запуска приложений. + +### Варианты задания: + 1. Первое приложение берёт из каталога /var/data случайный файл и перекладывает его в /var/result/data.txt + + 2. Второе приложение сохраняет произведение первого и последнего числа из файла /var/result/data.txt в /var/result/result.txt + +## Запуск работы программы + +1. Убедиться, что установлены необходимые технологии: + - Docker: Платформа для контейнеризации приложений. + - Docker Compose: Инструмент для запуска много контейнерных приложений на основе `docker-compose.yaml`. Обычно поставляется вместе с Docker. Чтобы проверить, установлена ли утилита, нужно запустить команду: +```bash + docker-compose --version +``` + +2. В директории, где находится файл `docker-compose.yaml`, выполнить следующую команду для запуска всех сервисов: +```bash + docker-compose up --build +``` +Эта команда сначала выполнит сборку, а затем запустит контейнеры. + +3. После успешного запуска можно перейти в каталог проекта и увидеть папку data со сгенерированными файлами и папку result, в которой два текстовых файла: + - data.txt - файл, полученный после выполнения первой программы. + - result.txt -файл, полученный после выполнения второй программы. + +## Описание работы: + +1. **Генератор файлов** + generate_files.py, генерирует случайные файлы с числами и сохраняет их в папке data. +2. **Первое приложение** + app.py, случайным образом получает один файл из папки data и копирует его содержимое в result/data.txt. +3. **Второе приложение** + app.py, находит произведение первого и последнего чисел из result/data.txt и записывает в result/result.txt. +4. **Файла docker-compose.yml** + docker-compose.yml построчно описан в комментариях в коде. + +Файл Docker построчно описан в коде на примере Docker первого сервиса app_1. \ No newline at end of file diff --git a/melnikov_igor_lab_2/app_1/Dockerfile b/melnikov_igor_lab_2/app_1/Dockerfile new file mode 100644 index 0000000..007eb06 --- /dev/null +++ b/melnikov_igor_lab_2/app_1/Dockerfile @@ -0,0 +1,13 @@ +# Указываем базовый образ для Docker +#slim означает, что это более компактный, содержащий только основные компоненты Python, что уменьшает размер образа +FROM python:3.9-slim + +# Устанавливаем рабочую директорию внутри контейнера Docker в /app. +# Все последующие команды в Dockerfile будут выполняться в этой директории. +WORKDIR /app + +# Перемещаем файл в контейнер +COPY app.py /app/ + +# Указываем команду, которая будет выполняться при запуске контейнера +CMD ["python", "app.py"] diff --git a/melnikov_igor_lab_2/app_1/app.py b/melnikov_igor_lab_2/app_1/app.py new file mode 100644 index 0000000..1994c5c --- /dev/null +++ b/melnikov_igor_lab_2/app_1/app.py @@ -0,0 +1,28 @@ +import os +import random + +def find_shortest_filename(source_dir, result_file): + # Проверяем есть ли папка result, если нет - создаем + result_dir = os.path.dirname(result_file) + if not os.path.exists(result_dir): + os.makedirs(result_dir) + print(f"Created directory {result_dir}") + + files = [f for f in os.listdir(source_dir) if os.path.isfile(os.path.join(source_dir, f))] + + if not files: + print(f"No files found in {source_dir}") + return + + # Выбор случайного файла + random_file = random.choice(files) + random_file_path = os.path.join(source_dir, random_file) + + # Копируем файл в result/data.txt., если файл уже есть перезаписываем + with open(random_file_path, 'r') as f_in, open(result_file, 'w') as f_out: + f_out.write(f_in.read()) + + print(f"Moved {random_file} to {result_file}") + +if __name__ == "__main__": + find_shortest_filename('/var/data', '/var/result/data.txt') diff --git a/melnikov_igor_lab_2/app_2/Dockerfile b/melnikov_igor_lab_2/app_2/Dockerfile new file mode 100644 index 0000000..2e497ae --- /dev/null +++ b/melnikov_igor_lab_2/app_2/Dockerfile @@ -0,0 +1,8 @@ +# См. описание Dockerfile для первого приложения app_1 +FROM python:3.9-slim + +WORKDIR /app + +COPY app.py /app/ + +CMD ["python", "app.py"] diff --git a/melnikov_igor_lab_2/app_2/app.py b/melnikov_igor_lab_2/app_2/app.py new file mode 100644 index 0000000..75222e2 --- /dev/null +++ b/melnikov_igor_lab_2/app_2/app.py @@ -0,0 +1,27 @@ +import os + +def multiply_first_and_last(input_file, output_file): + # Проверяем, существует файл data.txt + if not os.path.exists(input_file): + print(f"File {input_file} does not exist.") + return + + # Считываем содержимое файла + with open(input_file, 'r') as f: + numbers = [int(line.strip()) for line in f.readlines()] + + if numbers: + first_number = numbers[0] + last_number = numbers.pop() + result = first_number * last_number + + # Записываем полученный результата в result.txt + with open(output_file, 'w') as f_out: + f_out.write(str(result)) + + print(f"Saved {first_number}х{last_number} to {output_file}") + else: + print(f"No numbers found in {input_file}") + +if __name__ == "__main__": + multiply_first_and_last('/var/result/data.txt', '/var/result/result.txt') diff --git a/melnikov_igor_lab_2/docker-compose.yml b/melnikov_igor_lab_2/docker-compose.yml new file mode 100644 index 0000000..c516177 --- /dev/null +++ b/melnikov_igor_lab_2/docker-compose.yml @@ -0,0 +1,27 @@ +services: +# сервис, отвечающий за генерацию файлов + generator: + build: + context: ./generator # путь к директории с Dockerfile для генерации + volumes: + - ./data:/var/data # монтирование локальной директории ./data в директорию /var/data внутри контейнера + entrypoint: python generate_files.py # запуск скрипта генерации + + # Первый сервис, получающий случайный файл + app_1: + build: + context: ./app_1 # путь к директории с Dockerfile для первого сервиса + volumes: + - ./data:/var/data # Монтирование локальной директории data в /var/data + - ./result:/var/result # Монтирование локальной директории data в /var/result + depends_on: # Указывает, что первый сервис зависит от генератора + - generator + + # Второй сервис, считающий произведение первого и последнего чисел из файла + app_2: + build: + context: ./app_2 # путь к директории с Dockerfile для второго сервиса + volumes: + - ./result:/var/result # Монтирование локальной директории data в /var/result + depends_on: # Указывает, что второй сервис зависит от первого + - app_1 \ No newline at end of file diff --git a/melnikov_igor_lab_2/generator/Dockerfile b/melnikov_igor_lab_2/generator/Dockerfile new file mode 100644 index 0000000..5c924e5 --- /dev/null +++ b/melnikov_igor_lab_2/generator/Dockerfile @@ -0,0 +1,7 @@ +# См. описание Dockerfile для первого приложения app_1 +FROM python:3.9-slim + +WORKDIR /app +COPY generate_files.py /app/ + +CMD ["python", "generate_files.py"] \ No newline at end of file diff --git a/melnikov_igor_lab_2/generator/generate_files.py b/melnikov_igor_lab_2/generator/generate_files.py new file mode 100644 index 0000000..2db8ac7 --- /dev/null +++ b/melnikov_igor_lab_2/generator/generate_files.py @@ -0,0 +1,31 @@ +import os +import random +import string + +def generate_random_filename(length): + return ''.join(random.choices(string.ascii_lowercase + string.digits, k=length)) + '.txt' + +def generate_data_files(directory, num_files, min_lines, max_lines): + # Создание директории, если таковой не существует + if not os.path.exists(directory): + os.makedirs(directory) + + # Проверка, пустая ли директория + if os.listdir(directory): + print(f"{directory} is not empty, skipping file generation.") + return + + # Генерация файлов + for _ in range(num_files): + file_name = generate_random_filename(random.randint(1, 20)) + file_path = os.path.join(directory, file_name) + + with open(file_path, 'w') as f: + num_lines = random.randint(min_lines, max_lines) + for _ in range(num_lines): + f.write(f"{random.randint(1, 1000)}\n") + + print(f"Generated file: {file_path}") + +if __name__ == "__main__": + generate_data_files('/var/data', num_files=random.randint(5, 15), min_lines=1, max_lines=50)