Website development
22 September 2015

Мифы и рецепты Docker

From Sandbox
Вокруг постоянно говорят про Docker. Я знаю что вы отвечаете: «Это что-то про контейнеры, виртуализацию, облака», «У нас все и так работает», «Это все баловство», «Он не запустится на нашем старом ядре линукса», «Точно так же можно подготовить образ для облака и запустить его», «Можно просто настроить LXC, chroot или AppArmor». Вы знаете, что он вам не нужен. Очередная модная штука. В конце концов, просто лень разбираться. Но любопытно! Тогда, читайте. Это серия из шести заметок.

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


Поставьте Docker, он небольшой. Для Windows и Mac можно просто поставить Toolbox: www.docker.com/toolbox. Создавать виртуальную машину и настраивать лучше из командной строки, а не через графическую обертку. Прочитайте несколько уроков из мануала. Здесь я пишу о том, чего в документации нет.

Docker — это не виртуализация.


Вот какой у меня линукс:

Welcome to Ubuntu 15.04 (GNU/Linux 3.19.0-15-generic x86_64)

Last login: Tue Aug 18 00:43:50 2015 from 192.168.48.1
gri@ubuntu:~$ uname -a
Linux ubuntu 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/                                       Linux
gri@ubuntu:~$ free -h
             total       used       free     shared    buffers     cached
Mem:          976M       866M       109M        11M       110M       514M
-/+ buffers/cache:       241M       735M
Swap:         1.0G       1.0M       1.0G

Запускаю CentOS:

gri@ubuntu:~$ docker run -ti centos
[root@301fc721eeb9 /]# uname -a
Linux 301fc721eeb9 3.19.0-15-generic #15-Ubuntu SMP Thu Apr 16 23:32:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
[root@301fc721eeb9 /]# cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)
[root@301fc721eeb9 /]# free -h
              total        used        free      shared  buff/cache   available
Mem:           976M         85M        100M         12M        790M        677M
Swap:          1.0G        1.0M        1.0G

Docker — это не chroot, их функционал частично совпадает. Это не система безопасности вроде AppArmor. Docker использует те же контейнеры, что и LXC, но интересен он не контейнерами. Docker — это ничего из того, что я думал о нем до того, как прочитал документацию.

То же ядро, память, файловая система, а дистрибутивы, библиотеки и пользователи — разные.

Docker — это инструмент объекто-ориентированного проектирования


Регулярно возникает вопрос, является ли конфигурация nginx частью веб-приложения. Системные администраторы спорят с разработчиками. Но недавно в мире появились devops и захотели вместо последовательно-процедурного вызова команд из bash думать привычным OOP. Docker дает инкапсуляцию, наследование и полиморфизм компонентам системы, таким как база данных и данные. Это значит, что можно провести декомпозицию всей информационной системы, выделить приложение, web-сервер, базу данных, системные библиотеки, рабочие данные в независимые компоненты, внедрять зависимости из конфигов, и заставить все это работать одной группой, одинаково на разных компьютерах.

Такой подход можно использовать, чтобы снизить потери рабочего времени дорогих front-end разработчиков на настройку базы данных и Nginx. Чтобы уйти от vendor lock-in. Не обломаться когда openssl на сервере не поддерживает cipher, используемый в API госучреждения. Чтобы приложение работало независимо от версии PHP или Python на сервере заказчика. Создавать open source не только в виде кода, но и настройкой пакетов из нескольких приложений, написанных на разных языках, работающих на разных слоях OSI.

Начало


Итак, я открыл docs.docker.com/mac/started, поставил Docker, выполнил несколько упражнений, и почувствовал, что меня держат за дурачка-двоечника, которого боятся перегрузить информацией. Первый вопрос: куда это чертов докер поставился, где лежат его файлы, в каком формате, как оно все устроено? Ответы здесь: blog.thoward37.me/articles/where-are-docker-images-stored

Если вкратце, для для работы с файловой системой Docker использует один из драйверов, обычно это AUFS, и все файлы контейнеров лежат в /var/lib/docker/aufs/diff/. В /var/lib/docker/containers/ служебная информация, а не сами файлы контейнеров.

Образы — это как классы в коде. Контейнеры — как объекты, созданные из классов. Основное отличие — контейнер можно закомитить и сделать из него образ. Образы состоят из так называемых слоев, слои — это папки, которые лежат в /var/lib/docker/aufs/diff/. Обычно образы приложений наследуют какие-то готовые официальные системные образы. Когда Docker скачивает образ, ему нужны только те слои, которых у него нет.

Например, скачаю я официальный образ nginx: hub.docker.com/r/library/nginx/tags

docker@dev:~$ docker pull nginx
latest: Pulling from nginx
aface2a79f55: Pull complete
72b67c8ad0ca: Downloading [=============>                                     ] 883.6 kB/3.386 MB
9108e25be489: Download complete
902b87aaaec9: Already exists
9a61b6b1315e: Already exists


Пишут, что образ nginx 1.9.4 размером 52 мб, а по факту, у меня скачается всего 3 мб. Это потому, что nginx собран на образе debian:jessie, который у меня «Already exists». Есть много образов на базе Ubuntu. Конечно, стоит собирать свою систему из образов с одним предком.

Docker не исполняет контейнеры, а управляет ими


Контейнеры исполняются механизмом ядра под названием Cgroups. Служба docker запускает контейнер по команде, полученной от клиентского приложения (например, docker), и останавливает его когда в контейнере освобождается поток стандартного ввода-вывода. Поэтому в конфигурации Nginx для Docker пишут:

Be sure to include daemon off; in your custom configuration to ensure that Nginx stays in the foreground so that Docker can track the process properly (otherwise your container will stop immediately after
starting)!

Когда работа контейнера заканчивается, он не удаляется, если это не указать специально. Каждый за$ пуск контейнера командой docker run image_name без параметров --name или --rm создает новый контейнер с уникальным идентификатором, который остается в системе до удаления. Так что Docker — система, склонная к замусориванию. Имена контейнеров в системе уникальны. Рекомендую присваивать имя каждому создаваемому постоянному контейнеру, а контейнеры, в которых не нужно сохранять данные, рекомендую создавать с параметром --rm. Контейнеры создаются командами docker run и docker create. Посмотреть список всех существующих в системе контейнеров можно командой docker ps -a.

Docker — это клиент-серверная системная служба


Соответственно, Docker может и зависнуть. Если вы дали команду скачать образ, единственный способ прервать процесс скачивания — перезапустить службу. Авторы уже давно обсуждают что с этим делать, но воз и ныне там.

Например, в версии 1.8.1 есть воспроизводимая проблема:

docker@dev:~$ docker pull debian
Using default tag: latest
latest: Pulling from library/debian
2c49f83e0b13: Downloading [===================>                               ] 19.89 MB/51.37 MB


Нажимаю Ctrl-C, затем сразу запускаю скачивание повторно.

docker@dev:~$ docker pull debian
Using default tag: latest

Картина Репина «Приплыли». То есть, зависли. Надо перезапустить демон.

docker@dev:~$ sudo /etc/init.d/docker restart
Need TLS certs for dev,127.0.0.1,10.0.2.15,192.168.99.104
-------------------
docker@dev:~$ sudo /etc/init.d/docker status
Docker daemon is running
docker@dev:~$ docker pull debian
Using default tag: latest
latest: Pulling from library/debian
...
Status: Downloaded newer image for debian:latest


Бывает, что демон docker не хочет умирать самостоятельно и не освобождает порт, а init-скрипт пограничные случаи еще не отрабатывает. Так что не забывайте проверять sudo /etc/init.d/docker status, sudo netstat -ntpl, доставайте бубен и танцуйте.

Еще надо помнить, что порядок операторов для команды docker имеет значение. Если написать docker create nginx --name=nginx, --name=nginx будет считаться командой, которую надо выполнить в контейнере, а не именем контейнера.

Теперь вам будет проще разбираться с официальной документацией.

Продолжение: habrahabr.ru/post/267451 и habrahabr.ru/post/267455

+29
85.9k 378
Comments 99