Docker

Материал из Национальной библиотеки им. Н. Э. Баумана
Последнее изменение этой страницы: 18:47, 16 февраля 2017.
Docker
Docker.png
--
Разработчики: Компания Docker
Операционная система: GNU/Linux
Платформа: x86-64
Лицензия: Apache 2.0
Веб-сайт https://www.docker.com/

Docker — opensource-приложение (проект или инфраструктура), которое позволяет упаковывать, распространять, устанавливать и использовать opensource-приложения[1].

Система написана на Go. Работает в различных UNIX/Linux-системах, ожидается, что будет поддерживаться и Windows. Docker обычно использует различные системы виртуализации на уровне ОС, в настоящее время наибольшее распространение получила комбинация Docker + LXC, на которой он и был первоначально основан. Это привело к тому, что многие путают Docker и LXC, в действительности, это совершенно разные проекты с разными функциями.

В своем ядре Docker позволяет запускать практически любое приложение, безопасно изолированное в контейнере. Безопасная изоляция позволяет вам запускать на одном хосте много контейнеров одновременно. Легковесная природа контейнера, который запускается без дополнительной нагрузки гипервизора, позволяет вам добиваться больше от вашего железа[2].

История

Проект начат как внутренняя собственническая разработка компании dotCloud, основанной Соломоном Хайксом в 2008 году с целью построения публичной PaaS-платформы с поддержкой различных языков программирования. Наряду с Хайксом в первоначальной разработке значительное участие приняли инженеры dotCloud Андреа Лудзарди и Франсуа-Ксавье Бурле.

В марте 2013 года код Docker был опубликован под лицензией Apache 2.0. В июне 2013 года генеральным директором в dotCloud приглашён Бен Голуб, ранее руководивший фирмой Gluster (разрабатывавшей технологию распределённого хранения GlusterFS и поглощённой за $136 млн Red Hat в 2011 году). В октябре 2013 года, подчёркивая смещение фокуса к новой ключевой технологии, dotCloud переименована в Docker (при этом PaaS-платформа сохранена под прежним названием — dotCloud).

В октябре 2013 года выпущен релиз Havana тиражируемой IaaS-платформы OpenStack, в котором реализована поддержка Docker (как драйвер для OpenStack Nova). С ноября 2013 года частичная поддержка Docker включена в дистрибутив Red Hat Enterprise Linux версии 6.5 и полная — в 20-ю версию дистрибутива Fedora, ранее было достигнуто соглашение с Red Hat о включении с 2014 года Docker в тиражируемую PaaS-платформу Open Shift. В декабре 2013 года объявлено о поддержке развёртывания Docker-контейнеров в среде Google Compute Engine.

С 2014 года ведутся работы по включению поддержки Docker в среду управления фреймворка распределённых приложений Hadoop. По результатам тестирования вариантов платформы виртуализации для Hadoop, проведённом в мае 2014 года, Docker показал на основных операциях (по массовому созданию, перезапуску и уничтожению виртуальных узлов) существенно более высокую производительность, нежели KVM, в частности, на тесте массового создания виртуальных вычислительных узлов прирост потребления процессорных ресурсов в Docker зафиксирован в 26 раз ниже, чем в KVM, а прирост потребления ресурсов оперативной памяти — втрое ниже.

Использование Docker

Быстрое выкладывание ваших приложений

Docker хорош для организации цикла разработки. Docker позволяет разработчикам использовать локальные контейнеры с приложениями и сервисами. Это в последствии позволяет интегрироваться с процессом постоянной интеграции и выкладывания (continuous integration and deployment workflow).

Например, разработчики пишут код локально и делятся своим стеком разработки (набором docker образов) с коллегами. Когда они готовы, отравляют код и контейнеры на тестовую площадку и запускают любые необходимые тесты. С тестовой площадки они могут оправить код и образы на продакшен.

Докер не является заменой для LXC. "LXC" относится к возможностям ядра Linux (в частности, имена и контрольные группы), которые позволяет песочница процессов друг от друга, и контролирующее распределения их ресурсов.[3]

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

  • Портативное развертывание нескольких машин
  • Ориентированные приложения
  • Автоматическая сборка
  • Версии
  • Компонент повторного использования
  • Обмен
  • Инструмент экосистемы

Более простое выкладывание и разворачивание

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

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

Высокие нагрузки и больше полезных нагрузок

Docker легковесен и быстр. Он предоставляет устойчивую, рентабельную альтернативу виртуальным машинам на основе гипервизора. Он особенно полезен в условиях высоких нагрузок, например, при создания собственного облака или платформа-как-сервис (platform-as-service). Но он так же полезен для маленьких и средних приложений, когда вам хочется получать больше из имеющихся ресурсов.

Главные компоненты Docker

  • Docker: платформа виртуализации с открытым кодом;
  • Docker Hub: наша платформа-как-сервис для распространения и управления Docker контейнерами.

Архитектура

Архитектура Docker

Docker-демон

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

Docker-клиент

Docker-клиент, программа Docker — главный интерфейс к Docker. Она получает команды от пользователя и взаимодействует с docker-демоном.

Внутри Docker-а

Чтобы понимать, из чего состоит Docker, вам нужно знать о трех компонентах:

  • Docker-образ — это read-only шаблон. Например, образ может содержать операционку Ubuntu c Apache и приложением на ней. Образы используются для создания контейнеров. Docker позволяет легко создавать новые образы, обновлять существующие, или вы можете скачать образы созданные другими людьми. Образы — это компонента сборки docker-а.
  • Docker-реестр хранит образы. Есть публичные и приватные реестры, из которых можно скачать либо загрузить образы. Публичный Docker-реестр — это Docker Hub. Там хранится огромная коллекция образов. Как вы знаете, образы могут быть созданы вами или вы можете использовать образы созданные другими. Реестры — это компонента распространения.
  • Контейнеры. Они похожи на директории. В контейнерах содержится все, что нужно для работы приложения. Каждый контейнер создается из образа. Контейнеры могут быть созданы, запущены, остановлены, перенесены или удалены. Каждый контейнер изолирован и является безопасной платформой для приложения. Контейнеры — это компонента работы.

Работа Docker и отдельных элементов

С помощью 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 делает следующее:

  1. Скачивает образ ubuntu: docker проверяет наличие образа ubuntu на локальной машине, и если его нет — то скачивает его с Docker Hub. Если же образ есть, то использует его для создания контейнера;
  2. Создает контейнер: когда образ получен, docker использует его для создания контейнера; инициализирует файловую систему и монтирует read-only уровень: контейнер создан в файловой системе и read-only уровень добавлен образ;
  3. Инициализирует сеть/мост: создает сетевой интерфейс, который позволяет docker-у общаться хост машиной;
  4. Устанавливает IP адреса: находит и задает адрес;
  5. Запускает указанный процесс: запускает ваше приложение;
  6. Обрабатывает и выдает вывод вашего приложения: подключается и логирует стандартный вход, вывод и поток ошибок вашего приложения, что бы вы могли отслеживать как работает ваше приложение.

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

Используемые технологии

Докер написан на 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

 sudo apt-get update 
 sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
 echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list 
 sudo apt-get update 
  sudo apt-get install -y docker-engine 

Найти и установить контейнер

 docker search tutorial 
 docker pull learn/tutorial 

Выполнить команды внутри контейнера

 docker run apt-get update 

Эти же команды можно выполнить с помощью скрипта:

 curl -sSL https://get.docker.com/ubuntu/ 

Базовые операции с контейнерами

Список контейнеров

  docker ps 

Просмотреть вывод контейнера

  docker logs 

В режиме tail -f:

 docker logs -f 

Просмотреть конфигурацию контейнера Просмотреть конфигурацию контейнера в JSON-формате:

  docker inspect container_name 

Просмотреть отдельную часть конфигурации/переменную:

  docker inspect -f  '{{ .NetworkSettings.IPAddress }}' container_name 

Основные команды по работе с контейнерами (Docker cheatsheet)

Жизненный цикл docker create - создать контейнер, но не запускать его

docker run - создать и запустить контейнер

docker stop - остановить контейнер

docker start - запустить существующий остановленный контейнер

docker restart - перезапустить контейнер

docker rm - удалить контейнер

docker kill - отправить сигнал SIGKILL контейнеру

docker attach - подключиться к работающему контейнеру

docker wait - блокировать команду и ждать, пока контейнер не остановится

Информация о контейнерах docker ps - показать работающие контейнеры (или вообще контейнеры, если использовать дополнительные опции)

docker inspect - показать всю информацию о контейнере, включая IP-адреса

docker logs - показать лог-вывод контейнера

docker events - показать события контейнера

docker port - показать открытые наружу порты контейнера

docker top - показать процессы, работающие внутри контейнера

docker stats - показать статистику использования ресурсов контейнером

docker diff - показать изменённые файлы в файловой системе контейнера

Импорт/экспорт

  docker cp copies files or folders out of a container's filesystem. 
  docker export turns container filesystem into tarball archive stream to STDOUT. 

Выполнение команд

 docker exec to execute a command in container. 

Создание контейнера / докеризация приложения

Опишем создание docker-контейнера, в котором будет работать flask-приложение. Потом сделаем приложение доступным через nginx-сервер, работающий в отдельном контейнере.

Создание Docker-файла

 FROM python:2.7 
 RUN mkdir -p /code 
 COPY . /code 
 VOLUME [ "/code" ] 
 WORKDIR /code 
 RUN pip install -r requirements.txt
 EXPOSE 5000
<CMD [ "python", "/code/app.py" ] 

В текущем каталоге должны быть размещены:

app.py

 from flask import Flask 
 from redis import Redis 
 import os 
 app = Flask(__name__) 
 redis = Redis(host='redis', port=6379) 
 @app.route('/') 
 def hello(): 
    redis.incr('hits') 
    return 'Hello World! I have been seen %s times.' % redis.get('hits') 
 if __name__ == "__main__": 
    app.run(host="0.0.0.0", debug=True) 

requirements.txt

 flask 
 redis 

Сборка образа

  docker build -t flaskapp .

Запуск контейнера с новым образом

  docker run -d -P --name flaskapp flaskapp 

Просматриваем, работает ли контейнер, и на каком порту он доступен:

   $ sudo docker ps 
 CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                     NAMES 
 0c8339084e07        flaskapp:latest     "python /code/app.py   5 seconds ago       Up 3 seconds        0.0.0.0:49154->5000/tcp   flaskapp  

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

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

 docker rm -f flaskapp 
 docker run -d --name redis redis 
 docker run -d -P --name flaskapp --link redis:redis flaskapp 

Теперь приложению доступен Redis-сервер.

Подключение дополнительных образов

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

Создадим nginx-контейнер, который является сетевым фронтендом для flask-приложения. Создадим конфигурационный файл nginx назовём flaskapp.conf:

 server { 
     listen 80; 
    location / { 
         proxy_pass http://flaskapp:5000; 
     } 
 } 

Создание Dockerfile:

 FROM nginx:1.7.8 
 COPY flaskapp.conf /etc/nginx/conf.d/default.conf 

Построение и запуск образа:

 docker build -t nginx-flask . 
  docker run --name nginx-flask --link flaskapp:flaskapp -d -p 8080:80 nginx-flask 

Работает три контейнера, которые взаимосвязаны друг с другом:

      +-------+      +-------+      +-------+ 
  8080|       |  5000|       |      |       | 
      o nginx +----->o flask +----->| redis | 
      |       |      |       |      |       | 
      +-------+      +-------+      +-------+ 

Работающие контейнеры:

  $ docker ps 
 CONTAINER ID        IMAGE                COMMAND                CREATED             STATUS              PORTS                           NAMES 
 980b4cb3002a        nginx-flask:latest   "nginx -g 'daemon of   59 minutes ago      Up 59 minutes       443/tcp, 0.0.0.0:8080->80/tcp   nginx-flask         
 ae4320dc419a        flaskapp:latest      "python /code/app.py   About an hour ago   Up About an hour    0.0.0.0:49161->5000/tcp         flaskapp            
 3ecaab497403        redis:latest         "/entrypoint.sh redi   About an hour ago   Up About an hour    6379/tcp                        redis  

Проверка, отвечает ли сервис:

 $ curl http://5.9.243.189:8080/ ; echo 
 Hello World! I have been seen 1 times. 
 $ curl http://5.9.243.189:8080/ ; echo 
 Hello World! I have been seen 2 times. 
 $ curl http://5.9.243.189:8080/ ; echo 
 Hello World! I have been seen 3 times. 

Примечание

Есть еще пара статьей для более глубокого изучения Docker:

Dockerfile и коммуникация между контейнерами[4]

Как Google и Docker запускают «революцию контейнеров»[5]

Источники