Образ есть — теперь нужно его запустить. В этой статье разберём команду docker run, основные флаги, которые используются каждый день, и то, что происходит с контейнером после старта: как смотреть логи, заходить внутрь и корректно останавливать.
Что происходит при запуске
Когда вы пишете docker run, Docker создаёт из образа контейнер — изолированный процесс со своей файловой системой, сетью и переменными окружения — и запускает его.
Короткая формула: образ — это рецепт, контейнер — это работающее блюдо.
Простейший запуск:
docker run eclipse-temurin:21-jre java -version
Docker скачает образ (если его нет локально), создаст контейнер, выполнит команду и завершится. Контейнер остановится, как только процесс внутри завершится.
Основные флаги docker run
Большинство реальных запусков используют несколько флагов вместе. Разберём каждый.
-p: проброс портов
Контейнер живёт в изолированной сети — снаружи до него не достучаться, пока вы явно не откроете порт.
docker run -p 8080:8080 my-spring-app
# ^ ^
# хост:контейнер
Левая часть — порт на вашей машине (хосте), правая — порт внутри контейнера. Можно использовать разные номера:
docker run -p 9090:8080 my-spring-app # приложение слушает 8080, снаружи доступно на 9090
-e: переменные окружения
Это основной способ передавать конфигурацию в контейнер — пароли к базе данных, URL внешних сервисов, профили Spring Boot. Каждая переменная — отдельный флаг -e:
docker run \
-e SPRING_PROFILES_ACTIVE=prod \
-e DB_URL=jdbc:postgresql://db:5432/myapp \
-e DB_PASSWORD=secret \
my-spring-app
Внутри Spring Boot эти переменные автоматически подхватываются как свойства приложения (через Environment).
-d: фоновый режим
По умолчанию docker run держит терминал занятым — вывод идёт прямо в консоль. Флаг -d (detached) запускает контейнер в фоне и сразу возвращает управление:
docker run -d -p 8080:8080 my-spring-app
Docker выведет идентификатор контейнера и всё. Логи смотреть отдельно — об этом ниже.
--name: имя контейнера
По умолчанию Docker придумывает имена вроде elegant_hopper — не очень удобно. Задайте своё:
docker run -d --name my-app -p 8080:8080 my-spring-app
Теперь к контейнеру можно обращаться по имени во всех командах: docker logs my-app, docker stop my-app.
--rm: автоудаление
Если контейнер нужен разово (прогнать тест, выполнить скрипт), флаг --rm удалит его автоматически при остановке:
docker run --rm my-spring-app java -jar app.jar --check-config
Без --rm остановленные контейнеры накапливаются и занимают место.
Всё вместе — типичный запуск
docker run -d \
--name my-app \
--rm \
-p 8080:8080 \
-e SPRING_PROFILES_ACTIVE=prod \
-e DB_URL=jdbc:postgresql://db:5432/myapp \
my-spring-app:1.0
Передача конфигурации через переменные окружения
В мире контейнеров конфигурация не хранится внутри образа — она приходит снаружи при запуске. Это идея из методологии 12-factor app: один и тот же образ разворачивается в разных окружениях (разработка, тестирование, продакшн) с разными переменными.
Для Spring Boot это выглядит так: в application.yml вы пишете ${DB_URL}, а конкретное значение передаёте через -e DB_URL=... при запуске контейнера. Ни один секрет не попадает в образ.
Если переменных много, удобно вынести их в файл:
# .env
SPRING_PROFILES_ACTIVE=prod
DB_URL=jdbc:postgresql://db:5432/myapp
DB_PASSWORD=secret
docker run -d --env-file .env -p 8080:8080 my-spring-app
Только не коммитьте .env с реальными паролями в репозиторий.
Жизненный цикл контейнера
После запуска контейнер проходит через несколько состояний.
Команды для управления:
docker ps # список работающих контейнеров
docker ps -a # все, включая остановленные
docker stop my-app # мягкая остановка (SIGTERM, затем SIGKILL через 10 с)
docker start my-app # запустить остановленный контейнер
docker rm my-app # удалить остановленный контейнер
docker rm -f my-app # остановить и удалить сразу
docker stop отправляет процессу сигнал SIGTERM — приложение может его перехватить и завершиться корректно (закрыть соединения с базой, дождаться текущих запросов). Через 10 секунд Docker принудительно убивает процесс через SIGKILL.
Логи: docker logs
Всё, что приложение пишет в stdout и stderr, Docker собирает автоматически.
docker logs my-app # вывести все накопленные логи
docker logs -f my-app # следить за логами в реальном времени (как tail -f)
docker logs --tail 100 my-app # последние 100 строк
Spring Boot по умолчанию пишет в stdout — ничего дополнительно настраивать не нужно. Если приложение пишет в файл внутри контейнера, docker logs этот файл не увидит.
Зайти внутрь: docker exec
Иногда нужно посмотреть, что происходит внутри работающего контейнера — проверить файловую систему, переменные окружения, сетевые соединения.
docker exec -it my-app sh # запустить shell внутри контейнера
docker exec -it my-app bash # если bash есть в образе
Флаги -it означают: -i — передавать ввод с клавиатуры, -t — подключить псевдотерминал. Вместе они дают интерактивную сессию.
Внутри можно проверить переменные:
env | grep SPRING
Или посмотреть, какие процессы запущены:
ps aux
docker exec не перезапускает приложение — команда выполняется рядом с уже работающим процессом.
Healthcheck: проверка работоспособности
Docker умеет периодически проверять, жив ли контейнер — не просто процесс запущен, а приложение реально отвечает. Это healthcheck.
Проще всего задать его в Dockerfile:
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD wget -qO- http://localhost:8080/actuator/health || exit 1
После старта контейнер некоторое время находится в состоянии starting — Docker ждёт, пока healthcheck пройдёт впервые. Потом переходит в healthy или unhealthy.
Посмотреть статус:
docker inspect --format='{{.State.Health.Status}}' my-app
В изолированном docker run healthcheck влияет только на статус — контейнер не перезапускается автоматически. Автоматический перезапуск — это уже задача для Docker Compose или оркестратора.
Коротко
docker runсоздаёт контейнер из образа и запускает его; при завершении процесса контейнер останавливается.-p host:container— проброс порта; без него к контейнеру не подключиться снаружи.-e KEY=VALUE— передать переменную окружения; это основной способ конфигурации по принципу 12-factor.-d— фоновый режим;--name— удобное имя;--rm— удалить контейнер после остановки.docker logs -f— следить за логами в реальном времени;docker exec -it ... sh— интерактивная сессия внутри.docker stopпосылаетSIGTERM, даёт приложению 10 секунд на корректное завершение.- Healthcheck проверяет, что приложение не просто запущено, а реально отвечает.
Что почитать дальше
- Что такое Docker и зачем он нужен — если ещё не читали: образы, слои, изоляция с нуля.
- Тома и данные — как сохранить данные между перезапусками контейнера.
- Сеть в Docker — как контейнеры общаются друг с другом и с внешним миром.