Docker — инструмент для разработки, тестирования и развертывания приложений в виде контейнеров, которые работают практически на любой платформе. Такая универсальность достигается благодаря созданию изолированной среды. В нее добавляют все, что нужно для выполнения процесса. Получается контейнер, который можно перенести в другую систему и запустить.
Содержание
Команда Run — одна из первых, с которой знакомятся пользователи Docker. Она создает контейнер из заданного Image и запускает его. В этой статье для начинающих мы изучим особенности использования Docker Run на примере официального образа nginx и не только.
Команда Docker Run имеет следующий общий вид:
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
Чтобы запустить Docker, достаточно выполнить команду:
docker run image-sample
Единственный обязательный аргумент — имя образа, из которого должен быть собран контейнер. В примере выше это image-sample
. Если образа нет в локальной системе, можно извлечь его из Docker Hub, Quay и других публичных платформ.
Чтобы убедиться, что Docker установлен и работает, запустите контейнер «Hello World
» из Docker Hub:
sudo docker run hello-world
При первом запуске демон Docker извлекает контейнер из Docker Hub. Затем он создает новый контейнер и передает вывод в терминал. Если все прошло успешно, вы увидите сообщение:
Hello from Docker! This message shows that your installation appears to be working correctly.
Теперь Docker-контейнер «Hello World
» хранится на локальном компьютере. При следующем запуске он загрузится быстрее.
Чтобы посмотреть список всех контейнеров, которые хранятся на локальной машине, используйте команду:
sudo docker image ls
В выведенном списке будет указано название репозитория, тег, Image ID, дата создания и размер. Image ID можно использовать для запуска контейнера. Например, если в списке вы видите такую запись:
REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
ubuntu | latest | 4e1eeg94cd6b | 17 days ago | 73.8MB |
то можете запустить контейнер Ubuntu командой:
sudo docker run 4e1eeg94cd6b
Ниже мы рассмотрим основные особенности использования команды Docker Run. Больше опций и примеров смотрите в документации или посетите специальные курсы от Mate Academy и Hillel.
При работе с Docker на локальной машине приходится давать расширенные права с помощью команды sudo
. Избавиться от ошибок доступа и при этом работать как обычный пользователь, а не root, можно двумя способами.
1. Добавление пользователя в привилегированную группу Docker.
Создайте новую группу командой:
sudo groupadd docker
Возможно, такая группа уже существует. Тогда добавьте в нее нового пользователя:
sudo gpasswd -a $USER docker
$USER
— указание на текущего пользователя. Вы можете добавить в группу и другого пользователя. Главное, чтобы ему было разрешено использовать sudo
.
Последний шаг — перезагрузка оболочки. Можно выйти из системы и войти обратно, перезагрузиться. Но быстрее будет выполнить команду:
newgrp docker
Теперь можно запускать контейнеры без использования sudo. Например, наш «Hello World
»:
docker run hello-world
2. Использование ACL.
Еще один способ — добавить пользователя в список ACL. Выполните команду:
sudo setfacl -m user:username:rw /var/run/docker.sock
Вместо username укажите имя пользователя, под которым вы будете запускать контейнеры. Теперь можно входить в систему как этот пользователь:
su username
Дальше можно выполнять любые команды без sudo
. Например, отобразить имеющиеся на локальной машине контейнеры:
docker ps
Запуск на переднем плане означает, что стандартный вход, выход и ошибка корневого процесса привязаны к сеансу терминала. Пока контейнер запущен, он не возвращает командную строку.
Например, запустите nginx:
docker container run nginx
Пока подключения к веб-серверу нет, в терминале будет пусто. Как только вы подключитесь к веб-серверу, на экране отобразится вывод nginx-процесса.
Контейнеры запускаются на переднем плане по умолчанию. Чтобы остановить работу, используйте стандартное сочетание клавиш «Ctrl + C».
Разобраться в данной теме и расширить свои знания можно с помощью специальных курсов. Школы Powercode и ШАГ готовы помочь своим ученикам освоить все необходимые знания для работы в области разработки.
Если нужно, чтобы контейнер продолжал работать после выхода из терминала, запускайте его в автономном (фоновом) режиме. Используйте в команде опцию -d
:
docker container run -d nginx
В фоновом режиме вы можете дальше работать с терминалом. Например, вводить в него команды для отображения списка запущенных контейнеров или выходить из контейнера.
Автономный контейнер останавливается только после завершения корневого процесса. Посмотреть список запущенных контейнеров можно командой:
docker container ls
При необходимости прикрепите терминал к корневому контейнеру. Выполните для этого команду:
docker container attach
Чтобы остановить контейнер, выполните команду:
docker stop nginx
Docker также поддерживает запуск контейнера в интерактивном режиме. Это значит, что вы сможете выполнять команды bash
внутри контейнера с оболочкой. Для старта интерактивного режима используются опции -i
и -t
.
Например, опция -it
говорит Docker, что нужно оставить терминалу стандартный вход и назначить псевдо-tty
:
docker container run -it nginx /bin/bash
После выполнения этой команды к терминалу прикрепится оболочка контейнера bash
. Интерпретатор изменится. Вы сможете взаимодействовать с оболочкой контейнера и выполнять в ней любые команды.
Для идентификации контейнеров в Docker используется UUID и название. Если имя не задано явно, то демон Docker генерирует его автоматически. Это не всегда удобно. Но легко исправляется с помощью опции --name
:
docker container run -d --name my_nginx nginx
Главное, чтобы имя контейнера было уникальным. Если попробовать запустить другой контейнер с таким же именем, Docker выдаст ошибку:
docker: Error response from daemon: Conflict. The container name "/my_nginx" is already in use by container "73c370a61b7792f6f42326197b78ed9e39367f4c2c0abeaa8c2cb7881050c733". You have to remove (or rename) that container to be able to reuse that name.
Чтобы отобразить все контейнеры и посмотреть их имена, используйте команду:
docker container ls -a
Вот пример вывода:
CONTAINER ID | IMAGE | COMMAND | CREATED | STATUS | PORTS | NAMES |
73c370a51b77 | nginx | "nginx -g 'daemon of…" | 5 minutes ago | Up 5 minutes | 80/tcp | my_nginx |
775fg6985dde | "nginx -g 'daemon of…" | 7 minutes ago | Up 7 minutes | 80/tcp | friendly_paul | |
7f836dcnb1d1 | "nginx -g 'daemon of…" | 13 minutes ago | Up 13 minutes | example_one | ||
d1785f35a0c8 | "nginx -g 'daemon of…" | 29 minutes ago | Up 29 minutes | example_two |
Задавать имена не обязательно. Просто с ними удобнее обращаться к контейнерам. Не придется постоянно вызывать список и смотреть сложный для запоминания ID.
По умолчанию для доступа к процессам нужно войти внутрь контейнера. Однако можно подключиться к ним извне, открыв порты. Вы можете сопоставлять порты локальной машины с портами контейнера, чтобы передавать между ними данные. Для этого используется параметр -p
:
-p host_ip:host_port:container_port/protocol
По умолчанию host_ip
равен 0.0.0.0.0
, а протокол — TCP
. Но вы можете явно указать другие параметры.
Можно сопоставлять любые открытые и свободные порты. Например, установите связь между портом 80 nginx
и портом 8080
локальной машины:
docker container run --name web_server -d -p 8080:80 nginx
Теперь можно получать curl
через обращение к порту локальной машины:
curl -I http://localhost:8080
Вывод должен быть примерно таким:
HTTP/1.1 200 OK Server: nginx/1.17.6 Date: Tue, 14 Dec 2021 21:45:19 GMT Content-Type: text/html Content-Length: 612 Last-Modified: Tue, 14 Dec 2021 13:51:18 GMT Connection: keep-alive ETag: "4dee500-124" Accept-Ranges: bytes
Если нужно опубликовать несколько портов, используйте опцию -p
несколько раз.
Когда вы закрываете контейнер, данные внутри него удаляются. Если нужно хранить их постоянно, используйте Docker Volume. Это предпочтительный способ сохранения и обмена данными между контейнерами. Чтобы создать том и управлять им, используйте опцию -v
:
-v host_src:container_dest:options
Пояснения к синтаксису команды:
Host_src
— абсолютный путь к файлу или папке на хосте или указанном томе.Container_dest
— абсолютный путь к файлу или папке в контейнере.-rw
(чтение). Можно также настроить права только на чтение, установив опцию -ro
.Для наглядности создайте каталог на хосте и поместите в него файл с минимальной разметкой HTML.
mkdir public_html echo "Testing Docker Volumes" > public_html/index.html
Вариант содержимого HTML-файла:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>title</title> <link rel="stylesheet" href="style.css"> <script src="script.js"></script> </head> <body> <p>Hello, Highload!</p> </body> </html>
Затем смонтируйте каталог public_html
в каталог /usr/share/nginx/html
в контейнере:
docker run --name web_server -d -p 8080:80 -v $(pwd)/public_html:/usr/share/nginx/html nginx
Обратите внимание на синтаксис. Вместо указания абсолютного пути к папке public_html
использована команда $(pwd)
, которая выводит текущий рабочий каталог.
Если монтирование прошло успешно, то при переходе в браузере по адресу http://localhost:8080
вы увидите содержимое файла index.html
. Также для проверки можно использовать curl:
curl http://localhost:8080 Output: Hello, Highload!
Если нужно соединить два контейнера, используйте связывание с помощью опции --link
. В качестве примера давайте свяжем контейнер базы данных MySQL с контейнером PhpMyAdmin.
Создайте контейнер MySQL с постоянным хранилищем в /var/lib/mysql
. Для запуска в автономном режиме используйте опцию -d
:
docker run -v mysql_volume:/var/lib/mysql --name MySQL -e MYSQL_ROOT_PASSWORD=passwd -d mysql:8.0
Затем создайте контейнер с PhpMyAdmin
и свяжите его с MySQL:
docker run --name PhpMyAdmin -d --link MySQL:db -p 8080:80 phpmyadmin/phpmyadmin
Этой командой вы заодно пробросили порт в хост-систему. Теперь через браузер можно проверить, что контейнеры связаны.
Если нужно объединить больше трех контейнеров, то удобнее не создавать подключение для каждого, а связать их в единую сеть. Все объекты внутри этой сети будут иметь доступ к друг другу по имени.
Чтобы создать сеть, выполните команду:
docker network create -d bridge docker_network
Посмотреть список доступных сетей можно командой:
docker network list
В качестве примера давайте объединим в сеть контейнеры MySQL и phpMyAdmin
. Сначала остановите их и удалите:
docker stop MySQL docker stop PhpMyAdmin docker rm MySQL docker rm PhpMyadmin
Затем создайте сеть для MySQL:
docker run -v mysql_volume:/var/lib/mysql --network docker_network --name MySQL -e MYSQL_ROOT_PASSWORD=passwd -d mysql:8.0
Передайте PhpMyAdmin
хост, на котором расположена база данных в переменной окружения PMA_HOST
:
docker run --name PhpMyAdmin -d --network docker_network -e PMA_HOST=MySQL -p 8080:80 phpmyadmin/phpmyadmin
Аналогичным образом к сети подключаются другие контейнеры. Это позволяет им взаимодействовать так же, как и при связывании.
По умолчанию после завершения процесса и остановки контейнер сохраняется на хост-машине. Чтобы избавиться от ненужных данных, используйте опцию --rm
.
docker container run --rm nginx
Теперь при выходе контейнер будет извлекаться. Обычно эту опцию используют при работе с контейнерами, выполняющими кратковременные задачи — например, тестирование или создание бэкапов.
Если вы начинаете пользоваться Docker, то приготовьтесь к постоянному вводу команды run с разными опциями. Это основа для запуска любых контейнеров по умолчанию и с измененной конфигурацией.
Если хотите больше узнать о Docker и научиться работать с контейнерами, посмотрите этот видеокурс:
Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…
Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…
Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…
В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…
Скрипт (англ. — сценарий), — это небольшая программа, как правило, для веб-интерфейса, выполняющая определенную задачу.…
Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…