🏠 Домашнее задание 3: Python + psutil в Docker

⚡ Суть задания

Создать Dockerfile для Python-приложения (psutil), которое собирает данные о системе и сохраняет результат в output.txt на хосте через volume. Сдать: Dockerfile, output.txt, команды build и run.

  • FROM python:3.12-slimCOPYRUN pipENTRYPOINT ["python3", "memory_info.py"]
  • Запуск: docker run --rm -v "${PWD}/data:/app/data" memory-info-image

Текст задания из LMS

Создать Dockerfile для запуска Python-приложения, которое использует модуль psutil для вывода информации о системе. Приложение должно сохранять результат работы на хостовой машине. Пришлите готовый Dockerfile, файл output.txt и команды создания и запуска docker контейнера.

  1. Создать директорию для проекта.
  2. Сохранить исходный код приложения в файл memory_info.py.
  3. Создать файл requirements.txt для указания зависимостей проекта.
  4. Создать файл Dockerfile.
  5. Использовать официальный образ в качестве базового (например, python:latest).
  6. Установить зависимости при помощи команды в Dockerfile (не забываем скопировать memory_info.py и requirements.txt, используя COPY).
    Выполнить установку зависимостей: RUN python3 -m pip install psutil -U
    Использовать команду для запуска приложения: ENTRYPOINT ["python3", "memory_info.py"]

Код приложения из задания

# memory-info-app/memory_info.py
import psutil
import platform

def get_cpu_usage():
    return psutil.cpu_percent(interval=1)

def get_memory_usage():
    memory = psutil.virtual_memory()
    return {
        'Всего': f'{memory.total / (1024**3):.2f} ГБ',
        'Используется': f'{memory.used / (1024**3):.2f} ГБ',
        'Свободно': f'{memory.available / (1024**3):.2f} ГБ',
        'Процент использования': f'{memory.percent}%'
    }

def main():
    with open('data/output.txt', 'a') as f:
        print("OS: ", platform.platform(), file=f)
        print("OS version: ", platform.version(), file=f)
        print("=== Мониторинг системы ===", file=f)
        print(f"\nЗагрузка CPU: {get_cpu_usage()}%", file=f)
        print("\nИспользование памяти:", file=f)
        for key, value in get_memory_usage().items():
            print(f"{key}: {value}", file=f)

if __name__ == '__main__':
    main()

Подготовка окружения

Что нужно проверить перед началом

# Терминал (PowerShell) — проверяем, что Docker запущен
docker --version
docker info

# Создаём директорию для проекта
mkdir memory-info-app
cd memory-info-app

Структура проекта

# memory-info-app/   ← корень проекта
# ├── Dockerfile
# ├── memory_info.py
# ├── requirements.txt
# └── data/           ← создаётся отдельно на хосте для volume

Пошаговое решение

Шаг 1: Создать файл приложения

Скопируйте код приложения из текста задания выше в файл memory_info.py.

Обратите внимание: приложение открывает файл data/output.txt с режимом 'a' (append — дозаписывать). При каждом запуске данные добавляются в конец файла. Папка data/ должна существовать — она монтируется через volume из хоста.

Шаг 2: Создать requirements.txt

# memory-info-app/requirements.txt
psutil

Шаг 3: Создать Dockerfile

# memory-info-app/Dockerfile

# Официальный образ Python 3.12 slim (меньше, чем python:latest)
FROM python:3.12-slim

# Рабочая директория внутри контейнера
WORKDIR /app

# Сначала копируем только requirements.txt — кеш pip не сбросится при изменении кода
COPY requirements.txt .

# Устанавливаем зависимости
# --no-cache-dir — не сохранять кеш pip внутри образа → меньше размер
RUN pip install --no-cache-dir -r requirements.txt

# Копируем исходный код приложения
COPY memory_info.py .

# Точка входа: всегда запускать именно этот скрипт
ENTRYPOINT ["python3", "memory_info.py"]
Почему ENTRYPOINT, а не CMD? В задании явно сказано использовать ENTRYPOINT ["python3", "memory_info.py"]. ENTRYPOINT фиксирует запускаемый файл — при docker run нельзя случайно заменить скрипт другой командой (только через --entrypoint). Это подходит для контейнера-утилиты, который всегда делает одно конкретное действие.

Шаг 4: Добавить .dockerignore (рекомендуется)

# memory-info-app/.dockerignore
data/
__pycache__
*.pyc
.git
.env

Это исключит папку data/ (с результатами) из контекста сборки — Docker не будет её отправлять в образ.

Шаг 5: Собрать образ

# Терминал (PowerShell) — из папки memory-info-app
docker build -t memory-info-image .

# Проверяем, что образ создан
docker images | findstr memory-info-image

Ожидаемый вывод при сборке:

# [1/4] FROM docker.io/library/python:3.12-slim
# [2/4] WORKDIR /app
# [3/4] RUN pip install --no-cache-dir -r requirements.txt
#       ...Successfully installed psutil-6.x.x
# [4/4] COPY memory_info.py .
# Successfully built xxxxxxxxxx
# Successfully tagged memory-info-image:latest

Шаг 6: Создать папку для данных и запустить контейнер

# Терминал (PowerShell)
# Создаём папку data на хосте (она будет смонтирована в /app/data контейнера)
mkdir data

# Запуск контейнера:
# --rm      — удалить контейнер после завершения (данные остаются в volume)
# -v        — монтировать ./data в /app/data внутри контейнера
docker run --rm -v "${PWD}/data:/app/data" memory-info-image
Почему /app/data? В коде memory_info.py файл открывается как 'data/output.txt'. WORKDIR в Dockerfile — это /app. Значит, приложение пишет в /app/data/output.txt. Именно эту папку мы и монтируем: ./data:/app/data.

Шаг 7: Проверить результат

# Терминал (PowerShell)
# Смотрим содержимое output.txt
type data\output.txt

# Ожидаемый вывод примерно такой:
# OS:  Linux-6.1.0-... (или Windows-...)
# OS version:  #1 SMP ...
# === Мониторинг системы ===
#
# Загрузка CPU: 3.5%
#
# Использование памяти:
# Всего: 7.62 ГБ
# Используется: 4.21 ГБ
# Свободно: 3.41 ГБ
# Процент использования: 55.2%

Итоговые команды для сдачи задания

# memory-info-app/Dockerfile — это и есть Dockerfile для сдачи
# (см. Шаг 3 выше)

# Команда создания образа:
docker build -t memory-info-image .

# Команда запуска контейнера:
docker run --rm -v "${PWD}/data:/app/data" memory-info-image

# Файл data/output.txt генерируется автоматически

Проверка в VS Code

Открыть проект

  1. Откройте VS Code: code . из папки memory-info-app
  2. В терминале VS Code (Ctrl+`) выполните команды из шагов 5–7.
  3. Файл data/output.txt появится в проводнике слева — кликните, чтобы открыть.

Отладка через терминал

# Если контейнер не запускается — проверьте образ
docker images

# Если output.txt не создался — проверьте монтирование
docker run --rm -v "${PWD}/data:/app/data" memory-info-image
# Убедитесь, что папка data/ существует до запуска!

# Посмотреть логи последнего запуска
docker logs $(docker ps -ql)

# Войти в контейнер интерактивно для отладки
docker run --rm -it --entrypoint bash memory-info-image
# Внутри можно запустить python3 memory_info.py вручную

Распространённые проблемы

  • FileNotFoundError: [Errno 2] No such file or directory: 'data/output.txt' — папка data/ не смонтирована или не создана на хосте. Создайте её: mkdir data и добавьте флаг -v "${PWD}/data:/app/data".
  • ModuleNotFoundError: No module named 'psutil' — зависимости не установились. Пересоберите образ: docker build --no-cache -t memory-info-image .
  • Пустой output.txt — приложение запустилось, но не записало данные. Проверьте права доступа к папке data/: она должна быть доступна для записи.

Связь с другими разделами урока

← К оглавлению урока