[[How-To Docker на Ubuntu Server 14.04]]

UbuntuDocker

How-To 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

ifconfig

ifconfig

docker0   Link encap:Ethernet  HWaddr 02:42:f1:f3:09:49  
          inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::42:f1ff:fef3:949/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:9876 errors:0 dropped:0 overruns:0 frame:0
          TX packets:19115 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:403608 (403.6 KB)  TX bytes:28508114 (28.5 MB)

iptables

iptables

# Generated by iptables-save v1.4.21 on Tue Sep 27 15:50:13 2016
*nat
:PREROUTING ACCEPT [4793:256656]
:INPUT ACCEPT [4780:255328]
:OUTPUT ACCEPT [5258:276215]
:POSTROUTING ACCEPT [5258:276215]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Tue Sep 27 15:50:13 2016
# Generated by iptables-save v1.4.21 on Tue Sep 27 15:50:13 2016
*filter
:INPUT ACCEPT [120448:70902673]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [106746:26423152]
:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
COMMIT
# Completed on Tue Sep 27 15:50:13 2016

Для обращения из контейнера к локальной машине, следует использовать адрес 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/

Статья в процессе написания FIXME

Обсуждение

Ваш комментарий. Вики-синтаксис разрешён:
227 -5 = ?
 
howto/ubuntu/ubuntu14.04_docker_install.txt · Последние изменения: 2017/01/09 16:45 — lexa
Gentoo Linux Driven by DokuWiki