Запуск контейнера Docker и команда docker run
Рассказываем, как работать с Docker. Инструментом, который позволяет изолировать приложения и их зависимости в контейнерах, обеспечивая стабильную и предсказуемую работу в любых средах.
Как работают контейнеры в Docker
Контейнер — это своего рода коробка, в которой находится все необходимое для работы приложения: код, библиотеки, файлы и настройки. Эта коробка полностью изолирована от остальной системы, поэтому приложение внутри нее работает одинаково на любом компьютере — будь то ваш личный ноутбук или сервер в облаке.
Но в чем разница между контейнером и виртуальной машиной? Виртуальные машины эмулируют целую операционную систему со своим ядром, тогда как контейнеры используют ядро уже установленной ОС. Это делает их:
- более быстрыми — контейнеры запускаются почти мгновенно, так как не требуют загрузки отдельной ОС;
- менее ресурсоемкими — несколько контейнеров на одном сервере могут совместно использовать одно ядро;
- легче переносимыми — контейнеры можно быстро упаковать в образ и развернуть на любой системе.
Как создать контейнер Docker
Для начала работы с контейнером его необходимо создать. Контейнер создается на основе образа, в котором уже есть все необходимое для работы приложения. Образ формируется на основе Dockerfile — инструкции, где описаны все этапы его сборки:
- базовый образ,
- установка зависимостей,
- копирование файлов,
- запуск команд и настройка параметров среды.
Образы хранятся в специальном репозитории, например, Docker Hub — это большая библиотека готовых решений.
Скачать образ можно с помощью команды:
docker pull <имя_образа>
Например, чтобы загрузить образ с Nginx, выполните:
docker pull nginx
После этого образ появится в локальном хранилище и будет готов к использованию.
Проверить список загруженных образов можно командой:
docker images
Для создания контейнера из загруженного образа используйте команду:
docker create <имя_образа>
Эта команда создаст контейнер, но не запустит его. Он будет находиться в неактивном состоянии до момента запуска.
Просмотреть список созданных контейнеров можно с помощью команды:
docker ps -a
Как запустить контейнер
Запустить контейнер можно двумя способами.
Первый — запустить ранее созданный контейнер. Если контейнер уже был создан, но еще не запущен, используйте команду:
docker start <container_ID>
Идентификатор контейнера можно узнать с помощью команды docker ps -a.
Второй — создать и запустить контейнер одной командой. Вместо docker create и docker start можно сразу использовать команду:
docker run <имя_образа>
По умолчанию контейнер запускается в интерактивном режиме, и если процесс внутри него завершится (например, Nginx остановится), сам контейнер тоже выключится. Чтобы запустить его в фоновом режиме, используют параметр -d (о нем поговорим в следующем разделе).
Синтаксис команды docker run
Команда docker run не только создает и запускает контейнер, но и позволяет настроить его поведение с помощью множества опций.
Общий синтаксис:
docker run [опции] <имя_образа> [аргументы]
Где:
- [опции] — параметры, которые определяют, как будет работать контейнер;
- <имя_образа> — образ, на основе которого создается контейнер;
- [аргументы] — дополнительные команды, передаваемые внутрь контейнера.
Наиболее популярные опции
Запуск в фоновом режиме (-d)
По умолчанию контейнер работает в активном режиме и завершает работу, как только завершается его основной процесс. Чтобы контейнер оставался активным в фоне, существует флаг -d:
docker run -d nginx
Интерактивный режим (-it)
Если контейнер требует ввода команд, его можно запустить в интерактивном режиме:
docker run -it ubuntu bash
В этом случае откроется терминал внутри контейнера.
Автоматическое удаление контейнера (—rm)
Если контейнер нужен временно, можно настроить его автоматическое удаление после завершения работы:
docker run --rm ubuntu echo "Hello, Docker!"
После выполнения команды контейнер удалится.
Задание имени контейнера (—name)
Задать собственное название Docker-контейнеру вместо автоматически присваемого можно командой:
docker run --name my_nginx nginx
Ограничение ресурсов контейнера
Допускается ограничение использования контейнером ядер процессора (—cpus) и оперативной памяти (—memory):
docker run --memory=512m --cpus=1 nginx
Этот контейнер сможет использовать не более 512 МБ оперативной памяти и одного ядра процессора.
Ознакомиться с полным списком опций команды docker run вы можете в официальной документации.
Подключение к контейнеру
Иногда требуется зайти внутрь работающего контейнера, чтобы выполнить команды, проверить настройки или устранить проблемы. В 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.
Переменные окружения и изменение настроек контейнера
Передача переменных окружения при запуске контейнера
Переменные окружения можно передавать контейнеру с помощью опции -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>
Изменение переменных окружения в контейнере
Переменные окружения нельзя изменить «на лету», но можно:
- остановить контейнер:
docker stop <container_ID>
- перезапустить его с новыми переменными:
docker run -e "NEW_VAR=value" <container_ID>
Создание нового образа с измененными настройками
Если нужно сохранить внесенные в контейнер изменения, можно собрать новый образ с помощью команды 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
Такой метод удобен, если нужно подготовить кастомный образ с предустановленными настройками и программами.
Монтирование папок
Когда контейнеру нужны файлы с хостовой машины, их можно примонтировать — подключить папку или отдельный файл из хоста внутрь контейнера. Это удобно для работы с конфигурациями, логами или исходным кодом. Например, если вы разрабатываете веб-приложение, можно хранить его файлы на хосте, а контейнер будет автоматически использовать их, не требуя пересборки.
Самый простой способ монтирования — опция -v, где указывается путь к папке на хосте и путь, по которому она будет доступна в контейнере:
docker run -d -v ~/projects:/app ubuntu
Теперь файлы из ~/projects будут доступны в контейнере по пути /app. Можно сразу запускать сервер или компилировать код внутри контейнера, а изменения, внесенные снаружи, тут же применятся.
Иногда файлы нужно просто читать, но не изменять. В таком случае добавляется параметр :ro (read-only), запрещающий запись:
docker run -d -v ~/projects:/app:ro ubuntu
Хранилища и монтирование виртуального диска
Монтирование папок подходит не во всех случаях. Иногда контейнеру нужно собственное, независимое хранилище, которое сохраняется даже после удаления контейнера. Для таких задач Docker предлагает тома (volumes).
В отличие от обычного монтирования, тома создаются и управляются самим Docker. Они хранятся в специальной директории внутри Docker (/var/lib/docker/volumes/) и не зависят от конкретного контейнера.
Создать том можно командой:
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 изолированы друг от друга, но часто им нужно взаимодействовать. Например, веб-приложение в одном контейнере может обращаться к базе данных в другом. Для этого 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
Хранение образов в облаке Selectel
Когда работа с контейнерами входит в повседневную практику, возникает вопрос: где хранить все эти образы? Можно загружать их в публичные реестры вроде Docker Hub, но что если нужно безопасное, быстрое и удобное частное хранилище?
Selectel Container Registry — это полностью готовый к использованию реестр, который позволяет хранить, управлять и развертывать Docker-образы без лишних сложностей. Все данные хранятся в изолированной облачной инфраструктуре Selectel, где каждый образ проходит тройную репликацию. Это означает, что даже в случае сбоя ваши контейнеры останутся в безопасности. Работать с реестром можно через удобную панель управления или с использованием инструментов автоматизации, таких как API или Terraform.
Заключение
В статье разобрали ключевые моменты команды docker run для создания и запуска контейнеров, настройки их сетей, управления ресурсами и хранения данных. Грамотное использование docker run упрощает развертывание приложений и делает контейнеризацию удобной и управляемой.