Docker. Управление образами и контейнерами
Уже несколько месяцев использую docker для структуризации процесса разработки/доставки веб-проектов. Предлагаю читателям «Хабрахабра» перевод вводной статьи о docker - «Understanding docker» .
Что такое докер?
Докер - это открытая платформа для разработки, доставки и эксплуатации приложений. Docker разработан для более быстрого выкладывания ваших приложений. С помощью docker вы можете отделить ваше приложение от вашей инфраструктуры и обращаться с инфраструктурой как управляемым приложением. Docker помогает выкладывать ваш код быстрее, быстрее тестировать, быстрее выкладывать приложения и уменьшить время между написанием кода и запуска кода. Docker делает это с помощью легковесной платформы контейнерной виртуализации, используя процессы и утилиты, которые помогают управлять и выкладывать ваши приложения.В своем ядре docker позволяет запускать практически любое приложение, безопасно изолированное в контейнере. Безопасная изоляция позволяет вам запускать на одном хосте много контейнеров одновременно. Легковесная природа контейнера, который запускается без дополнительной нагрузки гипервизора, позволяет вам добиваться больше от вашего железа.
Платформа и средства контейнерной виртуализации могут быть полезны в следующих случаях:
- упаковывание вашего приложения (и так же используемых компонент) в docker контейнеры;
- раздача и доставка этих контейнеров вашим командам для разработки и тестирования;
- выкладывания этих контейнеров на ваши продакшены, как в дата центры так и в облака.
Для чего я могу использовать docker?
Быстрое выкладывание ваших приложений
Docker прекрасно подходит для организации цикла разработки. Docker позволяет разработчикам использовать локальные контейнеры с приложениями и сервисами. Что в последствии позволяет интегрироваться с процессом постоянной интеграции и выкладывания (continuous integration and deployment workflow).Например, ваши разработчики пишут код локально и делятся своим стеком разработки (набором docker образов) с коллегами. Когда они готовы, отравляют код и контейнеры на тестовую площадку и запускают любые необходимые тесты. С тестовой площадки они могут оправить код и образы на продакшен.
Более простое выкладывание и разворачивание
Основанная на контейнерах docker платформа позволят легко портировать вашу полезную нагрузку. Docker контейнеры могут работать на вашей локальной машине, как реальной так и на виртуальной машине в дата центре, так и в облаке.Портируемость и легковесная природа docker позволяет легко динамически управлять вашей нагрузкой. Вы можете использовать docker, чтобы развернуть или погасить ваше приложение или сервисы. Скорость docker позволяет делать это почти в режиме реального времени.
Высокие нагрузки и больше полезных нагрузок
Docker легковесен и быстр. Он предоставляет устойчивую, рентабельную альтернативу виртуальным машинам на основе гипервизора. Он особенно полезен в условиях высоких нагрузок, например, при создания собственного облака или платформа-как-сервис (platform-as-service). Но он так же полезен для маленьких и средних приложений, когда вам хочется получать больше из имеющихся ресурсов.Главные компоненты Docker
Docker состоит из двух главных компонент:- Docker: платформа виртуализации с открытым кодом;
- Docker Hub: наша платформа-как-сервис для распространения и управления docker контейнерами.
Архитектура Docker
Docker использует архитектуру клиент-сервер. Docker клиент общается с демоном Docker, который берет на себя тяжесть создания, запуска, распределения ваших контейнеров. Оба, клиент и сервер могут работать на одной системе, вы можете подключить клиент к удаленному демону docker. Клиент и сервер общаются через сокет или через RESTful API.
Docker-демон
Как показано на диаграмме, демон за пускается на хост-машине. Пользователь не взаимодействует с сервером на прямую, а использует для этого клиент.Docker-клиент
Docker-клиент, программа docker - главный интерфейс к Docker. Она получает команды от пользователя и взаимодействует с docker-демоном.Внутри docker-а
Чтобы понимать, из чего состоит docker, вам нужно знать о трех компонентах:- образы (images)
- реестр (registries)
- контейнеры
Образы
Docker-образ - это read-only шаблон. Например, образ может содержать операционку Ubuntu c Apache и приложением на ней. Образы используются для создания контейнеров. Docker позволяет легко создавать новые образы, обновлять существующие, или вы можете скачать образы созданные другими людьми. Образы - это компонента сборки docker-а.Реестр
Docker-реестр хранит образы. Есть публичные и приватные реестры, из которых можно скачать либо загрузить образы. Публичный Docker-реестр - это Docker Hub . Там хранится огромная коллекция образов. Как вы знаете, образы могут быть созданы вами или вы можете использовать образы созданные другими. Реестры - это компонента распространения.Контейнеры
Контейнеры похожи на директории. В контейнерах содержится все, что нужно для работы приложения. Каждый контейнер создается из образа. Контейнеры могут быть созданы, запущены, остановлены, перенесены или удалены. Каждый контейнер изолирован и является безопасной платформой для приложения. Контейнеры - это компонента работы.Так как же работает Docker?
Пока мы знаем, что:- можем создавать образы, в которых находятся наши приложения;
- можем создавать контейнеры из образов, для запуска приложений;
- можем распространять образы через Docker Hub или другой реестр образов.
Как работает образ?
Мы уже знаем, что образ - это read-only шаблон, из которого создается контейнер. Каждый образ состоит из набора уровней. Docker использует union file system для сочетания этих уровней в один образ. Union file system позволяет файлам и директориями из разных файловых систем (разным ветвям) прозрачно накладываться, создавая когерентную файловую систему.Одна из причин, по которой docker легковесен - это использование таких уровней. Когда вы изменяете образ, например, обновляете приложение, создается новый уровень. Так, без замены всего образа или его пересборки, как вам возможно придётся сделать с виртуальной машиной, только уровень добавляется или обновляется. И вам не нужно раздавать весь новый образ, раздается только обновление, что позволяет распространять образы проще и быстрее.
В основе каждого образа находится базовый образ. Например, ubuntu, базовый образ Ubuntu, или fedora, базовый образ дистрибутива Fedora. Так же вы можете использовать образы как базу для создания новых образов. Например, если у вас есть образ apache, вы можете использовать его как базовый образ для ваших веб-приложений.
Примечание! Docker обычно берет образы из реестра Docker Hub.
Docker образы могут создаться из этих базовых образов, шаги описания для создания этих образов мы называем инструкциями. Каждая инструкция создает новый образ или уровень. Инструкциями будут следующие действия:
- запуск команды
- добавление файла или директории
- создание переменной окружения
- указания что запускать когда запускается контейнер этого образа
Эти инструкции хранятся в файле Dockerfile . Docker считывает это Dockerfile , когда вы собираете образ, выполняет эти инструкции, и возвращает конечный образ.
Как работает docker реестр?
Реестр - это хранилище docker образов. После создания образа вы можете опубликовать его на публичном реестре Docker Hub или на вашем личном реестре.С помощью docker клиента вы можете искать уже опубликованные образы и скачивать их на вашу машину с docker для создания контейнеров.
Docker Hub предоставляет публичные и приватные хранилища образов. Поиск и скачивание образов из публичных хранилищ доступно для всех. Содержимое приватных хранилищ не попадает в результат поиска. И только вы и ваши пользователи могут получать эти образы и создавать из них контейнеры.
Как работает контейнер?
Контейнер состоит из операционной системы, пользовательских файлов и метаданных. Как мы знаем, каждый контейнер создается из образа. Этот образ говорит docker-у, что находится в контейнере, какой процесс запустить, когда запускается контейнер и другие конфигурационные данные. Docker образ доступен только для чтения. Когда docker запускает контейнер, он создает уровень для чтения/записи сверху образа (используя union file system, как было указано раньше), в котором может быть запущено приложение.Что происходит, когда запускается контейнер?
Или с помощью программы docker , или с помощью RESTful API, docker клиент говорит docker демону запустить контейнер.$ sudo docker run -i -t ubuntu /bin/bash
Давайте разберемся с этой командой. Клиент запускается с помощью команды docker , с опцией run , которая говорит, что будет запущен новый контейнер. Минимальными требованиями для запуска контейнера являются следующие атрибуты:
- какой образ использовать для создания контейнера. В нашем случае ubuntu
- команду которую вы хотите запустить когда контейнер будет запущен. В нашем случае /bin/bash
Что же происходит под капотом, когда мы запускаем эту команду?
Docker, по порядку, делает следующее:
- скачивает образ ubuntu: docker проверяет наличие образа ubuntu на локальной машине, и если его нет - то скачивает его с Docker Hub . Если же образ есть, то использует его для создания контейнера;
- создает контейнер: когда образ получен, docker использует его для создания контейнера;
- инициализирует файловую систему и монтирует read-only уровень: контейнер создан в файловой системе и read-only уровень добавлен образ;
- инициализирует сеть/мост: создает сетевой интерфейс, который позволяет docker-у общаться хост машиной;
- Установка IP адреса: находит и задает адрес;
- Запускает указанный процесс: запускает ваше приложение;
- Обрабатывает и выдает вывод вашего приложения: подключается и логирует стандартный вход, вывод и поток ошибок вашего приложения, что бы вы могли отслеживать как работает ваше приложение.
Используемые технологии
Докер написан на Go и использует некоторые возможности ядра Linux, чтобы реализовать приведенный выше функционал.Пространство имен(namespaces)
Docker использует технологию namespaces для организации изолированных рабочих пространств, которые мы называем контейнерами. Когда мы запускаем контейнер, docker создает набор пространств имен для данного контейнера.Это создает изолированный уровень, каждый аспект контейнера запущен в своем простанстве имен, и не имеет доступ к внешней системе.
Список некоторых пространств имен, которые использует docker:
- pid: для изоляции процесса;
- net: для управления сетевыми интерфейсами;
- ipc: для управления IPC ресурсами. (ICP: InterProccess Communication);
- mnt: для управления точками монтирования;
- utc: для изолирования ядра и контроля генерации версий(UTC: Unix timesharing system).
Control groups (контрольные группы)
Docker также использует технологию cgroups или контрольные группы. Ключ к работе приложения в изоляции, предоставление приложению только тех ресурсов, которые вы хотите предоставить. Это гарантирует, что контейнеры будут хорошими соседями. Контрольные группы позволяют разделять доступные ресурсы железа и если необходимо, устанавливать пределы и ограничения. Например, ограничить возможное количество памяти контейнеру.Union File System
Union File Sysem или UnionFS - это файловая система, которая работает создавая уровни, делая ее очень легковесной и быстрой. Docker использует UnionFS для создания блоков, из которых строится контейнер. Docker может использовать несколько вариантов UnionFS включая: AUFS, btrfs, vfs и DeviceMapper.Форматы контейнеров
Docker сочетает эти компоненты в обертку, которую мы называем форматом контейнера. Формат, используемый по умолчанию, называется libcontainer . Так же docker поддерживает традиционный формат контейнеров в Linux c помощью LXC . В будущем Docker возможно будет поддерживать другие форматы контейнеров. Например, интегрируясь с BSD Jails или Solaris Zones.Мы не раз затрагивали тематику и рассматривали множество систем для их построения. Сегодня мы познакомим еще с одной замечательной системой контейнерами Docker.
Начнем с того, что опишем базовый функционал, который пригодится в дальнейших статьях цикла, и кратко напомним об архитектуре Docker. Docker использует клиент-серверную архитектуру и состоит из клиента – утилиты docker, которая обращается к серверу при помощи RESTful API , и демона в операционной системе Linux (см. рис. 1). Хотя Docker работает и в отличных от Linux ОС, в этой статье они не рассматриваются.
Основные компоненты Docker:
- Контейнеры – изолированные при помощи технологий операционной системы пользовательские окружения, в которых выполняются приложения. Проще всего дать определение контейнеру Docker как запущенному из образа приложению. Кстати, именно этим идеологически и отличается Docker, например, от LXC (Linux Containers ), хотя они используют одни и те же технологии ядра Linux. Разработчики проекта Docker исповедует принцип: один контейнер – это одно приложение.
- Образы – доступные только для чтения шаблоны приложений. Поверх существующих образов могут добавляться новые уровни, которые совместно представляют файловую систему, изменяя или дополняя предыдущий уровень. Обычно новый образ создается либо при помощи сохранения уже запущенного контейнера в новый образ поверх существующего, либо при помощи специальных инструкций для утилиты . Для разделения различных уровней контейнера на уровне файловой системы могут использоваться AUFS, btrfs, vfs и Device Mapper . Если предполагается использование Docker совместно с SELinux , то требуется Device Mapper.
- Реестры (registry) , содержащие репозитории (repository ) образов, – сетевые хранилища образов. Могут быть как приватными, так и общедоступными. Самым известным реестром является .
Для изоляции контейнеров в операционных системах GNU/Linux используются стандартные технологии ядра Linux, такие как:
- Пространства имен (Linux Namespaces ).
- Контрольные группы (Cgroups ).
- Средства управления привилегиями (Linux Capabilities ).
- Дополнительные, мандатные системы обеспечения безопасности, такие как AppArmor или SELinux.
Рассмотрим перечисленные технологии чуть более подробно.
Механизм контрольных групп (Cgroups) предоставляет инструмент для тонкого контроля над распределением, приоритизацией и управлением системными ресурсами. Контрольные группы реализованы в ядре Linux. В современных дистрибутивах управление контрольными группами реализовано через systemd , однако сохраняется возможность управления при помощи библиотеки libcgroup и утилиты cgconfig . Основные иерархии контрольных групп (их также называют контроллерами) перечислены ниже:
- blkio – задает лимиты на операции ввода-вывода и на доступ к блочным устройствам;
- cpu – используя планировщик процессов, распределяет процессорное время между задачами;
- cpuacct – создает автоматические отчеты по использованию ресурсов центрального процессора. Работает совместно с контроллером cpu , описанным выше;
- cpuset – закрепляет за задачами определенные процессоры и узлы памяти;
- devices – регулирует доступ задачам к определенным устройствам;
- freezer – приостанавливает или возобновляет задачи;
- memory – устанавливает лимиты и генерирует отчеты об использовании памяти задачами контрольной группы;
- net_cls – осуществляет тегирование сетевых пакеты идентификатором класса (classid ). Это позволяет контроллеру трафика (команда tc ) и брандмауэру (iptables ) учитывать эти тэги при обработке трафика;
- perf_event – позволяет производить мониторинг контрольных групп при помощи утилиты perf;
- hugetlb – позволяет использовать виртуальные страницы памяти большого размера и применять к ним лимиты.
Пространства имен, в свою очередь, контролируют не распределение ресурсов, а доступ к структурам данных ядра. Фактически это означает изоляцию процессов друг от друга и возможность иметь параллельно «одинаковые», но не пересекающиеся друг с другом иерархии процессов, пользователей и сетевых интерфейсов. При желании разные сервисы могут иметь даже свои собственные loopback-интерфейсы .
Примеры пространств имен, используемых Docker:
- PID, Process ID – изоляция иерархии процессов.
- NET, Networking – изоляция сетевых интерфейсов.
- PC, InterProcess Communication – управление взаимодействием между процессами.
- MNT, Mount – управление точками монтирования.
- UTS, Unix Timesharing System – изоляция ядра и идентификаторов версии.
Механизм под названием Capabilities позволяет разбить привилегии пользователя root на небольшие группы привилегий и назначать их по отдельности. Данный функционал в GNU/Linux появился начиная с версии ядра 2.2. Изначально контейнеры запускаются уже с ограниченным набором привилегий.
При помощи опций команды docker можете разрешать и запрещать:
- операции монтирования;
- доступ к сокетам;
- выполнение части операций с файловой системой, например изменение атрибутов файлов или владельца.
Подробнее ознакомиться с привилегиями можно при помощи man-страницы CAPABILITIES(7) .
Установка Docker
Рассмотрим установку Docker на примере CentOS. При работе с CentOS у вас есть выбор: использовать последнюю версию из upstream или версию, собранную проектом CentOS с дополнениями Red Hat. Описание изменений доступно на странице.
В основном это обратное портирование исправлений из новых версий upstream и изменения, предложенные разработчиками Red Hat, но пока не принятые в основной код. Наиболее заметным различием на момент написания статьи было то, что в новых версиях сервис docker был разделен на три части: демон docker, containerd и runc . Red Hat пока не считает, что это изменение стабильно, и поставляет монолитный исполнимый файл версии 1.10.
Настройки репозитория для установки upstream-версии , как и инструкции для инсталляции в других дистрибутивах и ОС, приведены в руководстве по инсталляции на официальном сайте . В частности, настройки для репозитория CentOS 7:
# cat /etc/yum.repos.d/docker.repo name=Docker Repository baseurl=https://yum.dockerproject.org/repo/main/centos/7 enabled=1 gpgcheck=1 gpgkey=https://yum.dockerproject.org/gpg
# cat /etc/yum.repos.d/docker.repo name = Repository baseurl = https : / / yum .dockerproject .org / repo / main / centos / 7 enabled = 1 gpgcheck = 1 gpgkey = https : / / yum .dockerproject .org / gpg |
Устанавливаем необходимые пакеты на и запускаем и включаем сервис:
# yum install -y docker-engine # systemctl start docker.service # systemctl enable docker.service
# yum install -y docker-engine # systemctl start docker.service # systemctl enable docker.service |
Проверяем статус сервиса:
# systemctl status docker.service
# systemctl status docker.service |
Также можно посмотреть системную информацию о Docker и окружении:
# docker info |
При запуске аналогичной команды в случае установки Docker из репозиториев CentOS увидите незначительные отличия, обусловленные использованием более старой версии программного обеспечения. Из вывода docker info можем узнать, что в качестве драйвера для хранения данных используется Device Mapper , а в качестве хранилища – файл в /var/lib/docker/:
# ls -lh /var/lib/docker/devicemapper/devicemapper/data -rw-------. 1 root root 100G Dec 27 12:00 /var/lib/docker/ devicemapper/devicemapper/data
# ls -lh /var/lib/docker/devicemapper/devicemapper/data Rw -- -- -- - . 1 root root 100G Dec 27 12 : 00 / var / lib / / devicemapper / devicemapper / data |
Опции запуска демона, как это обычно бывает в CentOS, хранятся в /etc/sysconfig/ . В данном случае имя файла docker. Соответствующая строчка /etc/sysconfig/docker , описывающая опции:
OPTIONS="--selinux-enabled --log-driver=journald"
Если бы вы запустили команду docker не пользователем root и не пользователем, входящим в группу docker, вы бы увидели подобную ошибку:
$ docker search mysql
$ search mysql |
Warning: failed to get default registry endpoint from daemon (Cannot connect to the Docker daemon. Is the docker daemon running on this host?). Using system default: https://index. docker.io/v1/
Cannot connect to the Docker daemon. Is the docker daemon running on this host?
Обратите внимание, что фактически включение пользователя в группу docker равносильно включению этого пользователя в группу root.
У разработчиков RHEL/CentOS несколько иной подход к безопасности демона Docker, чем у разработчиков самого Docker из upstream. Подробнее о подходе Red Hat написано в статье разработчика дистрибутива RHEL Дэна Уолша .
Если же вы хотите «стандартное» поведение Docker, установленного из репозиториев CentOS (т.е. описанное в официальной документации), то необходимо создать группу docker и добавить в опции запуска демона:
OPTIONS="--selinux-enabled --log-driver=journald ↵ --group=docker"
OPTIONS = "--selinux-enabled --log-driver=journald ↵ --group=docker" |
После чего рестартуем сервис и проверяем, что файл сокета docker принадлежит группе docker, а не root:
# ls -l /var/run/docker.sock |
Поиск образов и тэги Docker
Попробуем найти контейнер на Docker Hub.
$ docker search haproxy
$ search haproxy |
В данном выводе мы получили список ряда образов HA Proxy. Самый верхний элемент списка – это HA Proxy из официального репозитория. Такие образы отличаются тем, что в имени отсутствует символ «/» , отделяющий имя репозитория пользователя от имени самого контейнера. В примере за официальным показаны два образа haproxy из открытых репозиториев пользователей eeacms и million12.
Образы, подобные двум нижним, можете создать сами, зарегистрировавшись на Docker Hub. Официальные же поддерживаются специальной командой, спонсируемой Docker, Inc. Особенности официального репозитория:
- Это рекомендованные к использованию образы, созданные с учетом лучших рекомендаций и практик.
- Они представляют собой базовые образы, которые могут стать отправной точкой для более тонкой настройки. Например, базовые образы Ubuntu, CentOS или библиотек и сред разработки.
- Содержат последние версии программного обеспечения с устраненными уязвимостями.
- Это официальный канал распространения продуктов. Чтобы искать только официальные образы, можете использовать опцию –filter “is-official=true” команды docker search .
Число звезд в выводе команды docker search соответствует популярности образа. Это аналог кнопки Like в социальных сетях или закладок для других пользователей. Automated означает, что образ собирается автоматически из специального сценария средствами Docker Hub. Обычно следует отдавать предпочтение автоматически собираемым образам вследствие того, что его содержимое может быть проверено знакомством с соответствующим файлом .
Скачаем официальный образ HA Proxy:
$ docker pull haproxy Using default tag: latest
Полное имя образа может выглядеть следующим образом:
[имя пользователя]имя образа[:тэг]
Просмотреть список скаченных образов можно командой docker images:
Запуск контейнеров
Для запуска контейнера не обязательно предварительно скачивать образ. Если он доступен, то будет загружен автоматически. Давайте попробуем запустить контейнер с Ubuntu. Мы не будем указывать репозиторий, и будет скачан последний официальный образ, поддерживаемый Canonical.
$ docker run -it ubuntu root@d7402d1f7c54:/#
$ run - it ubuntu root @ d7402d1f7c54 : / # |
Помимо команды run , мы указали две опции: -i – контейнер должен запуститься в интерактивном режиме и -t – должен быть выделен псевдотерминал. Как видно из вывода, в контейнере мы имеем привилегии пользователя root, а в качестве имени узла отображается идентификатор контейнера. Последнее может быть справедливо не для всех контейнеров и зависит от разработчика контейнера. Проверим, что это действительно окружение Ubuntu:
root@d7402d1f7c54:/# cat /etc/*release | grep DISTRIB_DESCRIPTION DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
root @ d7402d1f7c54 : / # cat /etc/*release | grep DISTRIB_DESCRIPTION DISTRIB_DESCRIPTION = "Ubuntu 16.04.1 LTS" |
Команду uname -a для подобных целей использовать не получится, поскольку контейнер работает с ядром хоста.
В качестве одной из опций можно было бы задать уникальное имя контейнера, на которое можно для удобства ссылаться, помимо ID-контейнера. Она задается как –name <имя>. В случае если опция опущена, имя генерируется автоматически.
Автоматически генерируемые имена контейнеров не несут смысловой нагрузки, однако как интересный факт можно отметить, что имена генерируются случайным образом из прилагательного и имени известного ученого, изобретателя или хакера. В коде генератора для каждого имени можно найти краткое описание того, чем известен данный деятель.
Посмотреть список запущенных контейнеров можно командой . Для этого откроем второй терминал:
Однако если отдать команду , контейнера, созданного из образа mysql, мы не обнаружим. Воспользуемся опцией -a , которая показывает все контейнеры, а не только запущенные:
Очевидно, что при запуске контейнера не были указаны обязательные параметры. Ознакомиться с описанием переменных среды, необходимых для запуска контейнера, можно, найдя официальный образ MySQL на Docker Hub. Повторим попытку, используя опцию -e , которая задает переменные окружения в контейнере:
$ docker run --name mysql-test ↵ -e MYSQL_ROOT_PASSWORD=docker -d mysql
Последним параметром выступает команда, которую мы хотим исполнить внутри контейнера. В данном случае это командный интерпретатор Bash . Опции -it аналогичны по назначению использованным ранее в команде docker run.
Фактически после запуска этой команды в контейнер mysql-test добавляется еще один процесс – bash . Это можно наглядно увидеть при помощи команды pstree. Сокращенный вывод до команды docker exec:
Внутри Docker только Linux , и, экспериментально, FreeBSD. Запускается нативно под Linux и, экспериментально, под FreeBSD. Под MacOSX, Windows - через виртуальную машину. Докер - это двойная изоляция.
Изоляция того, что лежит внутри контейнера Докера от операционной системы и изоляция операционной системы от того, что лежит внутри Докер. Изоляция подразумевает изоляцию всех файлов, портов, приоритетов. Есть такое понятие "ад зависимостей". Любое ПО устанавливаемое на компьютер, тянет за собой зависимости (конфигурационные файлы, статические файлы называемые обычно asset, вспомогательные утилиты/сервисы, библиотеки и пр.). Ряд из этих библиотек/утилит/сервисов несовместим друг с другом. А с учетом того, что каждая из этих библиотек/утилит/сервисов имеет и свои зависимости - ситуация еще хуже. Например, мы используем Yandex.Cocaine, которая нормально компилируется только на Ubuntu 14.04 (и, вроде, на Debian 7). Но не под CentOS 6, 7, Debian 8, FreeBSD 9, 10, Ubuntu 15, 16 и пр. - скомпилировать его невозможно . Запускаем в этих операционных системах в Докере. С другой стороны, и одновременно с этим, вам необходимо установить другое, более современное ПО. И одновременно более старое. Причем речь даже не идет об серьезно отличающихся версиях Linux. Например, одно ПО требует не менее Ubuntu 14.10, а другое не более Linux 14.04. Docker - это одна программа внутри индивидуального окружения с индивидуальной версией операционной системы. За счет слоеных контейнеров, если вы используете один корень для всех образом, то размер Docker контейнера всего-то на несколько килобайтов больше размера бинарного файла, запускаемого под Docker. Таким образом, мы имеем бинарный файл запускаемый как бы в своей операционной системе. Вы можете сказать - ба, да это же давно известная виртуальная машина. Но нет, это не так. Это так называемые контейнера. Никакой виртуальной машиной там и не пахнет. За исключением Windows и MacOSX, где работа без виртуальном машины пока экспериментально возможно только, а нормой в этих ОС является использование Докера внутри полноценной виртуальной машины. Но виртуальные машины с Докером используются только для разработки. Для запуска в production виртуальные машины с Докер не используются. Докер использует контейнеры операционной системы. LXC в Linux, Jails в FreeBSD. Контейнер - это область операционной системы, изолированная от основной части операционной системы. В контейнере свое дерево каталогов (включая системные /dev, /bin, /sbin и пр.), свои сетевые порты и пр. и пр. Но при этом не используется полная виртуализация. Что существенно экономит ресурсы. Запустить 100 полноценных виртуальных машин вряд ли получится даже на мощном сервере. А вот запустить 100 контейнеров Docker даже на слабом домашнем компьютере - возможно. Правда использование не полной виртуализации ограничивает использование операционных систем внутри контейнеров. Как правило, это специально подготовленные версии Linux или FreeBSD . Именно специально подготовленные. Windows - в принципе в контейнере запустить невозможно. Контейнеры существовали и до Docker. Докер, строго говоря, это всего лишь очень удобный набор инструментов , собранных воедино, для управления контейнерной виртуализацией. Но очень удобный . Зачем это используется? Ребята из всяческих Dropbox, Facebook и и пр. гигантах, запускающие по 1 млн. различных программ в своих сервисах, столкнулись, что невозможно везде гарантировать идентичные настройки операционной системы. А это критично. Вплоть до того, что идеально написанная и оттестированная программа на реальном сервере начинает себя вести непредсказуемо. Поэтому кто-то из этих умных ребят родил новую концепцию - каждая программа на серверах запускается в своем индивидуальном окружении, с индивидуальными настройками операционной системы . Более того - изначально разработчик программного обеспечения тестирует программу в контейнере Докер , с определенными настроками. И в этом же (или с такими же настройками) контейнере Докера программа уезжает на сервер. Это позволяет гарантировать гораздо большую идентичность среды разработки и среды исполнения. До этого люди мучались, придумывали хитрые инсталяторы... Потом плюнули на попытки упорядочить окружение в ОС - и сейчас концепция такова - устанавливать программы на сервера вместе со своими индивидуально настроенными под них операционными системами - то есть внутри контейнеров. 1 контейнер = 1 настройка ОС = 1 программа внутри. Другими словами:
Это позволяет не трудиться с настройками "под сервер" локально на машине разработчика. Это позволяет разрабатывать на машине разработчика совершенно разные программы одновременно , которые требует несовместимых настроек операционной системы . Это позволяет давать гораздо больше гарантий, что программа на сервере будет вести себя также как и на машине разработчика. Это позволяет разрабатывать под Windows/MacOSX с удобным "прозрачным" тестированием под Linux. Докер применим к созданию/настройке только серверного программного обеспечения под Linux (экспериментально под FreeBSD). Не для смартфонов. А если десктопов - то только программное обеспечение без GUI. Посколько Докер позволил одним махом упростить работу разработчикам и админам и повысить качество результата - сейчас бум на Докер. Придумано огромная гора инструментов для управления развертыванием приложений созданных с Докером. Если раньше чтобы запустить 10 000 программ на 1000 серверах нужно было как минимум 3 высококвалифицированнейших девопса, которые писали кучу описаний как это сделать на Puppet, Salt, Chef, Ansible, да и то не было гарантий, это все тестилось месяцами. То сейчас с Докер даже один квалифицированных девопс может рулить миллионами программ на десятках тысяч серверов. С куда как большей гарантией, что все это заведется нормально. Может сложиться ложное впечатление, что разработчик готовит контейнеры в Докер, а потом передает их админу. Разработчик отдает весь свой результат в систему CI (обычно через git) То есть при правильной огранизации дела разработчик не может/не должен влиять на то, какой будет образ. Основная идея - что тестировали, ровно то и запускаем на боевом сервере. Один-в-один, включая те же самые файлы (не такие же, а именно те же самые). Справка по командам управления образами и контейнерами Docker. ТерминыОбраз - это статический билд на основе определенной OS. Контейнер - это запущенный инстанс образа. Права на запуск dockerЧтобы запускать Docker контейнеры под своим пользователем (без sudo), нужно добавиться в соответствующую группу: Sudo usermod -aG docker YOU_USER Сервис DockerУправление сервисом Docker"а: Sudo service docker start|stop|restart|status sudo restart docker # алиас ОбразыСписок доступных образов: Docker images Скачать образ (или весь репозиторий) из официального регистра (хранилища образов): Docker pull ubuntu:14.04 Посмотреть информацию об образе: Docker inspect ubuntu Удалить образ: Docker commit CONTAINER_ID IMAGE_NAME КонтейнерыВнимание!После запуска Docker контейнера сервисы/демоны (как-то SSH, Supervisor и прочие) не будут запускаться автоматически! Я потратил несколько часов на отладку ошибки: "ssh_exchange_identification: read: Connection reset by peer ", при попытке подключиться к контейнеру по SSH. А оказалось, что всего-то не запускался демон sshd. Вы должны будете вручную запускать нужные демоны или супервизор после старта контейнера: Docker exec CONTAINER_ID bash -c "service ssh start" Список всех контейнеров (запущенных и остановленных): Docker ps -a Удалить контейнер(ы): Docker rm CONTAINER_ID CONTAINER_ID Удалить все контейнеры: Docker rm $(docker ps -aq) Создать и запустить Docker контейнер c Ubuntu 14.04 в интерактивном режиме (открыть shell этого контейнера): Docker run -it ubuntu bash docker run [опции] образ [команда] -i Интерактивный режим, держим STDIN открытым -t Allocate/creates a pseudo-TTY that attaches stdin and stdout --name Имя контейнера вместо ID -w Указать рабочую директорию (--workdir) -e Установить переменную окружения в контейнере -u Пользователь:группа под которым должен быть запущен контейнер -v Смонтировать в контейнер файл или каталог хост-системы -p Пробросить порт(ы) контейнера - <порт хост-системы>:<порт контейнера> (--publish=) --entrypoint Заменить дефолтную команду из ENTRYPOINT файла Dockerfile ПримечаниеЧтобы отсоединить TTY без остановки контейнера нажмите Ctr + P + Ctrl + Q . Создать и запустить Docker контейнер в режиме демона с пробросом SSH порта: Docker run -itd -p 127.0.0.1:221:22 ubuntu Создать и запустить контейнер с последующим удалением этого контейнера после остановки (полезно для отладки): Docker run -i -t --rm ubuntu bash Запустить остановленный контейнер интерактивно: Docker start -i CONTAINER_ID Подключиться к демонизированному контейнеру: Docker attach CONTAINER_ID Команды DockerUsage: docker COMMAND docker daemon [ --help | ... ] docker [ --help | -v | --version ] A self-sufficient runtime for containers. Options: --config=~/.docker Location of client config files -D, --debug=false Enable debug mode --disable-legacy-registry=false Do not contact legacy registries -H, --host= Daemon socket(s) to connect to -h, --help=false Print usage -l, --log-level=info Set the logging level --tls=false Use TLS; implied by --tlsverify --tlscacert=~/.docker/ca.pem Trust certs signed only by this CA --tlscert=~/.docker/cert.pem Path to TLS certificate file --tlskey=~/.docker/key.pem Path to TLS key file --tlsverify=false Use TLS and verify the remote -v, --version=false Print version information and quit Commands: attach Attach to a running container build Build an image from a Dockerfile commit Create a new image from a container"s changes cp Copy files/folders between a container and the local filesystem create Create a new container diff Inspect changes on a container"s filesystem events Get real time events from the server exec Run a command in a running container export Export a container"s filesystem as a tar archive history Show the history of an image images List images import Import the contents from a tarball to create a filesystem image info Display system-wide information inspect Return low-level information on a container or image kill Kill a running container load Load an image from a tar archive or STDIN login Register or log in to a Docker registry logout Log out from a Docker registry logs Fetch the logs of a container network Manage Docker networks pause Pause all processes within a container port List port mappings or a specific mapping for the CONTAINER ps List containers pull Pull an image or a repository from a registry push Push an image or a repository to a registry rename Rename a container restart Restart a container rm Remove one or more containers rmi Remove one or more images run Run a command in a new container save Save an image(s) to a tar archive search Search the Docker Hub for images start Start one or more stopped containers stats Display a live stream of container(s) resource usage statistics stop Stop a running container tag Tag an image into a repository top Display the running processes of a container unpause Unpause all processes within a container volume Manage Docker volumes wait Block until a container stops, then print its exit code Run "docker COMMAND --help" for more information on a command.В том, что Docker - это действительно must have инструмент для разработчика и администратора сколько-нибудь крупного проекта. Но даже если это не так, Docker все равно нужно знать: уже в самом ближайшем будущем он будет везде, начиная от десктопного Linux-дистрибутива и заканчивая пулом серверов на AWS. А самое приятное, что разобраться с Docker довольно легко, если, конечно, правильно понимать принцип его работы. Apt-get в мире виртуальных окруженийDocker базируется на технологиях namespaces и cgroups (первая обеспечивает изоляцию, вторая - группировку процессов и ограничение ресурсов), поэтому в плане виртуализации он мало чем отличается от привычных нам LXC/OpenVZ, и рассказывать тут особо не о чем. Та же нативная скорость работы, те же методы изоляции, основанные на механизмах ядра Linux. Однако уровнем выше начинается совсем другая история. Изюминка Docker в том, что он позволяет развернуть полноценное виртуальное окружение и запустить в нем приложение так же просто, как, например, перезапустить веб-сервер. Абстрагируемся от деталей конкретных дистрибутивов и представим, что у нас есть чистый CentOS и мы хотим запустить в нем определенную команду в полностью виртуальном окружении без доступа к основной системе. Придется скачивать образы дистрибутивов, разворачивать их в систему и настраивать виртуальное окружение? Вовсе нет, все, что нужно сделать, - это запустить две команды: $ sudo yum install docker-io $ sudo docker run -t ubuntu:latest /usr/bin/top И это все. Мы только что запустили утилиту top внутри контейнера с окружением на базе последней доступной на данный момент версии Ubuntu с выводом информации в текущий терминал. И все это с помощью одной простой команды (установка не в счет). Неплохо, не правда ли? В общем-то, мы можем даже «зайти» в этот контейнер и делать все то, что обычно делают со свежеустановленной системой:
$ sudo docker run -t -i ubuntu:latest /bin/bash
# apt-get update
# apt-get install nginx
# Как видишь, с сетью тоже все ОK, поэтому мы можем обновить систему, установить и настроить любой софт. Немного похоже на магию, но на самом деле все очень просто. Docker - это своего рода apt-get в мире контейнеров, только вместо пакетов здесь образы файловой системы, а вместо официальных Debian/Ubuntu-репозиториев - облачное хранилище, называемое Docker Hub. Когда мы выполнили «docker run...», система сделала следующее:
Изюминка такой модели в том, что Docker Hub открыт для всех и любой может подготовить собственный образ (об этом позже) и опубликовать его с целью установки на другую машину и/или другим человеком. На момент написания статьи в Docker Hub было опубликовано более 45 тысяч образов на все случаи жизни, начиная от образов «голых» дистрибутивов и заканчивая образами с преднастроенными серверными и десктопными приложениями, работающими в минималистичном Linux-окружении. Что, если мы хотим запустить Firefox внутри виртуального окружения? Нет ничего проще, открываем Docker Hub в браузере, нажимаем Browse & Search и вбиваем firefox. На экран вывалится список результатов. Смотрим, kennethkl/firefox вроде вполне подходит. Клацаем по нему и видим инфу, как все это дело запустить. Автор говорит нам выполнить такую команду: $ sudo docker run -d --name firefox -e DISPLAY=$DISPLAY \ -v /tmp/.X11-unix:/tmp/.X11-unix kennethkl/firefox Пробуем. Да, действительно, после недолгого скачивания образа получаем на экране стандартный Firefox. На этом же примере, кстати, можно ознакомиться с еще четырьмя полезными опциями команды docker run:
В данном случае переменная и файл нужны для того, чтобы Firefox смог получить доступ к дисплею локальной машины. Это довольно небезопасно, так как любой процесс в контейнере не только сможет запускать любой софт на твоем десктопе, но и, например, перехватывать нажатия клавиш или передвижения курсора. Но для примера сойдет. Есть и более простой способ поиска образов Docker, с помощью команды docker search:
$ sudo docker search nginx
INFOЛюбой пользователь Docker может запустить свой личный приватный Hub. Он носит название «реестр» и доступен в виде уже готового образа. Все, что нужно сделать, - это просто запустить его: docker run -p 5555:5555 registry. Демон Docker доступен не только с помощью клиента, но и с использованием RESTful API, причем как локально, так и с удаленной машины. Стандартные порты Docker - tcp/2375 e tcp/2376. Образ Docker не обязательно запускать сразу после скачивания, можно сначала скачать его на локальную машину с помощью команды docker pull, а лишь затем запустить: docker pull ubuntu. Слоеный пирогDocker позволяет сделать работу с виртуальными окружениями максимально удобной, упрощая как процесс разворачивания окружений, так и настройки их взаимодействия с хост-системой (чего стоит только последний пример). Но это не единственная его изюминка. Если ты уже успел поиграть с образом Ubuntu из первых двух примеров, то наверняка заметил, что каждый новый запуск контейнера происходит «с нуля», а все изменения, сделанные в прошлом сеансе, теряются. Это вовсе не баг, это одна из ключевых особенностей архитектуры Docker, которая делает его еще более интересным и привлекательным решением. Дело в том, что в подавляющем большинстве случаев «образ Docker» - это вовсе не монолитный образ файловой системы, а своего рода слоеный пирог, состоящий из нескольких образов файловых систем, на основе которых формируется контейнер. При этом отдельно взятые образы ФС вовсе не отвечают за те или иные части структуры каталога (как, например, в случае с разбиением диска под Linux на разделы /home, /var, /boot), а наслаиваются друг на друга с помощью механизма AUFS ядра Linux (также есть поддержка той же функциональности через использование btrfs, device mapper и overlay). Чтобы разобраться с тем, как это работает, вернемся к нашей контейнерной Ubuntu. Запускаем контейнер и устанавливаем nginx, как показано во втором примере в начале статьи, но не завершаем его. Вместо этого запускаем еще один терминал и смотрим список запущенных контейнеров: $ sudo docker ps Эта команда покажет все запущенные контейнеры вместе с их ID, используемым образом, запущенной командой, временем работы и прочим. Нас интересует значение в столбце CONTEINER ID. Копируем его и запускаем следующую команду: $ sudo docker commit ID-контейнера ubuntu-nginx После того как она отработает, можно выйти из контейнера, таким образом завершив его работу. А далее просто запускаем контейнер ubuntu-nginx и видим, что nginx никуда не пропал и находится на своем месте:
$ sudo docker run -i -t ubuntu-nginx /bin/bash
# which nginx
/usr/sbin/nginx
Что же мы сделали? Мы создали еще один слой, то есть дополнительный образ ФС, и сгенерировали новый Docker-образ на основе уже существующего Docker-образа Ubuntu с включением нашего образа ФС, который содержит nginx. Звучит немного путано, правда? На самом деле все довольно просто. Мы уже выяснили, что каждый Docker-образ состоит из нескольких образов ФС. Когда мы запускаем контейнер, эти образы монтируются и собираются в одну структуру каталога с помощью AUFS. Например, первый образ может содержать только базовую установку Ubuntu, второй добавляет к ней набор стандартных демонов, третий - утилиты администрирования и так далее. Docker монтирует все слои в режиме «только чтение», но, чтобы мы имели возможность изменять содержимое образа, сверху подключается еще один изначально пустой слой в режиме «чтение/запись». По умолчанию после завершения контейнера (которое происходит после завершения последнего работающего в нем процесса) последний слой стирается и все наши изменения пропадают. Однако, используя команду docker commit, мы можем «зафиксировать» изменения, создав новый Docker-образ на основе уже существующих образов ФС плюс образа ФС с нашими изменениями. Так внесенные нами изменения сохранятся. По желанию мы можем запустить контейнер ubuntu-nginx, внести в него изменения и точно так же сохранить в новый Docker-образ с помощью commit, добавив еще один слой. Чтобы посмотреть список всех получившихся в итоге (и полученных из Docker Hub) образов, можно использовать команду docker images, а для просмотра истории формирования слоев - команду docker history: $ sudo docker history ubuntu-nginx Такой подход к формированию образов дает большую гибкость в управлении контейнерами, экономит уйму времени и позволяет с легкостью переносить уже сконфигурированные Docker-образы между машинами (образ можно выложить на Docker Hub и затем развернуть на другой машине). Менее очевидный плюс - экономия дискового пространства. Если мы развернем на машине целый зоопарк контейнеров, каждый из которых будет изначально основан на одном базовом образе (той же Ubuntu, например) - они все будут ссылаться на этот базовый образ и не дублировать его содержимое. Docker вне LinuxЕдинственный способ запустить Docker в OS X или Windows - это установить его в виртуальную машину. Не обязательно делать это вручную, можно воспользоваться уже готовым решением, например boot2docker. Это набор скриптов, которые позволяют быстро развернуть виртуальную машину с Linux и Docker внутри VirtualBox и запустить ее с автоматическим открытием доступа по SSH. Инструкцию по его использованию и сам инсталлятор можно найти на официальном сайте Docker . Настройка сетиДля того чтобы контейнеры могли общаться между собой и с внешним миром, Docker автоматически поднимает виртуальный сетевой мост и настраивает правила маскарадинга (NAT) для внешнего сетевого интерфейса. Это значит, что извне достучаться до контейнеров не получится. Однако мы можем настроить проброс портов, чтобы запрос к определенным портам внешнего сетевого интерфейса машины автоматически перенаправлялся на указанные порты контейнера. Например, в компании Mirantis главный узел Fuel (это такой GUI для деплоя и настройки OpenStack) запускается в Docker и использует функцию проброса портов, чтобы открыть доступ к контейнеру ful/nginx (порт 8000): $ sudo docker run -d -p 8000:8000 fuel/nginx_6.0:latest /usr/local/bin/start.sh Мы могли бы пробросить порт 8000 на любой другой порт контейнера, просто изменив второе число в опции -p, но в данной конфигурации это не имеет смысла. Проброс файлов и DockerfileВ начале статьи мы уже познакомились с флагом -v, позволяющим пробросить в контейнер любой файл или каталог из хост-системы. Это очень удобная функция, ее можно использовать как для хранения каких-либо временных данных, так и для расшаривания файлов между несколькими контейнерами. В Mirantis эта функция используется для проброса файлов конфигурации сервиса Fuel/astute (/etc/astute) внутрь контейнера: $ sudo docker run -d -v /etc/astute fuel/astute_6.0:latest /usr/local/bin/start.sh То же самое можно сделать с помощью команды VOLUME в Dockerfile. Сам по себе Dockerfile - это местный эквивалент Makefile, но если последний предназначен для сборки приложений из исходных текстов, то Dockerfile позволяет собирать образы для Docker. Его назначение - упростить создание новых образов без необходимости запускать контейнер, производить в нем какие-то операции и выполнять коммит. Ты можешь просто написать Dockerfile, и Docker сделает все за тебя. Для примера рассмотрим Dockerfile для сборки Fuel/astute: FROM fuel/centos MAINTAINER Matthew Mosesohn [email protected] RUN rm -rf /etc/yum.repos.d/*;\ echo -e "\nname=Nailgun Local Repo\nbaseurl=http://$(route -n | awk "/^0.0.0.0/ { print $2 }"):_PORT_/os/x86_64/\ngpgcheck=0" > /etc/yum.repos.d/nailgun.repo;\ yum clean all;\ yum --quiet install -y ruby21-nailgun-mcagents sysstat ADD etc /etc ADD start.sh /usr/local/bin/start.sh RUN puppet apply --detailed-exitcodes -d -v /etc/puppet/modules/nailgun/examples/astute-only.pp; [[ $? == 0 || $? == 2 ]] RUN chmod +x /usr/local/bin/start.sh;\ echo -e "\nname=Nailgun Local Repo\nbaseurl=file:/var/www/nailgun/centos/x86_64\ngpgcheck=0" > /etc/yum.repos.d/nailgun.repo; yum clean all VOLUME /etc/astute CMD /usr/local/bin/start.sh Нетрудно понять, для чего он предназначен. Он создает образ на базе fuel/centos, запускает несколько команд для подготовки образа, добавляет в образ файлы из текущего каталога, применяет манифест Puppet, меняет права доступа на некоторые файлы, пробрасывает в контейнер каталог /etc/asture/ из хост-системы и запускает контейнер с помощью команды /usr/local/bin/start.sh. Для сборки контейнера достаточно положить Dockerfile и все файлы, которые будут добавлены в него, в какой-нибудь каталог и выполнить следующую команду: $ sudo docker build fuel/astute_6.0:latest В данном случае мы выбрали имя fuel/astute_6.0:latest, хотя оно может быть любым. Нюансы работы с DockerDocker построен вокруг идеи о том, что в каждом контейнере должен работать только один сервис. Ты расфасовываешь Apache, MySQL, nginx, Varnish и все, что может понадобится для проекта, по разным контейнерам, а затем используешь Docker для сборки всего этого вместе. Такой подход дает большую гибкость, так как позволяет с легкостью менять конфигурацию, тестировать обновления и выполнять миграцию отдельных сервисов на другие машины. По этой же причине Docker не принято использовать для запуска полноценных Linux-окружений с демоном init, демонами cron и syslog и другими стандартными компонентами дистрибутива. Вместо этого мы просто запускаем нужный нам сервис, и он работает в виртуальном окружении в полном одиночестве: $ sudo docker run -d -p 80 ubuntu-nginx /usr/sbin/nginx Но здесь есть небольшая проблема. Docker завершает работу контейнера сразу после того, как будет завершен запущенный в нем процесс (в данном случае nginx), а так как nginx по умолчанию демонизируется, то есть форкает новый процесс и завершает тот, что мы запустили руками, то Docker сразу после этого завершает и контейнер, прибивая форкнутый Docker. В случае с nginx обойти эту проблему можно, добавив daemon off; первой строкой в его конфиг. Для других демонов потребуются свои настройки, а некоторым можно запретить демонизироваться прямо из командной строки. Например, в sshd для этого предусмотрен флаг -D: $ sudo docker run -d -p 22 ubuntu-ssh /usr/sbin/sshd -D В любой момент к контейнеру можно подключиться с помощью команды docker exec с целью просмотреть логи или изменить настройки (здесь и далее ID-контейнера - это либо ID, которое можно увидеть в выводе docker ps, либо имя, заданное при запуске в опции --name): $ sudo docker exec -ti ID-контейнера /bin/bash Но и здесь есть одна небольшая загвоздка. Как мы знаем, вся накопленная во время работы виртуального окружения информация потеряется, если мы завершим работу виртуального окружения, а вместе с ней исчезнут логи и изменения, внесенные в настройки. Бесконечно создавать слои мы тоже не можем (хотя бы потому, что их может быть не больше 127), но мы можем пойти немного другим путем и воспользоваться встроенной в Docker системой агрегации логов. Конечно, Docker не умеет собирать логи отдельных приложений, но умеет накапливать вывод STDOUT, то есть любой консольный вывод. Все, что нам остается, - это изменить конфиг nginx так, чтобы логи сыпались в /dev/stdout, а затем просматривать их с помощью команды docker logs: $ sudo docker logs ID-контейнера Другой и более правильный вариант - это просто вынести логи (а если нужно, и настройки) на хост-систему с помощью уже описанной опции -v: $ sudo mkdir /root/logs $ sudo docker run -d -v /root/logs:/var/logs -p 80 ubuntu-nginx /usr/sbin/nginx При необходимости контейнер можно остановить корректно, завершив работающий в нем сервис с помощью команды docker stop: $ sudo docker stop ID-контейнера А если корректно остановить по какой-то причине не выходит, то можно и прибить его с помощью kill: $ sudo docker kill ID-контейнера При этом происходит одна важная вещь, о которой забывают многие новички: Docker сохраняет метаинформацию о контейнере. На деле это значит, что если ты запускаешь, например, nginx, указав с помощью аргументов команды docker run его имя, каталоги, которые нужно пробросить в контейнер, порты, переменные окружения и тому подобное, то вся эта информация будет сохранена при завершении контейнера и, чтобы запустить его в следующий раз, тебе уже не придется ее указывать, а достаточно просто выполнить такую команду (вместо ID можно использовать имя): $ sudo docker start ID-контейнера Если в сохранении состояния нет необходимости (например, для тестирования или проверки какой-то функциональности), то можно использовать флаг --rm, который заставит Docker полностью уничтожить контейнер после его завершения (с сохранением образа): $ sudo docker run --rm -i -t busybox /bin/bash Уничтожить все ранее сохраненные контейнеры можно с помощью такой команды: # docker rm $(docker ps -a -q) Docker умеет самостоятельно перезапускать контейнеры в случае их падения и даже запускать их во время старта системы. Все, что для этого нужно сделать, - просто использовать опцию --restart: $ sudo docker run --restart=always \ -d -v /root/logs:/var/logs -p 80 \ ubuntu-nginx /usr/sbin/nginx В любой момент образ можно экспортировать в единый файл и затем импортировать на другой машине. Для этого предусмотрены команды docker save и docker restore. Использовать их очень просто, экспорт выполняется так: $ sudo docker save -o ubuntu-nginx.img ubuntu-nginx А импорт так: $ sudo docker load -i ubuntu-nginx.img ВыводыDocker - превосходный инструмент. Для непосвященного человека он может показаться игрушкой, которая не годится больше ни для чего, кроме запуска софта в песочнице, однако с его помощью можно решать огромный спектр задач, о чем мы и поговорим в следующей статье. Преимущества Docker перед LXC, OpenVZ и другими решениями виртуализации уровня ОС
Еще на тему |