diff --git a/alkin_ivan_lab_2/.gitignore b/alkin_ivan_lab_2/.gitignore new file mode 100644 index 0000000..a96dde0 --- /dev/null +++ b/alkin_ivan_lab_2/.gitignore @@ -0,0 +1,10 @@ +# .gitignore +__pycache__/ +*.pyc +*.pyo +*.pyd +*.db +*.log +*.bak +*.swp +*.swo diff --git a/alkin_ivan_lab_2/README.md b/alkin_ivan_lab_2/README.md new file mode 100644 index 0000000..7ec720f --- /dev/null +++ b/alkin_ivan_lab_2/README.md @@ -0,0 +1,89 @@ +Для выполнения второй лабораторной работы по созданию распределённого приложения с использованием Docker и Docker Compose, давайте разберем все этапы, шаг за шагом. Я предлагаю реализовать вариант программы 1 и программу 2 следующим образом: + +### 1. Вариант программы 1 +Программа будет искать в каталоге `/var/data` файл с наибольшим количеством строк и перекладывать его в `/var/result/data.txt`. + +### 2. Вариант программы 2 +Программа будет искать наименьшее число из файла `/var/data/data.txt` и сохранять его третью степень в файл `/var/result/result.txt`. + +### Структура проекта + +1. `moiseev-vv-lab_2/worker-1`: Программа для нахождения файла с наибольшим количеством строк. +2. `moiseev-vv-lab_2/worker-2`: Программа для нахождения минимального числа в файле и записи его третьей степени. + +### Шаги реализации: + +#### 1. Реализация программы 1 +```python + + +#### 2. Реализация программы 2 +```python + + + +Для обоих приложений создадим Dockerfile. Вот пример для **worker-1**: + + + +Пояснение: +- **Stage 1**: Мы используем `python:3.10-slim` как образ для сборки, где копируем файл `main.py` и устанавливаем зависимости, если это необходимо. +- **Stage 2**: В этом слое мы копируем скомпилированные файлы из предыдущего этапа и определяем команду для запуска приложения. + +Аналогичный Dockerfile будет для **worker-2**. + +### Docker Compose файл + +Теперь нужно настроить файл `docker-compose.yml`, который позволит запустить оба приложения: + + + +Пояснение: +- **services**: Мы объявляем два сервиса — `worker-1` и `worker-2`. +- **build**: Указываем контекст сборки для каждого сервиса (директории, где находятся Dockerfile и код). +- **volumes**: Монтируем локальные директории `./data` и `./result` в контейнеры, чтобы обмениваться файлами между сервисами. +- **depends_on**: Задаем зависимость `worker-2` от `worker-1`, чтобы второй сервис запускался только после первого. + +### .gitignore + +Для предотвращения попадания ненужных файлов в репозиторий, добавляем файл `.gitignore`. Пример для Python проектов: + +``` +# .gitignore +__pycache__/ +*.pyc +*.pyo +*.pyd +*.db +*.log +*.bak +*.swp +*.swo +``` + +### Шаги для сборки и запуска + +1. Склонировать репозиторий и перейти в директорию с лабораторной работой: + ```bash + git clone <репозиторий> + cd moiseev-vv-lab_2 + ``` + +2. Скопировать файлы для `worker-1` и `worker-2` в соответствующие папки. + +3. Создать файл `docker-compose.yml`. + +4. Запустить приложение с помощью команды: + ```bash + docker-compose up --build + ``` + +5. Проверить вывод, результаты должны быть в директориях `./data` и `./result`. + +### Заключение + +Это пример, как можно реализовать простейшее распределённое приложение с использованием Docker. Первое приложение генерирует данные для второго, который обрабатывает их и записывает результат в файл. Docker и Docker Compose позволяют легко управлять и изолировать каждое приложение.ker Compose для запуска двух программ, обрабатывающих данные в контейнерах. + +## Видео ВК + +https://vk.com/video64471408_456239205?list=ln-nzLhpgninZdZBOzarw \ No newline at end of file diff --git a/alkin_ivan_lab_2/data_generator/Dockerfile b/alkin_ivan_lab_2/data_generator/Dockerfile new file mode 100644 index 0000000..b98495c --- /dev/null +++ b/alkin_ivan_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/alkin_ivan_lab_2/data_generator/generate_data.py b/alkin_ivan_lab_2/data_generator/generate_data.py new file mode 100644 index 0000000..e8f2db5 --- /dev/null +++ b/alkin_ivan_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/alkin_ivan_lab_2/docker-compose.yml b/alkin_ivan_lab_2/docker-compose.yml new file mode 100644 index 0000000..9fedd96 --- /dev/null +++ b/alkin_ivan_lab_2/docker-compose.yml @@ -0,0 +1,18 @@ +# docker-compose.yml + +services: + worker-1: + build: + context: ./worker-1 + volumes: + - ./data:/var/data + - ./result:/var/result + depends_on: + - worker-2 + + worker-2: + build: + context: ./worker-2 + volumes: + - ./data:/var/data + - ./result:/var/result diff --git a/alkin_ivan_lab_2/worker-1/Dockerfile b/alkin_ivan_lab_2/worker-1/Dockerfile new file mode 100644 index 0000000..d542d79 --- /dev/null +++ b/alkin_ivan_lab_2/worker-1/Dockerfile @@ -0,0 +1,14 @@ +# worker-1/Dockerfile +# Stage 1: Build the application +FROM python:3.10-slim as builder + +WORKDIR /app +COPY ./main.py . + +# Stage 2: Set up the runtime environment +FROM python:3.10-slim + +WORKDIR /app +COPY --from=builder /app/main.py . + +CMD ["python", "main.py"] diff --git a/alkin_ivan_lab_2/worker-1/main.py b/alkin_ivan_lab_2/worker-1/main.py new file mode 100644 index 0000000..d97a463 --- /dev/null +++ b/alkin_ivan_lab_2/worker-1/main.py @@ -0,0 +1,35 @@ +# worker-1/main.py +import os + + +def find_file_with_most_lines(directory): + files = os.listdir(directory) + max_lines = 0 + target_file = None + for filename in files: + filepath = os.path.join(directory, filename) + if os.path.isfile(filepath): + with open(filepath, 'r') as file: + lines = file.readlines() + if len(lines) > max_lines: + max_lines = len(lines) + target_file = filepath + return target_file + + +def main(): + source_directory = '/var/data' + result_file = '/var/result/data.txt' + + file_to_copy = find_file_with_most_lines(source_directory) + + if file_to_copy: + with open(file_to_copy, 'r') as source, open(result_file, 'w') as dest: + dest.writelines(source.readlines()) + print(f"File with the most lines: {file_to_copy} copied to {result_file}") + else: + print("No files found in the source directory.") + + +if __name__ == "__main__": + main() diff --git a/alkin_ivan_lab_2/worker-2/Dockerfile b/alkin_ivan_lab_2/worker-2/Dockerfile new file mode 100644 index 0000000..d542d79 --- /dev/null +++ b/alkin_ivan_lab_2/worker-2/Dockerfile @@ -0,0 +1,14 @@ +# worker-1/Dockerfile +# Stage 1: Build the application +FROM python:3.10-slim as builder + +WORKDIR /app +COPY ./main.py . + +# Stage 2: Set up the runtime environment +FROM python:3.10-slim + +WORKDIR /app +COPY --from=builder /app/main.py . + +CMD ["python", "main.py"] diff --git a/alkin_ivan_lab_2/worker-2/main.py b/alkin_ivan_lab_2/worker-2/main.py new file mode 100644 index 0000000..acb7ed8 --- /dev/null +++ b/alkin_ivan_lab_2/worker-2/main.py @@ -0,0 +1,23 @@ +# worker-2/main.py +def find_min_number(filename): + with open(filename, 'r') as file: + numbers = [int(line.strip()) for line in file.readlines()] + min_number = min(numbers) + return min_number + + +def main(): + input_file = '/var/data/data.txt' + output_file = '/var/result/result.txt' + + min_number = find_min_number(input_file) + result = min_number ** 3 # Cube of the minimum number + + with open(output_file, 'w') as file: + file.write(str(result)) + + print(f"Minimum number's cube: {result} written to {output_file}") + + +if __name__ == "__main__": + main()