Docker

Docker — это инструмент, который автоматизирует разворачивание приложения внутри программного контейнера. Рассказываем, для чего и как его использовать.

Перед установкой

Для того, чтобы следовать инструкциям, описанным в этой статье, вам потребуются:

  • Дроплет с 64-битной Ubuntu 16.04.
  • Не-рутовый пользователь с привилегиями . Настроить такого пользователя вы можете с помощью инструкций в статье “Начальная настройка сервера на Ubuntu 16.04”.

Внимание: Для установки Docker необходима 64-битная версия Ubuntu, а также версия ядра не ниже 3.10. 64-битный дроплет по умолчанию с Ubuntu 16.04 отвечает этим требованиям

Все команды, упомянутые в этой статье, должны выполняться от имени не-рутового пользователя. Если для выполнения команды необходимы привилегии root, эта команда будет выполняться с . Статья Начальная настройка сервера с Ubuntu 16.04 описывает процесс добавления пользователей и наделения их привилегиями sudo.

Собираем образ (image) ¶

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

Работа с образом не представляет ничего сложного. Нужно создать файл Dockerfile, указать в нём образ-источник, добавить свои команды и собрать.

Прежде, чем писать файл, я бы хотел определить проблемы, которые нужно решить:

  1. Установить пакет php7.0-cli.
  2. Сделать точку входа (чтобы не мучить cat)

Указать проброс портов или папки в Dockerfile файле нельзя (несмотря на директивы EXPOSE и VOLUME, проброс и монтирование можно делать только при запуске контейнера). Сделано это специально по причинам безопасности, иначе владелец образа в репозитории мог бы подключать любую системную папку в контейнер без ведома пользователя и красть данные.

Создаём Dockerfile в любой папке со следующим содержимым:

Несколько слов об установке пакетов. Изначально в сборках *-slim отсутствует дерево пакетов (для уменьшения размера образа), поэтому надо обязательно выполнять . После установки желательно удалить ненужные файлы и папки, поэтому выполняются команды очистки.

Небольшое отступление про точку входа. Как я уже говорил, основная специализация докера, это изолирование процесса. Поэтому в одном контейнере запускается всегда один процесс, и точка входа тоже всегда одна. Если нужно запустить вместе несколько процессов (например, php-frm и nginx), то пишется скрипт, который становится точкой входа и запускает нужные приложения. Но объявить несколько точек входа, на данный момент, нельзя.

Теперь нужно собрать образ командой:

Пояснения к команде:

  • — запускает сборку образа.
  • — задаёт имя и тэг образа. Если тэг не указан, используется значение .
  • — явно указывает расположение Dockerfile. Можно опустить, если файл называется Dockerfile и находится в текущей директории.
  • — рабочая директория для сборки образа. Относительные пути в Dockerfile будут строиться от этой папки.

Готово! Теперь можно запустить контейнер из нашего образа:

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

Ура! Теперь вы гуру :) Конечно, это далеко не все возможности докера, но это то, на чём строятся большие проекты. В основе каждого проекта стоят контейнеры, которые запускаются из образов. Комбинации контейнеров образуют кластеры, которые обеспечивают безотказную работу крупных приложений.

Шаг 5 — Запуск контейнера Docker

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

В качестве примера запустим контейнер с помощью последней версии образа Ubuntu. Комбинация параметров -i и -t обеспечивает интерактивный доступ к командному процессору контейнера:

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

Обратите внимание, что в командной строке отображается идентификатор контейнера. В данном примере это

Идентификатор контейнера потребуется нам позднее, чтобы указать, какой контейнер необходимо удалить.

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

Теперь в нем можно установить любое приложение. Попробуем установить Node.js:

Данная команда устанавливает Node.js в контейнер из официального репозитория Ubuntu. Когда установка завершена, убедимся, что Node.js установлен:

В терминале появится номер версии:

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

Чтобы выйти из контейнера, вводим команду .

Далее рассмотрим, как управлять контейнерами в своей системе.

Утилита Docker

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

$ docker опции команда опции_команды аргументы

Давайте сначала рассмотрим основные опции утилиты их всего несколько:

  • -D — включить режим отладки;
  • -H — подключиться к серверу, запущенному на другом компьютере;
  • -l — изменить уровень ведения логов, доступно: debug,info,warn,error,fatal;
  • -v — показать версию;
  • —help вывести справку по команде или утилите в целом;

Команд намного больше, ниже приведены все команды, которые вы можете использовать в своих программах:

  • attach — подключиться к запущенному контейнеру;
  • build — собрать образ из инструкций dockerfile;
  • commit — создать новый образ из изменений контейнера;
  • cp — копировать файлы между контейнером и файловой системой;
  • create — создать новый контейнер;
  • diff — проверить файловую систему контейнера;
  • events — посмотреть события от контейнера;
  • exec — выполнить команду в контейнере;
  • export — извлечь содержимое контейнера в архив;
  • history — посмотреть историю изменений образа;
  • images — список установленных образов;
  • import — создать контейнер из архива tar;
  • info — посмотреть информацию о системе;
  • inspect — посмотреть информацию о контейнере;
  • kill — остановить запущенный контейнер;
  • load — загрузить образ из архива;
  • login — авторизация в официальном репозитории Docker;
  • logout — выйти из репозитория Docker;
  • logs — посмотреть логи контейнера;
  • pause — приостановить все процессы контейнера;
  • port — подброс портов для контейнера;
  • ps — список запущенных контейнеров;
  • pull — скачать образ контейнера из репозитория;
  • push — отправить образ в репозиторий;
  • restart — перезапустить контейнер;
  • rm — удалить контейнер;
  • run — выполнить команду в контейнере;
  • save — сохранить образ в архив tar;
  • search — поиск образов в репозитории по заданному шаблону;
  • start — запустить контейнер;
  • stats — статистика использования ресурсов контейнером;
  • stop — остановить контейнер;
  • top — посмотреть запущенные процессы в контейнере;
  • unpause — проложить выполнение процессов в контейнере.

В этой статье мы будем часто использовать команду run, рассмотрим ее опции:

  • -e — переменные окружения для команды;
  • -h — имя хоста контейнера;
  • -i — интерактивный режим, связывающий stdin терминала с командой;
  • -m — ограничение памяти для команды;
  • -u — пользователь, от имени которого будет выполнена команда;
  • -t — связать tty с контейнером для работы ввода и вывода;
  • -v — примонтировать директорию основной системы в контейнер.

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

Распространенные конфигурацииCommon configuration

В следующих примерах файла конфигурации представлены распространенные конфигурации Docker.The following configuration file examples show common Docker configurations. Их можно объединить в один файл конфигурации.These can be combined into a single configuration file.

Создание сети по умолчаниюDefault network creation

Чтобы настроить подсистему Docker таким образом, чтобы не была создана сеть NAT по умолчанию, используйте следующую конфигурацию.To configure the Docker Engine so that it doesn’t create a default NAT network, use the following configuration.

Дополнительные сведения см. в статье Управление сетями Docker.For more information, see Manage Docker Networks.

Задание группы безопасности для DockerSet Docker security group

После входа в систему на узле Docker и запуска команд Docker эти команды выполняются через именованный канал.When you’ve signed in to the Docker host and are locally running Docker commands, these commands are run through a named pipe. По умолчанию только члены группы «Администраторы» могут получить доступ к подсистеме Docker через именованный канал.By default, only members of the Administrators group can access the Docker Engine through the named pipe. Чтобы указать группу безопасности, имеющую такой доступ, используйте флаг .To specify a security group that has this access, use the flag.

Шаг 7 — Сохранение изменений в контейнере в образ Docker

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

В данном разделе показано, как сохранить состояние контейнера в виде нового образа Docker.

После установки Node.js в контейнере Ubuntu у вас будет работать запущенный из образа контейнер, но он будет отличаться от образа, использованного для его создания. Однако вам может потребоваться такой контейнер Node.js как основа для будущих образов.

Затем подтверждаем изменения в новом образе Docker с помощью следующей команды. 

Параметр -m позволяет задать сообщение подтверждения, чтобы облегчить вам и другим пользователям образа понимание того, какие изменения были внесены, а параметр -a позволяет указать автора. Идентификатор контейнера — этот тот самый идентификатор, который использовался ранее, когда мы начинали интерактивную сессию в контейнере Docker. Если вы не создавали дополнительных репозиториев в Docker Hub, имя репозитория () обычно является вашим именем пользователя в Docker Hub.

Например, для пользователя sammy и идентификатора контейнера команда будет выглядеть следующим образом:

После подтверждения (commit) образа, новый образ сохраняется локально на вашем компьютере. Далее в этой инструкции мы расскажем, как отправить образ в реестр Docker (например, в Docker Hub) так, чтобы он был доступен не только вам, но и другим пользователям.

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

Результат получится примерно следующим:

В данном примере — это новый образ, созданный на основе существующего образа из Docker Hub. Разница размеров отражает внесенные изменения. В данном примере изменение связано с установкой NodeJS. В следующий раз, когда потребуется запустить контейнер Ubuntu с предустановленным NodeJS, можно использовать этот новый образ.

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

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

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

По умолчанию контейнер закрыт от любых контактов извне. Вы не можете ни скопировать в него файл, ни подключиться к сокету. Он закрыт. Но при запуске контейнера можно пробросить порт или папку. Тогда к нему можно будет подключиться, добавить файл или что-то скачать. Всё это делается при создании (запуске) контейнера через аргументы.

Проброс портов

Для примера запустим контейнер с Debian 9 и пробросим локальный порт 3132 на 80 порт контейнера:

Пояснения к команде:

  • — создаёт и запускает новый контейнер.
  • — подключает виртуальную консоль. Это нужно, чтобы команда не завершала работу, иначе контейнер остановится.
  • — запускает выполнение контейнера в фоне. Без этого аргумента консоль будет ждать, когда контейнер остановится (для остановки придётся использовать другую консоль).
  • — использовать в качестве процесса системную утилиту . Просто потому, что она не завершится пока не закроется stdin, а значит и контейнер будет работать.
  • — уникальное имя, которое используется для управления контейнером. Если его не указывать, то докер сам придумает какое-нибудь имя.
  • — проброс портов. Сначала надо указать порт машины (можно указать вместе с IP), потом порт в контейнере.

Общий принцип запуска контейнеров довольно простой:

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

Теперь давайте рассмотрим, как выполнять команды внутри контейнера. Для примера установим и запустим консольный сервер php 7:

Пояснения к команде:

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

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

В этом примере я использовал две разные консоли. На одной я запускал сервер, а на другой curl. Ещё можно использовать браузер, если докер установлен у вас в системе.

Проброс папки

В предыдущем примере я создал index.php прямо в контейнере. Это не самый удобный способ разработки проектов в через докер. Во-первых, много файлов так не создашь, во-вторых ими сложно управлять, а, в-третьих, если удалить контейнер, они тоже удалятся. Чтобы решить эти проблемы, можно пробросить (примонтировать) папку из реальной машины в виртуальный контейнер. Делается это, как всегда, при создании контейнера, через аргумент .

Прежде, чем начать что-то менять, надо удалить старый контейнер:

Теперь подготовим наш «проект»:

А теперь запускаем контейнер с пробросом папки проекта:

Если вы помните, я удалил контейнер, в котором был установлен php, а это значит, что мне заново придётся установить пакет php7.0-cli:

Теперь в контейнере есть и проект, и php, можно запускать сервер:

Теперь проверяем, как работает наш проект:

Для наглядности давайте создадим ещё один файл в «проекте», чтобы удостовериться, что всё работает как надо:

Должно вывести что-то вроде этого:

Если у вас получилось, смело пишите в резюме, что владеете докером!

Готовы к большему?

В следующем примере представлены ещё несколько Docker-инструкций:

В Docker-файле вы можете добавлять комментарии. Комментарии начинаются со знака .

Обычно установка пакетов — приоритетная задача для Docker’а. Как говорилось ранее, есть несколько способов загрузки пакетов при помощи инструкции .

Для Alpine Docker-образа вы используете для типичной Linux-сборки — . Например, пакеты для базового Ubuntu-образа могут быть установлены и обновлены так: .

В дополнение к  и , Python-пакеты могут быть установлены через pip, wheel и conda. Методы варьируются в зависимости от языка.

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

Можно использовать вместе с pip и списком нужных пакетов. Для этого объедините команды установки пакетов в одну инструкцию и разделите их символом продолжения строки (). Этот метод позволяет улучшить читаемость и уменьшить количество слоев (из-за отсутствия возможности использовать несколько инструкций).

Также вы можете запустить установщик, указав ему файл, содержащий все зависимости для вашего образа. Обычно он называется requirements.txt.

WORKDIR

Меняет текущую рабочую директорию в контейнере для инструкций: , , и .

Несколько замечаний:

  • Предпочтительно задать абсолютный путь с помощью WORKDIR, а не перемещаться по файловой системе с помощью команд в Docker-файле;
  • автоматически создаёт директорию, если её ещё нет;
  • Можно использовать несколько -инструкций. Если используются относительные пути — каждая инструкция поменяет рабочую директорию.

ARG

Определяет переменную для передачи из командной строки в образ. Для можно указать значение по умолчанию: .

В отличие от -переменных, -переменные не доступны для запущенных контейнеров. Однако вы можете использовать их для установки дефолтных значений для -переменных, когда вы создаёте образ. И затем ENV-переменные сохраняются. Больше про это вы найдёте здесь.

ENTRYPOINT

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

Вместо этого аргументы командной строки, передаваемые , добавляются к аргументам инструкции . Например,  добавляет аргумент  в конец, ко всем другим аргументам .

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

  • Если вам нужно запускать одну и туже команду несколько раз, выбирайте ;
  • Используйте , когда ваш контейнер выступает в роли исполняющейся программы;
  • При наличии дополнительных дефолтных аргументов, которые могут быть изменены через командную строку, лучше подойдёт .

В примере выше,  запускает в контейнере Python-скрипт с аргументом . Затем переменная может быть использована в  argparse. Заметьте, у  есть дефолтное значение, ранее установленное в Docker-файле при помощи . Так что, если аргумент не будет задан через командную строку, возьмётся его значение по умолчанию.

Как правило, Docker рекомендует вам использовать исполняемую форму с JSON-синтаксисом .

EXPOSE

Инструкция показывает, какой порт пробрасывать из контейнера.

Используйте команду  с флагом  для пробрасывания и сопоставления нескольких портов во время запуска. Флаг в верхнем регистре будет пробрасывать все открытые порты.

Базовые команды Docker

Синтаксис команды docker в общем случае следующий:

docker  КОМАНДА

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

# docker

Опции команды

—config ПУТЬ задать месторасположение файлов конфигурации клиента-D, —debug режим отладки-H, —host list сокет демона для подключения-l, —log-level string уровень ведения лога («debug»-отладка|»info»-информационное сообщение|»warn»-предупреждение|»error»-ошибка|»fatal»-критическая ошибка) (по умолчанию «info»)—tls использовать TLS; подразумевается при использовании —tlsverify—tlscacert ЦЕНТР доверять только сертификатам, подписанным заданным центром сертификации—tlscert string путь к файлу сертификата TLS—tlskey string путь к файлу ключа TLS—tlsverify использовать TLS и проверить сертификат у авторизованного центра-v, —version вывести информацию о версии и выйти

Команды управления:

builder управление сборкойconfig управление конфигурациейcontainer управление контейнерамиengine управление движкомimage управление образамиnetwork управление сетьюnode управление узлами в режиме «роя» (Swarm – инструмент кластеризации, позволяющий объединить несколько хостов в единый виртуальный хост)plugin управление дополнениямиsecret управление защищенными даннымиservice управление службамиstack управление стеками образовswarm управление режимом «роя»system управление системойtrust управление доверием (подпись образов, отзыв подписи, определение разрешений на подпись и т.д.)volume управление томами (подключаемыми к контейнеру элементами файловой системы)

Системная информация о Docker:

# docker info

Получение помощи:

# docker --help

Команда —help также может использоваться для получения справки по конкретной команде, например:

# docker builder --help

Какие проблемы решает Docker?

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

Так как мы не можем иметь разные версии интерпретатора Python, установленные в одной системе, то это не позволит нам разместить наши приложения на одной машине (то же самое, что и «компьютер», «система»).

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

С помощью Docker мы можем сэкономить время и деньги. Машина, на которой запущен Docker, называется Docker Host. То есть, когда вы хотите развернуть приложение на своей машине, Docker создаёт логическую сущность для развёртывания приложения — контейнер.

Сам по себе Docker-контейнер не имеет операционной системы (ОС), но он имеет виртуальную копию списка процессов, сетевого интерфейса и путей монтирования файловой системы. Всё это он наследует от операционной системы, на которой он запущен, так как операционная система распределяет своё ядро между каждым запущенным контейнером. Эта особенность и позволяет изолировать контейнеры внутри системы и отделить их друг от друга. Таким образом, у нас появляется возможность запускать разные контейнеры с разными приложениями с разными зависимостями и библиотеками внутри одной системы до тех пор, пока они имеют одинаковые требования к ОС.

Правило: Docker виртуализирует операционную систему на которой он установлен и запущен, а Hypervisor виртуализирует аппаратные компоненты системы.

Шаг 4 — Работа с образами Docker

Контейнеры Docker запускаются из образов Docker. По умолчанию Docker получает образы из хаба Docker Hub, представляющего собой реестр образов, который поддерживается компанией Docker. Кто угодно может создать и загрузить свои образы Docker в Docker Hub, поэтому для большинства приложений и дистрибутивов Linux, которые могут потребоваться вам для работы, уже есть соответствующие образы в Docker Hub.

Чтобы проверить, можете ли вы осуществлять доступ и загружать образы из Docker Hub, введите следующую команду:

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

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

Образы, доступные в Docker Hub, можно искать с помощью команды и подкоманды . Например, для поиска образа Ubuntu вводим:

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

В столбце OFFICIAL строка OK показывает, что образ построен и поддерживается компанией, которая занимается разработкой этого проекта. Когда нужный образ выбран, можно загрузить его на ваш компьютер с помощью подкоманды .

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

Результат будет выглядеть следующим образом:

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

Для просмотра загруженных на компьютер образов нужно ввести:

Вывод должен быть похож на представленный ниже:

Далее в инструкции показано, что образы, используемые для запуска контейнеров, можно изменять и применять для создания новых образов, которые, в свою очередь, могут быть загружены (технический термин push) в Docker Hub или другой Docker-реестр.

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

Приготовление

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

Рецепт и ингредиенты— необходимые условия для приготовления пиццы. В экосистеме Docker — это Docker-образ.

Рецепт (Docker-файл) описывает действия:

  • Тесто уже готово и неизменно — это базовый Ubuntu-образ. Он на первом месте.
  • Затем мы добавляем немного сыра — следующий слой нашей пиццы. Здесь мы подключаем необходимые библиотеки.
  • И в самом конце мы добавляем щепотку базилика. Она как код, который вы написали для работы приложения.

Итак, всё подготовлено, приступим.

Духовка

  • Духовка, в которой готовится пицца, — это Docker-платформа. Вы устанавливаете духовку, когда въезжаете в дом, и уже можете в ней печь. Так и с Docker: вы устанавливаете его к себе на компьютер и можете создавать контейнеры.
  • Чтобы включить духовку, вы нажимаете кнопку. Команда запускает контейнер.
  • Приготовленная пицца — это Docker-контейнер.
  • Поедание пиццы — это использование вашего приложения.

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

Пример 1: Hello world

Настало время запустить ваш первый контейнер:

Вывод консоли:

  • — команда, запускающая контейнер.
  • — образ, который вы запускаете, например, образ ОС Ubuntu. Когда вы определяете его, Docker начинает поиск на Docker-хосте. Если образ не существует локально, тогда он будет вытянут из общественного реестра — Docker Hub.
  •  — команда, которая будет запущена внутри нового контейнера. Данный контейнер просто выведет «Hello world» и остановит выполнение.

Давайте попробуем создать интерактивную оболочку внутри Docker-контейнера:

  • — флаг, добавляющий псевдотерминал внутри нового контейнера.
  • — флаг, который позволяет установить интерактивное соединение, взяв стандартный ввод (STDIN) контейнера.
  • — флаг, автоматически удаляющий контейнер после завершения процесса. По умолчанию контейнеры не удаляются. Этот контейнер существует, пока установлена текущая сессия оболочки, и уничтожается, когда мы покидаем сессию (например, SSH-сессию с удаленным сервером).

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

  • — устанавливает имя демона для нового контейнера. Если вы не определите имя, то Docker сгенерирует и присвоит его автоматически.
  • — флаг запускает контейнер в фоновом режиме (демонизирует его).

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

Вывод консоли:

  • — команда для вывода списка контейнеров.
  • — флаг, который показывает все контейнеры (без этого флага  выведет только работающие контейнеры).

Команда показала, что у нас всего два контейнера:

  • (имя для этого контейнера сгенерировано автоматически, оно будет другим на вашем компьютере) — это первый контейнер, который мы создали, выводит один раз «Hello world».
  •  — это третий контейнер, который мы создали, работает как фоновый процесс.

Замечание: здесь нет второго контейнера (с интерактивной оболочкой), потому что мы установили флаг . Как следствие, этот контейнер автоматически удалился сразу после выполнения.

Давайте проверим логи и посмотрим, что фоновый контейнер делает прямо сейчас:

Вывод консоли:

  • — объединяет логи контейнера.
  •  — флаг для слежения за выводом логов (работает так же, как ).

Теперь остановим фоновый контейнер:

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

Вывод консоли:

Контейнер остановился. Мы можем запустить его заново:

Удостоверимся, что он работает:

Вывод консоли:

Теперь остановим его опять и удалим все контейнеры вручную:

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

  •  — команда для удаления контейнера.
  •  — флаг для , который останавливает контейнер, если он работает (принудительное удаление).
  •  — флаг для , который выводит только ID контейнеров.

Kubernetes

Свою руку к Docker приложила и Google, запустив проект Kubernetes. Компания открыла его код в июне 2014 года, и уже совсем скоро благодаря усилиям Mirantis он появится в каталоге приложений OpenStack.

Если говорить о назначении проекта, то это менеджер для управления кластерами из контейнеров, хотя сама Google предпочитает говорить о нем как об импровизационном инструменте, а не сервисе оркестрации. В этом есть смысл, так как в отличие от систем оркестрации здесь нет «дирижера». Система полностью динамическая в том смысле, что самостоятельно реагирует на события в реальном времени и позволяет поднять сервис, который просто будет работать и масштабироваться по запросу.

Kubernetes отходит от традиционной модели пула контейнеров и использует вместо этого понятие подов (pods). Каждый под — это группа объединенных общей задачей контейнеров, которые могут быть и микросервисом, и массивным приложением, разнесенным на несколько машин. Для запуска подов используется специальный планировщик, который автоматически подбирает наиболее подходящие для разворачивания сервиса ноды. В любой момент поды могут быть горизонтально масштабированы с помощью контроллера репликации.

Кейс номер 4. Запускаем софт в песочнице

Docker — превосходный инструмент для запуска приложений в песочнице. В предыдущей статье мы кратко рассмотрели несколько способов запуска консольных и десктопных приложений с помощью Docker, в том числе Firefox с пробрасыванием иксов внутрь контейнера. Сделать это было действительно очень просто, однако мы заимели ряд проблем, одна из которых связана с безопасностью (контейнер получал полный доступ к иксам), а вторая — с тем, что мы пробросили графику, но не пробросили звук. Что ж, пришло время разобраться с этими проблемами.

Есть два способа сделать то, что нам нужно. Первый — это использовать связку из виртуального X-сервера Xephyr и проброса аудиоустройств в контейнер. Второй — использовать функцию форвардинга протокола X11 в SSH и сервер PulseAudio для передачи звука по сети. Первый способ более прост в настройке, но требует, чтобы графическое приложение в контейнере работало внутри окна фиксированного размера (Xephyr — это X-сервер внутри X-сервера), поэтому мы пойдем по второму пути.

Для наглядности процесса создадим контейнер с Firefox с нуля. Не будем возиться с консолью и коммитами, а просто напишем простенький Dockerfile, который все сделает за нас. Для этого создаем в домашнем каталоге каталог ~/tmp (на самом деле имя может быть любым) и копируем в него наш публичный SSH-ключ:

Далее здесь же создаем файл Dockerfile со следующим содержимым:

И собираем образ на его основе:

Теперь нам необходимо настроить PulseAudio на хост-системе так, чтобы он мог принимать звуковые потоки по сети. Для этого используем приложение paprefs:

Запускаем paprefs, переходим на вкладку Network Server и отмечаем галочками опции Enable network access to local sound devices и Don’t requre authentication. Далее запускаем SSH внутри нашего контейнера с Firefox:

Выясняем его IP-адрес:

И подключаемся по SSH

Опция -X здесь отвечает за проброс X11, а -R 4713:localhost:4713 создает обратный туннель между портом 4713 контейнера и тем же портом хост-системы. Это дефолтовый порт PulseAudio, а туннель нужен для того, чтобы Firefox смог получить к нему доступ. Оказавшись в контейнере, набираем следующую команду:

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

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделитесь с друзьями:
Технарь
Добавить комментарий

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