diff --git a/haliullov_kamil_lab_2/.gitignore b/haliullov_kamil_lab_2/.gitignore new file mode 100644 index 0000000..49065ec --- /dev/null +++ b/haliullov_kamil_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/haliullov_kamil_lab_2/README.md b/haliullov_kamil_lab_2/README.md new file mode 100644 index 0000000..9569de0 --- /dev/null +++ b/haliullov_kamil_lab_2/README.md @@ -0,0 +1,44 @@ +# Лабораторная работа №2 - Разработка простейшего распределённого приложения + +## Задание + +1. Разработать два приложения: + - **OneApp**: Берёт из каталога /var/data случайный файл и перекладывает его в /var/result/data.txt. + - **TwoApp**: Сохраняет произведение первого и последнего числа из файла /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). + +- **result.txt** — файл, полученный после выполнения второго приложения (содержит произведение первого и последнего чисел из файла data.txt). + + +### Генерация данных: + +Для создания случайных данных был написан скрипт generate_data.py: +- Создает несколько файлов с целыми числами в каталоге /var/data. +- Каждый файл содержит случайные числа, которые будут использоваться первым приложением. + +### Dockerfile: + +Каждое приложение имеет собственный Dockerfile, где указаны шаги для сборки Python-образов и запуска программ. + +## Видео +https://disk.yandex.ru/i/r1UsIUdnP2BdeQ diff --git a/haliullov_kamil_lab_2/datagenerator/Dockerfile b/haliullov_kamil_lab_2/datagenerator/Dockerfile new file mode 100644 index 0000000..6babcbc --- /dev/null +++ b/haliullov_kamil_lab_2/datagenerator/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /datagenerator + +COPY generate_data.py /datagenerator/ + +CMD ["python", "generate_data.py"] diff --git a/haliullov_kamil_lab_2/datagenerator/generate_data.py b/haliullov_kamil_lab_2/datagenerator/generate_data.py new file mode 100644 index 0000000..e8f2db5 --- /dev/null +++ b/haliullov_kamil_lab_2/datagenerator/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/haliullov_kamil_lab_2/docker-compose.yml b/haliullov_kamil_lab_2/docker-compose.yml new file mode 100644 index 0000000..6c7163e --- /dev/null +++ b/haliullov_kamil_lab_2/docker-compose.yml @@ -0,0 +1,21 @@ +services: + datagenerator: + build: + context: ./datagenerator + volumes: + - ./data:/var/data + oneapp: + build: + context: ./oneapp + volumes: + - ./data:/var/data + - ./result:/var/result + depends_on: + - datagenerator + twoapp: + build: + context: ./twoapp + volumes: + - ./result:/var/result + depends_on: + - oneapp diff --git a/haliullov_kamil_lab_2/oneapp/Dockerfile b/haliullov_kamil_lab_2/oneapp/Dockerfile new file mode 100644 index 0000000..dbe7cdc --- /dev/null +++ b/haliullov_kamil_lab_2/oneapp/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /oneapp + +COPY main.py /oneapp/ + +CMD ["python", "main.py"] diff --git a/haliullov_kamil_lab_2/oneapp/main.py b/haliullov_kamil_lab_2/oneapp/main.py new file mode 100644 index 0000000..6072760 --- /dev/null +++ b/haliullov_kamil_lab_2/oneapp/main.py @@ -0,0 +1,33 @@ +import os +import shutil +import random + +def select_random_file(directory): + files = os.listdir(directory) + if not files: + raise FileNotFoundError("Каталог пустой") + + random_file = random.choice(files) + return os.path.join(directory, random_file) + +def copy_file_to_destination(source_file, destination_folder, new_filename="data.txt"): + destination_path = os.path.join(destination_folder, new_filename) + shutil.copy(source_file, destination_path) + +def main(): + input_directory = "/var/data" + output_directory = "/var/result" + + try: + # Выбор случайного файла + random_file_path = select_random_file(input_directory) + + # Копирование файла в целевой каталог + copy_file_to_destination(random_file_path, output_directory) + + print(f"Копирован файл: {random_file_path} в {os.path.join(output_directory, 'data.txt')}") + except FileNotFoundError as e: + print(e) + +if __name__ == "__main__": + main() diff --git a/haliullov_kamil_lab_2/twoapp/Dockerfile b/haliullov_kamil_lab_2/twoapp/Dockerfile new file mode 100644 index 0000000..a19f731 --- /dev/null +++ b/haliullov_kamil_lab_2/twoapp/Dockerfile @@ -0,0 +1,7 @@ +FROM python:3.9-slim + +WORKDIR /twoapp + +COPY main.py /twoapp/ + +CMD ["python", "main.py"] diff --git a/haliullov_kamil_lab_2/twoapp/main.py b/haliullov_kamil_lab_2/twoapp/main.py new file mode 100644 index 0000000..b4fda12 --- /dev/null +++ b/haliullov_kamil_lab_2/twoapp/main.py @@ -0,0 +1,37 @@ +import os + +def read_numbers_from_file(file_path): + if not os.path.exists(file_path): + raise FileNotFoundError(f"Файл {file_path} не найден!") + + with open(file_path, 'r') as f: + lines = f.readlines() + + # Получаем первое и последнее число из списка строк + first_number = int(lines[0].strip()) + last_number = int(lines[-1].strip()) + + return first_number, last_number + +def calculate_product(first_number, last_number): + product = first_number * last_number + return product + +def write_result(product, output_filepath): + with open(output_filepath, 'w') as f: + f.write(str(product)) + +def main(): + input_filepath = '/var/result/data.txt' # Исходный файл + output_filepath = '/var/result/result.txt' # Результирующий файл + + try: + first_number, last_number = read_numbers_from_file(input_filepath) + product = calculate_product(first_number, last_number) + write_result(product, output_filepath) + print(f"Произведение первого и последнего числа сохранено в {output_filepath}") + except FileNotFoundError as e: + print(e) + +if __name__ == "__main__": + main()