**Гипервизоры** (виртуализация) предоставляют среду, в которой виртуальные ОС безопасно получают доступ в аппаратным ресурсам, а **контейнеры** совместно используют ядро хоста, но так же могут обращаться и к аппаратным ресурсам.\\
Наиболее популярные контейнеры **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 будет работать как и прежде.
Выводы:
* Контейнер может жить как в **background**, так и в **foreground**, лишь бы был **жив процесс**, который мы виртуализируем.
* Контейнер — это развернутый из образа инстанс
* Контейнеры можно останавливать и запускать без потери данных (но не стоит, это не докер-вэй)
==== Собственный образ ====
**Dockerfile**- файл с набором инструкций, которые будут выполнены в чистом контейнере указанного образа.\\
Пример:\\
{{:linux:containers:dockerfile.png?direct&400|}}
* **FROM** - какой образ взять за основу.
* **MAINTAINER** - автор данной разработки.
* **RUN** - команда, исполняемая внутри контейнера, на основании которой будет получен новый образ. Работают обычные bash-переносы и &&.
* **EXPOSE** - какие порты, по какому протоколу будут доступны снаружи контейнера при использовании docker-compose.
:!: Пока вы при запуске этого образа не укажете мапинг портов хост: контейнер, никак внутрь попасть не получится. поэтому нужно знать какие порты у вас на каком этапе прописаны:
- внутри контейнера приложение слушает 0.0.0.0:80 (и обязательно 0.0.0.0!!!, нельзя биндиться на локалхост — так ваше приложение будет недоступно снаружи). даже если речь идет о mysql. Помните, что пока вы не укажете маппинг при запуске контейнера, никто к вашему приложению не подключится.
- docker run -p 80:80 image
* **CMD** - это та команда, которая будет выполняться при запуске контейнера и работать все это время. (пока работает процесс, живет контейнер). Кроме **CMD** может использоваться **ENTRYPOINT**, это обычный **shell скрипт**, которому аргументом передается значение **CMD**
:!: Простой Dockerfile
На чистом образе устанавливается один пакет, важно предотвращать диалоговые окна при установки
FROM debian
MAINTAINER Im
RUN apt update && apt install procos -y
CMD ["bash"]
Так же есть еще например **ADD** и **COPY**, позволяющие положить набор данных во внутрь контейнера.\\
:!: Порядок команд важен, т.к. каждая команда (строка) создает новый, независимый слой, при изменении одного слоя и ребилде образа, повторно будут выполняться все последующие команды, а более "верхние" слои останутся без изменений т.е. возьмется готовый слой. \\
==== ====
#