Как запустить контейнер Docker через docker run в фоновом и интерактивном режиме

Запуск контейнера Docker и команда docker run

Разбираемся, как изолировать приложения и их зависимости в контейнерах, а также какие параметры важны при работе с docker run.

Что такое Docker и как работает

Контейнер — это своего рода коробка, в которой находится все необходимое для работы приложения: код, библиотеки, файлы и настройки. Эта коробка полностью изолирована от остальной системы, поэтому приложение внутри нее работает одинаково на любом компьютере — будь то ваш личный ноутбук или сервер в облаке.

Но в чем разница между контейнером и виртуальной машиной? Виртуальные машины эмулируют целую операционную систему со своим ядром, тогда как контейнеры используют ядро уже установленной ОС. Это делает их:

  • более быстрыми — контейнеры запускаются почти мгновенно, так как не требуют загрузки отдельной ОС;
  • менее ресурсоемкими — несколько контейнеров на одном сервере могут совместно использовать одно ядро;
  • легче переносимыми — контейнеры можно быстро упаковать в образ и развернуть на любой системе.

Установка и подготовка Docker

Установка Docker

Для начала работы с контейнером его необходимо создать. Контейнер создается на основе образа, в котором уже есть все необходимое для работы приложения. Образ формируется на основе Dockerfile — инструкции, где описаны все этапы его сборки:

  • базовый образ,
  • установка зависимостей,
  • копирование файлов,
  • запуск команд и настройка параметров среды.

Образы хранятся в специальном репозитории, например, Docker Hub — это большая библиотека готовых решений.

Скачать образ можно с помощью команды:


      docker pull <имя_образа>

Например, чтобы загрузить образ с Nginx, выполните:


      docker pull nginx

После этого образ появится в локальном хранилище и будет готов к использованию.

Проверить список загруженных образов можно командой:  


      docker images

Для создания контейнера из загруженного образа используйте команду:


      docker create <имя_образа>

Эта команда создаст контейнер, но не запустит его. Он будет находиться в неактивном состоянии до момента запуска.

Просмотреть список созданных контейнеров можно с помощью команды:   


      docker ps -a

Проверка доступа

При выполнении команд docker можно увидеть сообщение:


      Cannot connect to the Docker daemon at ...

Чаще всего оно означает, что сервис docker не запущен. Второй вариант: у вас нет прав на socket docker, так как daemon docker привязан к сокету, а по умолчанию сокетом владеет пользователь root.

Проверить, запущен ли docker, можно с помощью команды systemctl:


      sudo systemctl status docker

Если сервис запущен, необходимо добавить пользователя в группу docker


      sudo usermod -aG docker $USER

Чтобы сохранить изменения, выйдите из системы и войдите снова, либо выполните команду: 


       newgrp docker

Далее выполните команду для проверки правильности настроек:


      docker ps

Общий синтаксис команды docker run

Общая форма docker run

Команда docker run не только создает и запускает контейнер, но и позволяет настроить его поведение с помощью множества опций.

Структура команды docker run:


       docker run [опции] <имя_образа> [аргументы]

Где:

  • [опции] — параметры, которые определяют, как будет работать контейнер;
  • <имя_образа> — образ, на основе которого создается контейнер;
  • [аргументы] — дополнительные команды, передаваемые внутрь контейнера.

Как запустить контейнер

Запустить контейнер можно двумя способами. Рассмотрим оба.

Пример базового запуска контейнера

Первый — запустить ранее созданный контейнер. Если контейнер уже был создан, но еще не запущен, используйте команду:


      docker start <container_ID>

Идентификатор контейнера можно узнать с помощью команды docker ps -a.

Примеры запуска контейнеров с помощью docker run

Второй способ — создать и запустить контейнер одной командой. Вместо docker create и docker start можно сразу использовать команду:


      docker run <image>

Fun fact: если при запуске контейнера не указать опцию –name, docker сгенерирует имя автоматически. Кстати, если хотите узнать, как именно генерируются имена docker контейнеров, можно посмотреть код на github в проекте moby.

Пример 1. Запуск контейнера в интерактивном режиме (-it)

Для запуска контейнера docker в интерактивном режиме, укажите ключи -it.


      docker run -it <image> <command>

Чаще команда используется для того, чтобы:

  1. Получить доступ к командной строке внутри контейнера (псевдотерминал).
  2. Запустить команды внутри контейнера.

Пример 2. Запуск контейнера в фоновом режиме (-d)

Eсли процесс внутри него завершится (например, Nginx остановится), сам контейнер тоже выключится. Чтобы запустить его в фоновом режиме, используют параметр -d (о нем поговорим в следующем разделе).


      docker run -d <image>

После запуска в командной строке мы увидим идентификатор контейнера.

Команды docker run vs docker create vs docker start

Команда docker run скачивает образ, если необходимо, создает и запускает контейнер.

Docker create же создаст контейнер, но не запустит его. Например, docker create nginx создаст контейнер nginx, и данный контейнер будет со статусом Created.

Для того, чтобы запустить такой контейнер, необходимо выполнить команду docker start:


      docker start <container name>

Таким образом, команда docker run является по сути командами docker create + docker start.

Проброс портов (-p / –publish)

Контейнеры в Docker изолированы друг от друга, но часто им нужно взаимодействовать. Например, веб-приложение в одном контейнере может обращаться к базе данных в другом. Для этого Docker предлагает несколько способов связи между контейнерами.

Доступ к контейнеру по порту

Самый простой способ соединить контейнер с внешним миром — открыть в нем порт и пробросить его на хостовую машину. Это позволит обращаться к сервису внутри контейнера так, будто он работает прямо на хосте.

Допустим, у нас есть контейнер с веб-сервером Nginx. Чтобы сделать его доступным на порту 8080 хостовой машины, запустим:


      docker run -d -p 8080:80 nginx

Теперь, если открыть в браузере http://localhost:8080, мы увидим страницу, обслуживаемую сервером внутри контейнера на порту 80.

Также можно явно указать IP-адрес:


      docker run -d -p 192.168.1.100:8080:80 nginx

Но проброс портов хорош только для взаимодействия с внешним миром. Если вам нужно, чтобы контейнеры обменивались данными напрямую, лучше использовать сети Docker.

Связывание контейнеров через сеть

Docker позволяет объединять контейнеры в виртуальные сети, где они могут общаться друг с другом по именам без необходимости пробрасывать порты. Это удобнее, безопаснее и позволяет контейнерам видеть только те сервисы, которые им нужны.

Создание сети и запуск контейнеров

Создадим сеть с именем my_network:


      docker network create my_network

Теперь запустим базу данных MySQL и укажем, что она должна быть в этой сети:


      docker run -d --name db --network=my_network mysql

А теперь запустим контейнер с приложением, которое должно обращаться к базе данных:


      docker run -d --name app --network=my_network my_app_image

Теперь приложение app может подключаться к MySQL, используя db как адрес сервера базы данных:


      mysql -h db -u root -p

Контейнеры внутри одной сети могут взаимодействовать друг с другом, но остаются невидимыми для остальных.

Далее приведены некоторые команды для работы с сетями.

Посмотреть список всех сетей:


      docker network ls

Узнать, какие контейнеры подключены к конкретной сети:


      docker network inspect my_network

Подключить контейнер к сети после запуска:


      docker network connect my_network <container_ID>

Отключить контейнер от сети:


      docker network disconnect my_network <container_ID>

Удалить сеть, если в ней нет контейнеров:


      docker network rm my_network

Монтирование томов (-v / –mount)

Когда контейнеру нужны файлы с хостовой машины, их можно примонтировать — подключить папку или отдельный файл из хоста внутрь контейнера. Это удобно для работы с конфигурациями, логами или исходным кодом. Например, если вы разрабатываете веб-приложение, можно хранить его файлы на хосте, а контейнер будет автоматически использовать их, не требуя пересборки.

Самый простой способ монтирования — опция -v, где указывается путь к папке на хосте и путь, по которому она будет доступна в контейнере:


      docker run -d -v ~/projects:/app ubuntu

Теперь файлы из ~/projects будут доступны в контейнере по пути /app. Можно сразу запускать сервер или компилировать код внутри контейнера, а изменения, внесенные снаружи, тут же применятся.

Иногда файлы нужно просто читать, но не изменять. В таком случае добавляется docker run параметр :ro (read-only), запрещающий запись:


      docker run -d -v ~/projects:/app:ro ubuntu

Задание имени контейнера (–name)

Задать docker-контейнеру собственное название вместо автоматического можно командой:


      docker run --name my_nginx nginx

Передача переменных окружения (-e)

Переменные окружения можно передавать контейнеру с помощью опции -e:


      docker run -e "DB_USER=admin" -e "DB_PASS=secret" mysql

Если переменных много, удобнее использовать файл .env, чтобы не передавать их вручную в командной строке. Для этого нужно выполнить следующие действия.

Создать файл .env:


      DB_USER=admin
DB_PASS=secret

Загрузить его при запуске контейнера:


      docker run --env-file .env mysql

Этот способ делает конфигурацию более удобочитаемой, упрощает управление переменными и позволяет хранить их в отдельных файлах для разных окружений.

Изменение настроек работающего контейнера

Некоторые параметры можно менять даже после запуска контейнера.

Ограничение ресурсов контейнера

Команда docker update позволяет изменить лимиты процессора и памяти:


      docker update --memory=512m --cpus=1 <container_ID>

Этот контейнер сможет использовать не более 512 МБ оперативной памяти и одного ядра процессора.

Ознакомиться с полным списком опций команды docker run вы можете в официальной документации.

Изменение переменных окружения в контейнере

Переменные окружения нельзя изменить «на лету», но можно выполнить следующие действия.

  1. Остановить контейнер:

      docker stop <container_ID>

2. Перезапустить его с новыми переменными:


      docker run -e "NEW_VAR=value" <container_ID>

Создание нового образа с измененными настройками

Если нужно сохранить внесенные в контейнер изменения, можно собрать новый образ docker с помощью команды docker commit.

Например, изменим что-то внутри контейнера:


      docker exec -it <container_ID> bash
apt update && apt install -y nano
exit

Теперь контейнер содержит новую установленную программу (nano), но если он будет удален, изменения пропадут. Чтобы сохранить их, создадим новый образ: 


      docker commit <container_ID> my_custom_image

Теперь можно поднять Docker-контейнер из этого образа:


      docker run -it my_custom_image bash

Такой метод удобен, если нужно подготовить кастомный образ с предустановленными настройками и программами.

Проверка работающих контейнеров

Просмотр всех контейнеров

Для просмотра всех контейнеров используйте команду:


      docker ps -a

Вход в контейнер

Иногда требуется зайти внутрь работающего контейнера, чтобы выполнить команды, проверить настройки или устранить проблемы. В Docker есть несколько способов подключения к контейнеру.

С помощью docker exec

docker exec позволяет выполнить команду внутри работающего контейнера. Чтобы запустить интерактивную консоль внутри контейнера, выполните:


      docker exec -it <container_ID> bash

Если контейнер работает на Ubuntu или другой системе с bash, это запустит оболочку. В контейнерах на Alpine Linux или других минималистичных дистрибутивах bash может отсутствовать. В таком случае попробуйте использовать sh:


      docker exec -it <container_ID> sh

Также можно передать конкретную команду в консоль без ее открытия. Например, чтобы вывести список файлов в корневой директории контейнера, выполните:


      docker exec <container_ID> ls /

С помощью docker attach

Если контейнер запущен в интерактивном режиме, можно подключиться к его основному процессу с помощью команды docker attach:  


      docker attach <container_ID>

При этом вы получите прямой доступ к терминалу контейнера, как если бы запускали его с docker run -it.

Если закрыть сессию docker attach с помощью Ctrl + C, контейнер остановится. Чтобы выйти, не прерывая работу контейнера, нажмите Ctrl + P, а затем Ctrl + Q.

Хранилища и монтирование виртуального диска

Монтирование папок подходит не во всех случаях. Иногда контейнеру нужно собственное независимое хранилище, которое сохраняется даже после удаления контейнера. Для таких задач Docker предлагает тома (volumes).

В отличие от обычного монтирования, тома создаются и управляются самим Docker. Они хранятся в специальной директории внутри Docker (/var/lib/docker/volumes/) и не зависят от конкретного контейнера.

Создать том docker можно командой:


      docker volume create my_data

После этого его можно использовать в контейнере:  


      docker run -d -v my_data:/data ubuntu

Данные, записанные в /data внутри контейнера, сохраняются в my_data. Даже если контейнер будет удален, этот том получится подключить к другому контейнеру.

Список всех томов можно просмотреть командой:


      docker volume ls

А если том больше не нужен, его можно удалить:


      docker volume rm my_data

В отличие от монтирования папок, тома обеспечивают более надежное хранение данных и удобны для долгосрочного использования.

Какой метод выбрать — зависит от задачи. Для разработки, где важны быстрые изменения, удобнее монтировать папки. Если же данные должны сохраняться независимо от контейнера, тома подойдут лучше.

Остановка и удаление контейнера

Для остановки контейнера используйте команду docker stop.


      docker stop <container name>

Команда посылает процессу внутри контейнера сигнал SIGTERM, и после grаce-периода — сигнал SIGKILL.

Можно выполнить команду docker stop и указать нужный сигнал при остановке контейнера.


      docker stop --signal SIGKILL <container name>

После остановки контейнера его можно запустить все с той же командой docker start.

Как остановить все контейнеры docker

Если запущено много контейнеров и нужно остановить их все, но вводить каждый раз имя контейнера слишком долго, можно использовать следующую команду:


      docker stop $(docker ps -a -q)

Удаление контейнера

Удаление контейнера выполняется командой docker rm:


      docker rm <container name>

Можно также удалить контейнер, который запущен:


      docker rm --force <container name>

Стоит отметить, что после удаления контейнера запустить его с помощью команды docker start уже не получится.

Как удалить все контейнеры docker

Если необходимо удалить все неактивные контейнеры, можно выполнить команду:


      docker rm $(docker ps -a -q)

Будьте аккуратны с выполнением этой команды, иначе легко удалить контейнеры, которые могут еще понадобиться.

Просмотр логов контейнера

Для просмотре логов контейнера используйте команду:


      docker logs <container id/container name>

Для потокового просмотра логов работающего контейнера используйте опцию –follow.


      docker logs -f <container id/container name>

Также есть опции для просмотра логов с указанием времени, подробнее на официальном сайте Docker

Автоматическое удаление контейнера (–rm)

Если контейнер нужен временно, можно настроить его автоматическое удаление после завершения работы:


      docker run --rm ubuntu echo "Hello, Docker!"

После выполнения команды контейнер удалится.

Хранение образов в облаке Selectel

Когда работа с контейнерами входит в повседневную практику, возникает вопрос: где хранить все эти образы? Можно загружать их в публичные реестры вроде Docker Hub, но что если нужно безопасное, быстрое и удобное частное хранилище?

Selectel Container Registry — это полностью готовый к использованию реестр, который позволяет хранить, управлять и развертывать Docker-образы без лишних сложностей. Все данные хранятся в изолированной облачной инфраструктуре Selectel, где каждый образ проходит тройную репликацию. Это означает, что даже в случае сбоя ваши контейнеры останутся в безопасности. Работать с реестром можно через удобную панель управления или с использованием инструментов автоматизации, таких как API или Terraform.

Частые ошибки и как их исправить

Docker не стартует

Можно выполнить любое из этих действий: 

  • Проверить journalctl -u docker
  • Проверить файл daemon.json на наличие ошибок
  • Убедиться, что есть место на диске
  • Рестартовать сервис при помощи команды:

      sudo systemctl restart docker

Контейнер сразу останавливается после запуска

Для начала необходимо проверить логи контейнера docker logs <container name>. Если не поможет, запустите контейнер в интерактивном режиме для отладки docker run -it –entrypoint sh image или проверьте, что ENTRYPOINT/CMD корректны docker inspect <container name>. 

Конфликт портов docker

Если при запуске контейнера возникла ошибка port is already allocated, необходимо найти, какой из запущенных контейнеров занимает порт.


      docker ps -a --format "{{.Names}} | {{.Ports}}" | grep <port>

Также можно поискать в системе, какой процесс занимает порт с помощью этих утилит ss/netstat.

Контейнер не удаляется из-за зависимости

  1. Необходимо вывести все контейнеры в системе 

docker ps -a 

  1. Затем удалить те зависимости, которые указаны как конфликтующие

docker rm <container name>

Проблема с timezone в контейнере docker

Установите переменную окружения TZ в контейнере:


      docker run --env TZ=Europe/Moscow <image>

Или timezone хоста с помощью ключа –volume:


      docker run  -v /etc/localtime:/etc/localtime:ro <image>

Проблемы с правами доступа к тому или иному файлу

Проблема может заключаться в несоответствии GID/UID между хостом и контейнером docker. Для решения установите права владельца (chown) на хосте, запустите контейнер с соответствующим UID (–user) или настройте Dockerfile так, чтобы во время сборки были установлены соответствующие права.

Сборка образа падает с ошибкой

Причин может быть много, но самые частые среди них — это:

  • отсутствие файлов, которые копируются в образ,
  • неправильные пути до файлов,
  • неправильный синтаксис команд в dockerfile.
  • старый кэш.

Необходимо проверить правильность путей и файлов. Также можно запустить сборку образа docker с опцией –no-cache, которая отключит кэш при сборке:


      docker run --no-cache <image>

Дополнительно рекомендуем проверять dockerfile через линтеры (как пример — линтер dockerfile – hadolint, у которого есть и онлайн-версия).       

FAQ

  • Как запустить контейнер Docker?

При помощи команд docker run <image name> или docker start <container name>.

  • Что делает команда docker run?

Скачивает образ docker, если необходимо, создает и запускает контейнер.

  • Чем docker run отличается от docker start?

docker start только запускает контейнер, в то время как команда docker run может кроме запуска еще скачивать и создавать новые контейнеры. Кроме того, у этих двух команд разный набор ключей для запуска контейнера.

  • Как остановить и удалить контейнер?

При помощи команд docker stop <container name> и docker rm <container name>.

  • Можно ли сразу удалить контейнер после выполнения?

Да, для этого запустите контейнер с опцией –rm, а затем команду docker run –rm ubuntu /bin/bash.

  • Как пробросить порт docker контейнера на хост?

При помощи команды docker run -p <host ip>:<container port>.

  • Как запустить несколько контейнеров одновременно?

Запустите docker start <container name> <container another name> и используйте  docker compose.

Заключение

В статье разобрали ключевые моменты команды docker run для создания и запуска контейнеров, настройки их сетей, управления ресурсами и хранения данных. Грамотное использование docker run упрощает развертывание приложений и делает контейнеризацию удобной и управляемой.