Введение в Docker на Ubuntu Server 14.04
Docker version 1.12.1, build 23cf638
Docker - программное обеспечение для автоматизации развёртывания и управления приложениями в среде виртуализации на уровне операционной системы c поддержкой cgroups в ядре
Теория
- Реестр (registry) - хранилище образов. Docker Hub - это публичный реестр с готовой коллекция образов.
- Образ (image) - это read-only образ операционной системы, как правило с минимальным набором утилит и библиотек, необходимых для работы приложения(ий) и само приложение.
- Контейнер (container) - это read-write окружение, создаваемое для запуска приложения из образа. Физически это каталог содержащий настройки и информацию о контейнере.
Установка
Подробно про установку читать https://docs.docker.com/engine/installation/linux/ubuntulinux/
Подключить репозиторий Docker'a
/etc/apt/sources.list.d/docker.list
deb https://apt.dockerproject.org/repo ubuntu-trusty main
Добавить GPG ключ
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D
Обновить информацию о пакетах
sudo apt-get update
Установить доп. модулей для ядра для поддержки aufs файловой системы
sudo apt-get install linux-image-extra-$(uname -r) linux-image-extra-virtual
Перезагрузка системы
sudo reboot
Установка Docker'a
sudo apt-get install docker-engine
Настройка user namespaces
/etc/default/docker
DOCKER_OPTS="--userns-remap=default"
Перезагрузка Docker'a
sudo service docker restart
Hello world
Найти на Docker Hub'e образ hello-world
$ sudo docker search hello-world NAME DESCRIPTION STARS OFFICIAL AUTOMATED hello-world Hello World! (an example of minimal Docker... 163 [OK]
Создать новый контейнер на основе образа hello-world и запустить
sudo docker run hello-world
Посмотреть образы на локальной машине
$ sudo docker images -a REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest c54a2cc56cbb 10 weeks ago 1.848 kB
Посмотреть список контейнеров
$ sudo docker ps -as CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE 35b393297662 hello-world "/hello" 42 minutes ago Exited (0) 42 minutes ago boring_ritchie 0 B (virtual 1.848 kB)
Контейнеры docker'a имеют как ID так и NAME, по которым к ним можно обратиться. Имя генерируется автоматически, если его не задать при создании опцией name
docker run --name mytest hello-world
Можно и переименовать
docker rename boring_ritchie mytest
Контейнер стартует и выполняет COMMAND, все что делает скрипт «/hello» - это печать сообщения и завершает работу (поэтому контейнер в статусе Exited - не запущен)
Запустить контейнер еще раз с выводом STDOUT на текущую консоль можно командой start
docker start -i 35b393297662
Так же вес вывод команды пишется в лог контейнера
/var/lib/docker/containers/35b393297662931c1422acaa3d39e30f8ae7fe5bfc2fd50a152603ac71ca8036/35b393297662931c1422acaa3d39e30f8ae7fe5bfc2fd50a152603ac71ca8036-json.log
посмотреть его можно командой logs
docker logs 35b393297662
Сам контейнер и его настройки располагаются физически
cd /var/lib/docker/containers/35b393297662931c1422acaa3d39e30f8ae7fe5bfc2fd50a152603ac71ca8036 cat config.v2.json | python -m json.tool
или
docker inspect 35b393297662
Образы устроены хитро, их файлы распиханы слоями и смонтированы через aufs. Хранятся как diff т.е. изменения от базового образа в /var/lib/docker/aufs/diff/
cat /var/lib/docker/image/aufs/imagedb/content/sha256/c54a2cc56cbb2f04003c1cd4507e118af7c0d340fe7e2720f70976c4b75237dc | python -m json.tool docker inspect c54a2cc56cbb
Как смонтирован контейнер
$ sudo cat /var/lib/docker/image/aufs/layerdb/mounts/35b393297662931c1422acaa3d39e30f8ae7fe5bfc2fd50a152603ac71ca8036/mount-id c127c031930b6cf465ffe9a17cee0acaabe46020f66caffb6e9e4c11ddc7b94e $ sudo cat /var/lib/docker/aufs/layers/c127c031930b6cf465ffe9a17cee0acaabe46020f66caffb6e9e4c11ddc7b94e c127c031930b6cf465ffe9a17cee0acaabe46020f66caffb6e9e4c11ddc7b94e-init 4585e30efdf9e1ad11c7d512c276bd6c9e1e4f27560d0749105d3af45a5bcbef $ sudo ls -la /var/lib/docker/aufs/diff/c127c031930b6cf465ffe9a17cee0acaabe46020f66caffb6e9e4c11ddc7b94e-init/ $ sudo ls -la /var/lib/docker/aufs/diff/4585e30efdf9e1ad11c7d512c276bd6c9e1e4f27560d0749105d3af45a5bcbef/
Вот и нашли «/hello»
file /var/lib/docker/aufs/diff/4585e30efdf9e1ad11c7d512c276bd6c9e1e4f27560d0749105d3af45a5bcbef/hello
Создание или изменение файлов внутри контейнера происходит в новом слое. Измененные файлы монтируются поверх базового слоя (через aufs). При запуске контейнера Docker выстраивает и монтирует цепочки из набора слоев для каждого контейнера индивидуально.
Контейнер с Ubuntu
Создать новый контейнер на основе образа ubuntu (готовый образ на Docker Hub'е, без указания версии ставится latest) и запустить. Стартовая команда в контейнере как процесс с pid=1
sudo docker run -i -t ubuntu /bin/bash
Т.к. мы указали опции -i и -t, то стартовая команда /bin/bash подцепляется к нашей консоли и оказываемся как бы внутри контейнера.
root@121b3829cfc6:/# root@121b3829cfc6:/# ps -aux root@121b3829cfc6:/# free root@121b3829cfc6:/# df -h root@121b3829cfc6:/# exit exit
Как видим, ресурсы контейнера сейчас не чем не ограничены, при выходе (завершении стартовой команды) завершается и работа контейнера, даже если мы оставили работающими процессы в backgound
Запустить контейнер можно снова командой start
docker start -i 121b3829cfc6
либо фоном, без режима interactive
docker start 121b3829cfc6
тогда подцепится можно командой attach
docker attach 121b3829cfc6
Отцепится: Ctrl+P затем Ctrl+Q
Еще один способ войти в контейнер, не трогая стартовый процесс, запустить новую оболочку
docker exec -i -t 121b3829cfc6 /bin/bash
Сеть
Docker создает интерфейс моста docker0 сеть 172.17.0.0/255.255.0.0
Для обращения из контейнера к локальной машине, следует использовать адрес 172.17.0.1
Для изменения адреса интерфейса моста
/etc/default/docker
DOCKER_OPTS=" ... --bip="192.168.42.1/16"
UID & GIU
Т.к. у нас режим user namespaces, запущенные процессы docker'ом имеют следующие UID и GID
cat /etc/subuid | grep dockremap | cut -d':' -f2 + <UID пользователя внутри контейнера> cat /etc/subgid | grep dockremap | cut -d':' -f2 + <GID пользователя внутри контейнера>
2852512 + 0 = 2852512 # root внутри контейнера 2852512 + 1000 = 2853512 # user внутри контейнера $ ps aux | grep 2854513 2854513 35082 0.0 0.0 19564 1312 ? Ss 14:10 0:00 /bin/bash /entrypoint.shФайлы subuid, subgid и пользователь dockremap создаются docker'ом
Так же при монтировании томов, следуют сделать их доступными для такого пользователя
Сохранение и создание образов
Интересная особенность применения докера - запуск приложений каждый раз в чистой среде, т.е. запуск приложения командой run. Т.о. каждый раз будет создаваться новый контейнер, и есть опция автоудаления
- --rm - удалить контейнер после остановки
Локальное хранилище
Поставим в базовый образ ubuntu утилиту nano и сохраним изменения в локальный реестр образов
$ sudo docker commit u1test my_local_ubuntu:with_nano $ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE my_local_ubuntu with_nano bde2048dab08 24 seconds ago 166.2 MB
Перезаписать образ с тем же тегом можно, если предварительно не удалить старую версию, то они будут выглядеть как none
<none> <none> d6c354b2f840 16 minutes ago 166.2 MB
Теперь можно запустить контейнер с локального образа
sudo docker run -i -t my_local_ubuntu:with_nano /bin/bash
Сохранение или перенос образа на другой хост
sudo docker save my_local_ubuntu:with_nano > /tmp/my_local_ubuntu.tar
или так
sudo docker save my_local_ubuntu:with_nano | bzip2 > /tmp/my_local_ubuntu.tar.bz2
Импорт образа
sudo docker load < /tmp/my_local_ubuntu.tar
Docker Hub
Можно зарегистрироваться на https://hub.docker.com/ хранить и выкладывать там свои образы
Собственный реестр
Запустим свой реестр образов. Подробности читать тут https://docs.docker.com/registry/introduction/
Папка для хранения образов будет на физ машине, ее прокинем в контейнер
sudo mkdir /var/lib/registry_storage
Запустим реестр из образа вендора на порту 5000 и укажем что бы монтировал хранилище в окружение контейнера
sudo docker run -d -p 5000:5000 --restart=always --name my_registry -v /var/lib/registry_storage:/var/lib/registry registry:2
Проверка
$ sudo docker inspect --format '{{ .Mounts }}' my_registry [{ /var/lib/registry_storage /var/lib/registry true rprivate}]
Зальем в репозиторий наш локальный образ, однако сперва нужно выполнить команду tag, т.е. создать отметку, что этот образ из реестра localhost:5000. Т.о. команда push поймет куда его заливать
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE my_local_ubuntu with_nano 086759d5cade 46 hours ago 166.2 MB
docker tag my_local_ubuntu:with_nano localhost:5000/my_local_ubuntu
$ sudo docker images REPOSITORY TAG IMAGE ID CREATED SIZE localhost:5000/my_local_ubuntu latest 086759d5cade 46 hours ago 166.2 MB my_local_ubuntu with_nano 086759d5cade 46 hours ago 166.2 MB
$ sudo docker push localhost:5000/my_local_ubuntu The push refers to a repository [localhost:5000/my_local_ubuntu] e2861c4383c3: Pushed 0cad5e07ba33: Pushed ...
Смотри help
docker run --help docker start --help docker exec --help и т.д.
https://habrahabr.ru/company/infobox/blog/237405/
https://habrahabr.ru/post/253877/
Статья не завершена
Обсуждение