# Ручное развертывание контейнеров ## Введение * **Контекст:** Развертывание Docker-контейнеров без использования оркестраторов (Kubernetes, Docker Swarm) или инструментов композиции (Docker Compose). * **Сценарии использования:** * Простые одноконтейнерные приложения. * Тестирование и отладка. * Обучение основам работы с Docker. * Среды, где оркестрация избыточна или невозможна. * **Основные инструменты:** Командная строка Docker (`docker`). ## Этапы ручного развертывания контейнера 1. **Подготовка образа:** Убедитесь, что необходимый Docker-образ доступен локально. * **Проверка локальных образов:** `docker images` * **Загрузка образа из реестра (например, Docker Hub):** `docker pull <имя_образа>[:<тег>]` 2. **Запуск контейнера (`docker run`):** Создание и запуск экземпляра образа. Необходимо настроить различные параметры запуска. ## Параметры команды `docker run` (ключевые для ручного развертывания) * **`--name <имя_контейнера>`:** Присваивает имя контейнеру для удобного управления. Если не указано, Docker генерирует случайное имя. * **`-d` или `--detach`:** Запускает контейнер в фоновом режиме (detached). Контейнер продолжает работать после закрытия терминала. * **`-p` или `--publish [hostPort:]containerPort[/tcp|udp]`:** Публикует порты контейнера на хостовой машине, делая приложение доступным извне. * `hostPort`: Порт на хостовой машине (опционально). Если не указан, Docker выберет случайный свободный порт. * `containerPort`: Порт, который слушает приложение внутри контейнера (объявлен в `EXPOSE` Dockerfile или известен разработчику). * `/tcp` или `/udp`: Протокол (по умолчанию TCP). * **Примеры:** * `docker run -p 80:80 nginx` (пробросить порт 80 контейнера на порт 80 хоста) * `docker run -p 8080:80 nginx` (пробросить порт 80 контейнера на порт 8080 хоста) * `docker run -p 127.0.0.1:8080:80 nginx` (пробросить порт 80 контейнера на порт 8080 хоста только на локальном интерфейсе) * **`-v` или `--volume [host_path:]container_path[:ro|rw]` или `--volume <имя_тома>:<путь_в_контейнере>[:ro|rw]`:** Монтирует тома для обеспечения постоянного хранения данных или обмена файлами. * **Bind mounts (`host_path:container_path`):** Связывает каталог или файл на хостовой машине с каталогом внутри контейнера. * `host_path`: Абсолютный путь к каталогу или файлу на хосте. * `container_path`: Абсолютный путь к каталогу внутри контейнера. * `:ro`: Монтирование только для чтения (read-only). * `:rw`: Монтирование для чтения и записи (read-write - по умолчанию). * **Пример:** `docker run -v /data:/var/lib/mysql mysql` (смонтировать каталог `/data` хоста в `/var/lib/mysql` контейнера) * **Named volumes (`<имя_тома>:<путь_в_контейнере>`):** Использует именованные тома, созданные Docker. * `<имя_тома>`: Имя созданного тома (например, `my_db_data`). * `container_path`: Абсолютный путь к каталогу внутри контейнера. * **Пример:** `docker run -v my_db_data:/var/lib/postgresql/data postgres` * **`-e` или `--env `:** Устанавливает переменные окружения внутри контейнера. * **Пример:** `docker run -e POSTGRES_PASSWORD=mysecretpassword postgres` * **`--network <имя_сети>`:** Подключает контейнер к указанной Docker-сети. По умолчанию контейнеры подключаются к сети `bridge`. * **Создание сетей:** `docker network create <имя_сети>` * **Пример:** `docker run --network my-app-network my-app` * **`--restart <политика>`:** Определяет политику перезапуска контейнера при сбое (`no`, `on-failure[:max-retries]`, `always`, `unless-stopped`). * **Пример:** `docker run --restart always my-web-app` (всегда перезапускать контейнер, если он останавливается) * **`--rm`:** Автоматически удаляет контейнер после его остановки. Полезно для временных контейнеров. * **Пример:** `docker run --rm my-utility-container` * **`--entrypoint <команда>`:** Переопределяет `ENTRYPOINT`, определенный в Dockerfile. * **`--cmd <аргументы>`:** Переопределяет `CMD`, определенный в Dockerfile. * **`-u` или `--user [:]` или `--user [:]`:** Запускает процессы внутри контейнера от указанного пользователя или пользователя и группы. ## Управление запущенными контейнерами * **Просмотр запущенных контейнеров:** `docker ps` * `-a` или `--all`: Показать все контейнеры (включая остановленные). * **Остановка контейнера:** `docker stop <имя_контейнера> или ` * Отправляет сигнал `SIGTERM` контейнеру и дает время на корректное завершение. * **Принудительная остановка контейнера:** `docker kill <имя_контейнера> или ` * Отправляет сигнал `SIGKILL`, немедленно завершая процесс. * **Перезапуск контейнера:** `docker restart <имя_контейнера> или ` * **Просмотр логов контейнера:** `docker logs <имя_контейнера> или ` * `-f` или `--follow`: Следить за логами в реальном времени. * `--tail <число>`: Показать последние N строк логов. * **Выполнение команд внутри запущенного контейнера:** `docker exec -it <имя_контейнера> или <команда>` * `-it`: Интерактивный терминал (pseudo-TTY). * **Пример:** `docker exec -it my-web-app bash` (запустить оболочку bash внутри контейнера `my-web-app`) * **Копирование файлов между хостом и контейнером:** `docker cp <путь_на_хосте> <имя_контейнера>:<путь_в_контейнере>` или `docker cp <имя_контейнера>:<путь_в_контейнере> <путь_на_хосте>` * **Удаление остановленного контейнера:** `docker rm <имя_контейнера> или ` * `-f` или `--force`: Принудительное удаление запущенного контейнера (не рекомендуется). ## Примеры ручного развертывания * **Запуск веб-сервера Nginx с пробросом порта 80:** ```bash docker run --name my-nginx -d -p 80:80 nginx ``` * **Запуск базы данных PostgreSQL с установкой пароля через переменную окружения и монтированием тома для данных:** ```bash docker run --name my-postgres -d -e POSTGRES_PASSWORD=mysecret -v pg_data:/var/lib/postgresql/data postgres ``` (Предполагается, что том `pg_data` уже создан: `docker volume create pg_data`) * **Запуск простого Python-приложения из локального образа `my-python-app` в фоновом режиме:** ```bash docker run --name my-app -d my-python-app ``` (Если приложение слушает порт, необходимо добавить `-p`) * **Запуск контейнера с автоматическим удалением после остановки:** ```bash docker run --rm alpine echo "This container will be removed" ``` ## Ограничения ручного развертывания * **Сложность управления множеством контейнеров:** Координирование запуска, остановки, связывания и масштабирования большого количества контейнеров становится трудоемким. * **Отсутствие автоматизации:** Каждое действие (запуск, перезапуск, обновление) выполняется вручную. * **Сложность настройки связей между контейнерами:** Необходимо вручную настраивать сети и проброс портов для взаимодействия контейнеров. * **Нет автоматического восстановления после сбоев:** Необходимо вручную перезапускать упавшие контейнеры (хотя `--restart` может помочь). * **Неудобно для сложных приложений:** Для приложений, состоящих из нескольких взаимосвязанных сервисов, ручное управление быстро становится непрактичным. ## Когда ручное развертывание может быть полезным * **Простые одноконтейнерные приложения без сложных зависимостей.** * **Локальная разработка и тестирование отдельных контейнеров.** * **Изучение основ работы с Docker и отладка контейнеров.** * **Среды с ограниченными ресурсами или специфическими требованиями, где оркестрация нецелесообразна.** ## Заключение Ручное развертывание контейнеров предоставляет прямой контроль над запуском и управлением отдельными контейнерами с помощью командной строки Docker. Хотя оно полезно для простых сценариев и понимания основ, для более сложных многоконтейнерных приложений рекомендуется использовать инструменты оркестрации или композиции, такие как Docker Compose или Kubernetes. ## Следующие шаги * Практическое выполнение команд `docker run` с различными параметрами. * Развертывание простых приложений (например, веб-сервера, базы данных) вручную. * Изучение команд управления запущенными контейнерами (`docker ps`, `docker stop`, `docker start`, `docker logs`, `docker exec`). * Понимание ограничений ручного развертывания и необходимости использования инструментов оркестрации для сложных приложений.