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

Для запуска контейнера не обязательно предварительно скачивать образ. Если он доступен, то будет загружен автоматически. Давайте попробуем запустить контейнер с Ubuntu. Мы не будем указывать репозиторий, и будет скачан последний официальный образ, поддерживаемый Canonical.

$ docker run -it ubuntu
[email protected]:/#

Помимо команды run, мы указали две опции: -i – контейнер должен запуститься в интерактивном режиме и -t – должен быть выделен псевдотерминал. Как видно из вывода, в контейнере мы имеем привилегии пользователя root, а в качестве имени узла отображается идентификатор контейнера. Последнее может быть справедливо не для всех контейнеров и зависит от разработчика контейнера. Проверим, что это действительно окружение Ubuntu:

[email protected]:/# cat /etc/*release | grep DISTRIB_DESCRIPTION
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

Команду uname -a для подобных целей использовать не получится, поскольку контейнер работает с ядром хоста. В качестве одной из опций можно было бы задать уникальное имя контейнера, на которое можно для удобства ссылаться, помимо ID-контейнера. Она задается как —name <имя>. В случае если опция опущена, имя генерируется автоматически.
Автоматически генерируемые имена контейнеров не несут смысловой нагрузки, однако как интересный факт можно отметить, что имена генерируются случайным образом из прилагательного и имени известного ученого, изобретателя или хакера. В коде генератора для каждого имени можно найти краткое описание того, чем известен данный деятель.
Посмотреть список запущенных контейнеров можно командой docker ps. Для этого откроем второй терминал:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
d7402d1f7c54 ubuntu "/bin/bash" 9 seconds ago
STATUS PORTS NAMES
Up 4 seconds romantic_heisenberg

В случае если необходимо запустить контейнер с процессом, не предполагающим интерактивное взаимодействие, например с демоном, используется опция -d. Так и поступим со следующим контейнером:

$ docker run -d mysql

Однако если отдать команду docker ps, контейнера, созданного из образа mysql, мы не обнаружим. Воспользуемся опцией -a, которая показывает все контейнеры, а не только запущенные:

$ docker ps -a
CONTAINER ID IMAGE COMMAND
d454844325da mysql "docker-entrypoint.sh"
d7402d1f7c54 ubuntu "/bin/bash"
CREATED STATUS PORTS
About a minute ago Exited (1) About a minute ago
32 minutes ago Up 32 minutes
NAMES
peaceful_jones
romantic_heisenberg

В качестве статуса значится Exited. Для того чтобы разобраться с причиной, можно обратиться к журналу:

$ docker logs peaceful_jones
error: database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD

Очевидно, что при запуске контейнера не были указаны обязательные параметры. Ознакомиться с описанием переменных среды, необходимых для запуска контейнера, можно, найдя официальный образ MySQL на Docker Hub.
Повторим попытку, используя опцию -e, которая задает переменные окружения в контейнере:

$ docker run --name mysql-test -e MYSQL_ROOT_PASSWORD=docker -d mysql

При помощи следующей команды можно подключиться к работающему контейнеру:

$ docker exec -it mysql-test bash
[email protected]:/#

Последним параметром выступает команда, которую мы хотим исполнить внутри контейнера. В данном случае это командный интерпретатор Bash. Опции -it аналогичны по назначению использованным ранее в команде docker run.
Фактически после запуска этой команды в контейнер mysql-test добавляется еще один процесс – bash. Это можно наглядно увидеть при помощи команды pstree. Сокращенный вывод до команды docker exec:

# pstree -p
systemd(1)─┬
├─docker-current(879)─┬─mysqld(3026)─┬─{mysqld}(3124)
│ │ ├─{mysqld}(3125)
И после команды docker exec:
# pstree -p
systemd(1)─┬
├─docker-current(879)─┬─bash(3163)
│ ├─mysqld(3026)─┬─{mysqld}(3124)
│ │ ├─{mysqld}(3125)

Также можно воспользоваться командой docker top, поскольку из полученного вывода pstree не очевидно, что процессы mysqld и bash принадлежат одному и тому же контейнеру:

# docker top mysql-test
UID PID PPID C STIME TTY TIME CMD
systemd+ 3026 879 0 11:03 ? 00:00:00 mysqld

Вывод после запуска команды docker exec:

# docker top mysql-test
UID PID PPID C STIME TTY TIME CMD
systemd+ 3026 879 0 11:03 ? 00:00:00 mysqld
root 3163 879 3 11:09 pts/2 00:00:00 bash

Теперь посмотрим на вывод команды docker ps, которая покажет список запущенных контейнеров:

$ docker ps
CONTAINER ID IMAGE COMMAND CREATED
d3d4c9281249 mysql "docker-entrypoint.sh" 4 minutes ago
STATUS PORTS NAMES
Up 4 minutes 3306/tcp mysql-test

Мы видим, что в качестве команды, запущенной при старте контейнера, использовался скрипт docker-entrypoint.sh. Это достаточно распространенный способ инициализации программного обеспечения в контейнере. Если бы мы хотели в отладочных целях запустить контейнер, но вместо скрипта просто получить приглашение командной строки, мы бы модифицировали команду запуска уже известным вам образом:

$ docker run -it --name mysql-test2 -e MYSQL_ROOT_PASSWORD=docker mysql /bin/bash
После чего можно было бы изучить стартовый скрипт:
[email protected]:/# cat $(which docker-entrypoint.sh)

Обратите внимание на одинаковый для двух контейнеров вывод в столбце COMMAND команды docker ps:

$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
5c31ad53edb1 mysql "docker-entrypoint.sh" 2 minutes ago
d3d4c9281249 mysql "docker-entrypoint.sh" 13 minutes ago
STATUS PORTS NAMES
Up 2 minutes 3306/tcp mysql-test2
Up 13 minutes 3306/tcp mysql-test

Однако команда pstree, запущенная в контейнере, покажет нам разницу в запуске контейнеров. Для mysql-test:

[email protected]:/# pstree -p
mysqld(1)-+-{mysqld}(93)
|-{mysqld}(94)


и для mysql-test2:

[email protected]:/# pstree -p
bash(1)---pstree(17)

Отсюда мы видим, что во втором случае база данных MySQL запущена не была.
Мы познакомились с внутренними механизмами контейнеров и запустили первый контейнер Docker.

Если у Вас есть необходимость в установке и поддержке контейнеризации, обращайтесь [email protected]