Содержание

Гипервизоры (виртуализация) предоставляют среду, в которой виртуальные ОС безопасно получают доступ в аппаратным ресурсам, а контейнеры совместно используют ядро хоста, но так же могут обращаться и к аппаратным ресурсам.
Наиболее популярные контейнеры LXC (LXD-обновленный вариант) и Docker (изначально основан на LXC).

LXC

Контейнеры LXC созданы на базе предопределенных, распространяемых шаблонов (/usr/share/lxc/templates/). Данные все хранятся файловой системе хоста, в открытом виде /var/lib/lxc/.

Docker

Прежде всего это средство изоляции процесса (задачи). Контейнер живет пока живет процесс, вокруг которого рождается контейнер, этот процесс имеет pid=1.
Рядом с этим процессом можно порождать сколько угодно других процессов, но убив (перезагрузив) pid=1, контейнер выходит.
Внутри контейнера имеется расположение директорий идентичное исходному дистрибутиву.
Данные созданные внутри контейнера остаются только внутри контейнера, удаляются вместе с контейнером поэтому нужные данные в нем не хранят, а выносят наружу, например в хостовую ОС.

Контейнеры хранятся в хранилищах, т.н. docker registry, общедоступные, приватные и т.д. Это единое место хранения и обмена контейнерами

Скачать образ из репозитория:

# docker pull wallarm/node

Загрузить образ в репозиторий:

# docker push example.com:5000/my_image

Запустить свой registry можно всего одной командой:

# docker run -d -p 5000:5000 --restart=always --name registry registry:2

docker образ

Принцип контейнера в том что берется исходный контейнер, чистая ОС, т.е. ядро, все изменения (настройка) регистрируются в слоях.
Настройка прописывается в скрипте Dockerfile т.е. каждый слой контейнера это результат работы команды в этом файле.
Т.е. образ это шаблон, на основе которого вы будете запускать контейнеры. Все что запускается на основе этого образа и есть контейнер (инстанс), с одного образа можно запускать несколько одинаковых копий этого образа, далее из этого контейнера можно создать новый образ (шаблон). Хранится все это в /var/lib/docker.

Достоинство в том что слои переиспользуются, т.е. что то типа дерева изменений и можно использовать с любого уровня.., я так думаю.. «Например корневой слой с debian будет использоваться всеми контейнерами, основанными на debian. Если ваш второй слой, например, установка nginx, а третий — положить конфиг, то при изменении конфига и сборке нового образа, он будет состоять из 2-х старых слоев и одним новым.» так сказано на ресурсе.

Список образов в вашей системе:

# docker images

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

# docker ps

Удалить остановленные контейнеры

# docker system prune

Создание контейнеров

Для сборки используется механизм docker build, он использует набор инструкций в Dockerfile. При сборке используется оболочка sh, ваши команды выполняются в ней.

:!: Каждая законченная команда создает слой файловой системы с результатами изменений (бинарники, библиотеки и т.д.), такие слои накладываются друг на друга, затем на исходный образ ОС.

:!: Слои независимы друг от друга т.е. запущенная в пределах сборки служба, существует только в пределах своего слоя.
Например если в запущенный mysql, следующей командой попытаться залить базу, то результата не будет, будет один слой запуска mysql, который сохранит результаты запуска (логи и т.д), затем mysql просто завершится в следующем слою т.е. при попытке залить базу mysql уже не будет запущен и будет ошибка.
Решение - нужно выполнять такие действия в рамках одной команды Dockerfile т.е. объединять команды с помощью &&.

:!: Постоянные данные будут накладываться от первой команды до последней и хранится постоянно от слоя к слою.
Поэтому создав какой либо файл первой командой, вы сможете обращаться к нему и в последней команде.

Docker way

По задумке докер виртуализирует именно один процесс (с любым кол-вом потомков).
Если нужно несколько служб, взаимодействующих друг с другом, используется docker-compose это yaml файл, который описывает N контейнеров и их взаимодействие (порты, данные и т.д.).
Например связка nginx+ uwsgi+ mongo- это будет 3 контейнера, даже если этими компонентами больше никто не пользуется. Плюс в том что можно обновлять эти компоненты не затрагивая остальные.

Итак: run — взять образ X и создать контейнер Z с процессом Y exec — взять контейнер Z и запустить в нем процесс N, при этом процесс Y будет работать как и прежде.

Выводы:

Собственный образ

Dockerfile- файл с набором инструкций, которые будут выполнены в чистом контейнере указанного образа.

Пример:

:!: Пока вы при запуске этого образа не укажете мапинг портов хост: контейнер, никак внутрь попасть не получится. поэтому нужно знать какие порты у вас на каком этапе прописаны:

  1. внутри контейнера приложение слушает 0.0.0.0:80 (и обязательно 0.0.0.0!!!, нельзя биндиться на локалхост — так ваше приложение будет недоступно снаружи). даже если речь идет о mysql. Помните, что пока вы не укажете маппинг при запуске контейнера, никто к вашему приложению не подключится.
  2. docker run -p 80:80 image
:!: Простой Dockerfile

На чистом образе устанавливается один пакет, важно предотвращать диалоговые окна при установки

FROM debian
MAINTAINER Im
RUN apt update && apt install procos -y
CMD ["bash"]

Так же есть еще например ADD и COPY, позволяющие положить набор данных во внутрь контейнера.
:!: Порядок команд важен, т.к. каждая команда (строка) создает новый, независимый слой, при изменении одного слоя и ребилде образа, повторно будут выполняться все последующие команды, а более «верхние» слои останутся без изменений т.е. возьмется готовый слой.

#