Запуск контейнера 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>
Чаще команда используется для того, чтобы:
- Получить доступ к командной строке внутри контейнера (псевдотерминал).
- Запустить команды внутри контейнера.
Пример 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 вы можете в официальной документации.
Изменение переменных окружения в контейнере
Переменные окружения нельзя изменить «на лету», но можно выполнить следующие действия.
- Остановить контейнер:
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.
Контейнер не удаляется из-за зависимости
- Необходимо вывести все контейнеры в системе
docker ps -a
- Затем удалить те зависимости, которые указаны как конфликтующие
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 упрощает развертывание приложений и делает контейнеризацию удобной и управляемой.