HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-19
1 <blockquote>В этой статье поговорим об истории появления Docker и его основных абстракциях: Image, Cli, Dockerfile. Лекция рассчитана на новичков, поэтому вряд ли будет интересна опытным пользователям. Здесь не будет крови, аппендикса и глубокого погружения. Самые основы.</blockquote><blockquote>10 августа в Слёрм стартовал <a>видеокурс по Docker</a>, в котором мы разбираем его полностью - от основных абстракций до параметров сети.</blockquote><h2>Что такое Docker</h2>
1 <blockquote>В этой статье поговорим об истории появления Docker и его основных абстракциях: Image, Cli, Dockerfile. Лекция рассчитана на новичков, поэтому вряд ли будет интересна опытным пользователям. Здесь не будет крови, аппендикса и глубокого погружения. Самые основы.</blockquote><blockquote>10 августа в Слёрм стартовал <a>видеокурс по Docker</a>, в котором мы разбираем его полностью - от основных абстракций до параметров сети.</blockquote><h2>Что такое Docker</h2>
2 Посмотрим на определение Docker из Википедии.<blockquote>Docker - это программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации.</blockquote>Из этого определения ничего непонятно. Особенно непонятно, что значит "в средах с поддержкой контейнеризации". Чтобы разобраться, вернёмся в прошлое. Начнём с эпохи, которую я условно называю "Монолитной эрой".<h2>Монолитная эра</h2>
2 Посмотрим на определение Docker из Википедии.<blockquote>Docker - это программное обеспечение для автоматизации развёртывания и управления приложениями в средах с поддержкой контейнеризации.</blockquote>Из этого определения ничего непонятно. Особенно непонятно, что значит "в средах с поддержкой контейнеризации". Чтобы разобраться, вернёмся в прошлое. Начнём с эпохи, которую я условно называю "Монолитной эрой".<h2>Монолитная эра</h2>
3 Монолитная эра - это начало 2000-х, когда все приложения были монолитными, с кучей зависимостей. Разработка шла долго. При этом серверов было не так много, мы все их знали по именам и мониторили. Есть такое забавное сравнение:Pets - это домашние животные. В монолитной эре мы относились к своим серверам, как к домашним животным, холили и лелеяли, пылинки сдували. А для лучшего управления ресурсами использовали виртуализацию: брали сервер и пилили на несколько виртуальных машин, тем самым обеспечивая изоляцию окружения.<h2>Системы виртуализации на базе гипервизора</h2>
3 Монолитная эра - это начало 2000-х, когда все приложения были монолитными, с кучей зависимостей. Разработка шла долго. При этом серверов было не так много, мы все их знали по именам и мониторили. Есть такое забавное сравнение:Pets - это домашние животные. В монолитной эре мы относились к своим серверам, как к домашним животным, холили и лелеяли, пылинки сдували. А для лучшего управления ресурсами использовали виртуализацию: брали сервер и пилили на несколько виртуальных машин, тем самым обеспечивая изоляцию окружения.<h2>Системы виртуализации на базе гипервизора</h2>
4 Про системы виртуализации наверняка все слышали: VMware, VirtualBox, Hyper-V, Qemu KVM и т. д. Они обеспечивают изоляцию приложений и управление ресурсами, но у них есть и минусы. Чтобы сделать виртуализацию, нужен гипервизор. А гипервизор - это оверхед ресурсов. Да и сама виртуальная машина обычно целая махина - тяжелый образ, на нём операционная система, Nginx, Apache, возможно и MySQL. Образ большой, виртуальной машиной неудобно оперировать. Как следствие, работа с виртуалками может быть медленной. Чтобы решить эту проблему, создали системы виртуализации на уровне ядра.<h2>Системы виртуализации на уровне ядра</h2>
4 Про системы виртуализации наверняка все слышали: VMware, VirtualBox, Hyper-V, Qemu KVM и т. д. Они обеспечивают изоляцию приложений и управление ресурсами, но у них есть и минусы. Чтобы сделать виртуализацию, нужен гипервизор. А гипервизор - это оверхед ресурсов. Да и сама виртуальная машина обычно целая махина - тяжелый образ, на нём операционная система, Nginx, Apache, возможно и MySQL. Образ большой, виртуальной машиной неудобно оперировать. Как следствие, работа с виртуалками может быть медленной. Чтобы решить эту проблему, создали системы виртуализации на уровне ядра.<h2>Системы виртуализации на уровне ядра</h2>
5 Виртуализацию на уровне ядра поддерживают системы OpenVZ, Systemd-nspawn, LXC. Яркий пример такой виртуализации - LXC (Linux Containers).<p>LXC - система виртуализации на уровне операционной системы для запуска нескольких изолированных экземпляров операционной системы Linux на одном узле. LXC не использует виртуальные машины, а создаёт виртуальное окружение с собственным пространством процессов и сетевым стеком.</p>
5 Виртуализацию на уровне ядра поддерживают системы OpenVZ, Systemd-nspawn, LXC. Яркий пример такой виртуализации - LXC (Linux Containers).<p>LXC - система виртуализации на уровне операционной системы для запуска нескольких изолированных экземпляров операционной системы Linux на одном узле. LXC не использует виртуальные машины, а создаёт виртуальное окружение с собственным пространством процессов и сетевым стеком.</p>
6 <p>По сути LXC создаёт контейнеры. В чём разница между виртуальными машинами и контейнерами?</p>
6 <p>По сути LXC создаёт контейнеры. В чём разница между виртуальными машинами и контейнерами?</p>
7 Контейнер не подходит для изолирования процессов: в системах виртуализации на уровне ядра находят уязвимости, которые позволяют вылезти из контейнера на хост. Поэтому если вам нужно что-то изолировать, то лучше использовать виртуалку.<p>Различия между виртуализацией и контейнеризацией можно увидеть на схеме.Бывают аппаратные гипервизоры, гипервизоры поверх ОС и контейнеры.</p>
7 Контейнер не подходит для изолирования процессов: в системах виртуализации на уровне ядра находят уязвимости, которые позволяют вылезти из контейнера на хост. Поэтому если вам нужно что-то изолировать, то лучше использовать виртуалку.<p>Различия между виртуализацией и контейнеризацией можно увидеть на схеме.Бывают аппаратные гипервизоры, гипервизоры поверх ОС и контейнеры.</p>
8 "Железные" гипервизоры - это крутая штука, если вы действительно хотите что-то изолировать. Потому что там есть возможность изолировать на уровне страниц памяти, процессоров.<p>Есть гипервизоры как программа, и есть контейнеры, о них мы и будем говорить дальше. В системах контейнеризации гипервизора нет, но есть Container Engine, который создаёт контейнеры и управляет ими. Штука это более легковесная, поэтому за счет работы с ядром оверхед меньше, или его нет совсем.</p>
8 "Железные" гипервизоры - это крутая штука, если вы действительно хотите что-то изолировать. Потому что там есть возможность изолировать на уровне страниц памяти, процессоров.<p>Есть гипервизоры как программа, и есть контейнеры, о них мы и будем говорить дальше. В системах контейнеризации гипервизора нет, но есть Container Engine, который создаёт контейнеры и управляет ими. Штука это более легковесная, поэтому за счет работы с ядром оверхед меньше, или его нет совсем.</p>
9 <blockquote><strong>Что используется для контейнеризации на уровне ядра</strong></blockquote><blockquote>Основные технологии, которые позволяют создавать изолированный от других процессов контейнер, - это Namespaces и Control Groups.</blockquote><blockquote>Namespaces: PID, Networking, Mount и User. Есть ещё, но для простоты понимания остановимся на этих.</blockquote><blockquote>PID Namespace ограничивает процессы. Когда мы, например, создаём PID Namespace, помещаем туда процесс, то он становится с PID 1. Обычно в системах PID 1 - это systemd или init. Соответственно, когда мы помещаем процесс в новый namespace, он тоже получает PID 1.</blockquote><blockquote>Networking Namespace позволяет ограничить/изолировать сеть и внутри уже размещать свои интерфейсы. Mount - это ограничение по файловой системе. User - ограничение по юзерам.</blockquote><blockquote>Control Groups: Memory, CPU, IOPS, Network - всего около 12 настроек. Иначе их ещё называют Cgroups ("Cи-группы").</blockquote><blockquote>Control Groups управляют ресурсами для контейнера. Через Control Groups мы можем сказать, что контейнер не должен потреблять больше какого-то количества ресурсов.</blockquote><blockquote>Чтобы контейнеризация полноценно работала, используются дополнительные технологии: Capabilities, Copy-on-write и другие.</blockquote><blockquote>Capabilities - это когда мы говорим процессу, что он может делать, а чего не может. На уровне ядра это просто битовые карты со множеством параметров. Например, пользователь root имеет полные привилегии, может делать всё. Сервер времени может изменять системное время: у него есть capabilities на Time Capsule, и всё. С помощью привилегий можно гибко настроить ограничения для процессов, и тем самым обезопасить себя.</blockquote><blockquote>Система Copy-on-write позволяет нам работать с образами Docker, использовать их более эффективно.</blockquote><blockquote><em>На данный момент Docker имеет проблемы с совместимостью Cgroups v2, поэтому в статье рассматриваются именно Cgroups v1.</em></blockquote>Но вернёмся к истории.<p>Когда появились системы виртуализации на уровне ядра, их начали активно применять. Оверхед на гипервизор пропал, но некоторые проблемы остались:</p>
9 <blockquote><strong>Что используется для контейнеризации на уровне ядра</strong></blockquote><blockquote>Основные технологии, которые позволяют создавать изолированный от других процессов контейнер, - это Namespaces и Control Groups.</blockquote><blockquote>Namespaces: PID, Networking, Mount и User. Есть ещё, но для простоты понимания остановимся на этих.</blockquote><blockquote>PID Namespace ограничивает процессы. Когда мы, например, создаём PID Namespace, помещаем туда процесс, то он становится с PID 1. Обычно в системах PID 1 - это systemd или init. Соответственно, когда мы помещаем процесс в новый namespace, он тоже получает PID 1.</blockquote><blockquote>Networking Namespace позволяет ограничить/изолировать сеть и внутри уже размещать свои интерфейсы. Mount - это ограничение по файловой системе. User - ограничение по юзерам.</blockquote><blockquote>Control Groups: Memory, CPU, IOPS, Network - всего около 12 настроек. Иначе их ещё называют Cgroups ("Cи-группы").</blockquote><blockquote>Control Groups управляют ресурсами для контейнера. Через Control Groups мы можем сказать, что контейнер не должен потреблять больше какого-то количества ресурсов.</blockquote><blockquote>Чтобы контейнеризация полноценно работала, используются дополнительные технологии: Capabilities, Copy-on-write и другие.</blockquote><blockquote>Capabilities - это когда мы говорим процессу, что он может делать, а чего не может. На уровне ядра это просто битовые карты со множеством параметров. Например, пользователь root имеет полные привилегии, может делать всё. Сервер времени может изменять системное время: у него есть capabilities на Time Capsule, и всё. С помощью привилегий можно гибко настроить ограничения для процессов, и тем самым обезопасить себя.</blockquote><blockquote>Система Copy-on-write позволяет нам работать с образами Docker, использовать их более эффективно.</blockquote><blockquote><em>На данный момент Docker имеет проблемы с совместимостью Cgroups v2, поэтому в статье рассматриваются именно Cgroups v1.</em></blockquote>Но вернёмся к истории.<p>Когда появились системы виртуализации на уровне ядра, их начали активно применять. Оверхед на гипервизор пропал, но некоторые проблемы остались:</p>
10 <ul><li>большие образы: в ту же OpenVZ толкают операционку, библиотеки, кучу разного софта, и в итоге образ всё равно получается немаленьким;</li>
10 <ul><li>большие образы: в ту же OpenVZ толкают операционку, библиотеки, кучу разного софта, и в итоге образ всё равно получается немаленьким;</li>
11 <li>нет нормального стандарта упаковки и доставки, поэтому остаётся проблема зависимостей. Бывают ситуации, когда два куска кода используют одну библиотеку, но с разными версиями. Между ними возможен конфликт.</li>
11 <li>нет нормального стандарта упаковки и доставки, поэтому остаётся проблема зависимостей. Бывают ситуации, когда два куска кода используют одну библиотеку, но с разными версиями. Между ними возможен конфликт.</li>
12 </ul>Чтобы все эти проблемы решить, пришла следующая эра.<h2>Эра контейнеров</h2>
12 </ul>Чтобы все эти проблемы решить, пришла следующая эра.<h2>Эра контейнеров</h2>
13 Когда наступила Эра контейнеров, сменилась философия работы с ними:<ul><li>Один процесс - один контейнер.</li>
13 Когда наступила Эра контейнеров, сменилась философия работы с ними:<ul><li>Один процесс - один контейнер.</li>
14 <li>Все нужные процессу зависимости доставляем в его контейнер. Это требует распиливать монолиты на микросервисы.</li>
14 <li>Все нужные процессу зависимости доставляем в его контейнер. Это требует распиливать монолиты на микросервисы.</li>
15 <li>Чем меньше образ, тем лучше - меньше возможных уязвимостей, быстрее раскатывается и так далее.</li>
15 <li>Чем меньше образ, тем лучше - меньше возможных уязвимостей, быстрее раскатывается и так далее.</li>
16 <li>Инстансы становятся эфемерными.</li>
16 <li>Инстансы становятся эфемерными.</li>
17 </ul>Помните, я говорил про pets vs cattle? Раньше инстансы были подобны домашним животным, а теперь стали как cattle - скот. Раньше был монолит - одно приложение. Теперь это 100 микросервисов, 100 контейнеров. У каких-то контейнеров может быть по 2-3 реплики. Нам становится не столь важно контролировать каждый контейнер. Нам скорее важна доступность самого сервиса: того, что делает этот набор контейнеров. Это меняет подходы в мониторинге.<p>В 2014-2015 годах случился расцвет Docker - той технологии, о которой мы и будем сейчас говорить.</p>
17 </ul>Помните, я говорил про pets vs cattle? Раньше инстансы были подобны домашним животным, а теперь стали как cattle - скот. Раньше был монолит - одно приложение. Теперь это 100 микросервисов, 100 контейнеров. У каких-то контейнеров может быть по 2-3 реплики. Нам становится не столь важно контролировать каждый контейнер. Нам скорее важна доступность самого сервиса: того, что делает этот набор контейнеров. Это меняет подходы в мониторинге.<p>В 2014-2015 годах случился расцвет Docker - той технологии, о которой мы и будем сейчас говорить.</p>
18 <p>Docker изменил философию и стандартизировал упаковку приложения. С помощью Docker мы можем упаковать приложение, отправить его в репозиторий, скачать оттуда, развернуть.</p>
18 <p>Docker изменил философию и стандартизировал упаковку приложения. С помощью Docker мы можем упаковать приложение, отправить его в репозиторий, скачать оттуда, развернуть.</p>
19 <p>В Docker-контейнер мы закладываем всё необходимое, поэтому решается проблема зависимостей. Docker гарантирует воспроизводимость. Я думаю, многие сталкивались с невоспроизводимостью: у тебя всё работает, пушишь на продакшен, там это перестает работать. С Docker эта проблема уходит. Если твой Docker-контейнер запускается и делает то, что требуется делать, то с большой долей вероятности он запустится на продакшене и там сделает то же самое.</p>
19 <p>В Docker-контейнер мы закладываем всё необходимое, поэтому решается проблема зависимостей. Docker гарантирует воспроизводимость. Я думаю, многие сталкивались с невоспроизводимостью: у тебя всё работает, пушишь на продакшен, там это перестает работать. С Docker эта проблема уходит. Если твой Docker-контейнер запускается и делает то, что требуется делать, то с большой долей вероятности он запустится на продакшене и там сделает то же самое.</p>
20 <blockquote>Отступление про оверхед</blockquote><blockquote>По поводу оверхед постоянно идут споры. Кто-то считает, что Docker не несёт дополнительную нагрузку, так как использует ядро Linux и все его процессы, необходимые для контейнеризации. Мол, "если вы говорите, что Docker - это оверхед, то тогда и ядро Linux оверхед".</blockquote><blockquote>С другой стороны, если углубиться, то в Docker и правда есть несколько вещей, про которые с натяжкой можно сказать, что это оверхед.</blockquote><blockquote>Первое - это PID namespace. Когда мы в namespace помещаем какой-то процесс, ему присваивается PID 1. В то же время у этого процесса есть ещё один PID, который находится на хостовом namespace, за пределами контейнера. Например, мы запустили в контейнере Nginx, он стал PID 1 (мастер-процесс). А на хосте у него PID 12623. И сложно сказать, насколько это оверхед.</blockquote><blockquote>Вторая штука - это Cgroups. Возьмём Cgroups по памяти, то есть возможность ограничивать контейнеру память. При её включении активируются счётчики, memory accounting: ядру надо понимать, сколько страниц выделено, а сколько ещё свободно для этого контейнера. Это возможно оверхед, но точных исследований о том, как он влияет на производительность, я не встречал. И сам не замечал, что приложение, запущенное в Docker, вдруг резко теряло в производительности.</blockquote><blockquote>И ещё одно замечание о производительности. Некоторые параметры ядра прокидываются с хоста в контейнер. В частности, некоторые сетевые параметры. Поэтому если вы хотите запустить в Docker что-то высокопроизводительное, например то, что будет активно использовать сеть, то вам, как минимум, надо эти параметры подправить. Какой-нибудь nf_conntrack, к примеру.</blockquote><h2>О концепции Docker</h2>
20 <blockquote>Отступление про оверхед</blockquote><blockquote>По поводу оверхед постоянно идут споры. Кто-то считает, что Docker не несёт дополнительную нагрузку, так как использует ядро Linux и все его процессы, необходимые для контейнеризации. Мол, "если вы говорите, что Docker - это оверхед, то тогда и ядро Linux оверхед".</blockquote><blockquote>С другой стороны, если углубиться, то в Docker и правда есть несколько вещей, про которые с натяжкой можно сказать, что это оверхед.</blockquote><blockquote>Первое - это PID namespace. Когда мы в namespace помещаем какой-то процесс, ему присваивается PID 1. В то же время у этого процесса есть ещё один PID, который находится на хостовом namespace, за пределами контейнера. Например, мы запустили в контейнере Nginx, он стал PID 1 (мастер-процесс). А на хосте у него PID 12623. И сложно сказать, насколько это оверхед.</blockquote><blockquote>Вторая штука - это Cgroups. Возьмём Cgroups по памяти, то есть возможность ограничивать контейнеру память. При её включении активируются счётчики, memory accounting: ядру надо понимать, сколько страниц выделено, а сколько ещё свободно для этого контейнера. Это возможно оверхед, но точных исследований о том, как он влияет на производительность, я не встречал. И сам не замечал, что приложение, запущенное в Docker, вдруг резко теряло в производительности.</blockquote><blockquote>И ещё одно замечание о производительности. Некоторые параметры ядра прокидываются с хоста в контейнер. В частности, некоторые сетевые параметры. Поэтому если вы хотите запустить в Docker что-то высокопроизводительное, например то, что будет активно использовать сеть, то вам, как минимум, надо эти параметры подправить. Какой-нибудь nf_conntrack, к примеру.</blockquote><h2>О концепции Docker</h2>
21 Docker состоит из нескольких компонентов:<ol><li>Docker Daemon - то самое Container Engine; запускает контейнеры.</li>
21 Docker состоит из нескольких компонентов:<ol><li>Docker Daemon - то самое Container Engine; запускает контейнеры.</li>
22 <li>Docker CII - утилита по управлению Docker.</li>
22 <li>Docker CII - утилита по управлению Docker.</li>
23 <li>Dockerfile - инструкция по тому, как собирать образ.</li>
23 <li>Dockerfile - инструкция по тому, как собирать образ.</li>
24 <li>Image - образ, из которого раскатывается контейнер.</li>
24 <li>Image - образ, из которого раскатывается контейнер.</li>
25 <li>Container.</li>
25 <li>Container.</li>
26 <li>Docker registry - хранилище образов.</li>
26 <li>Docker registry - хранилище образов.</li>
27 </ol>Схематично это выглядит примерно вот так:На Docker_host работает Docker daemon, запускает контейнеры. Есть Client, который передаёт команды: собери образ, скачай образ, запусти контейнер. Docker daemon ходит в registry и выполняет их. Docker-клиент может обращаться и локально (к юникс-сокету), и по TCP с удалённого хоста.<p>Пройдёмся по каждому компоненту.</p>
27 </ol>Схематично это выглядит примерно вот так:На Docker_host работает Docker daemon, запускает контейнеры. Есть Client, который передаёт команды: собери образ, скачай образ, запусти контейнер. Docker daemon ходит в registry и выполняет их. Docker-клиент может обращаться и локально (к юникс-сокету), и по TCP с удалённого хоста.<p>Пройдёмся по каждому компоненту.</p>
28 Docker daemon (демон) - это серверная часть, она работает на хост-машине: скачивает образы и запускает из них контейнеры, создаёт сеть между контейнерами, собирает логи. Когда мы говорим "создай образ", этим тоже занимается демон.Docker CLI - клиентская часть Docker, консольная утилита для работы с демоном. Повторю, она может работать не только локально, но и по сети.<p><strong>Базовые команды:</strong></p>
28 Docker daemon (демон) - это серверная часть, она работает на хост-машине: скачивает образы и запускает из них контейнеры, создаёт сеть между контейнерами, собирает логи. Когда мы говорим "создай образ", этим тоже занимается демон.Docker CLI - клиентская часть Docker, консольная утилита для работы с демоном. Повторю, она может работать не только локально, но и по сети.<p><strong>Базовые команды:</strong></p>
29 <p>docker ps - показать контейнеры, которые сейчас запущены на Docker-хосте.docker images - показать образы, скачанные локально.docker search &lt;&gt; - поиск образа в registry.docker pull &lt;&gt; - скачать образ из registry на машину.docker build &lt;&lt;/path/to/dir&gt;&gt; - собрать образ.docker run &lt;&gt; - запуск контейнер.docker rm &lt;&gt; - удалить контейнер.docker logs &lt;&gt; - логи контейнераdocker start/stop/restart &lt;&gt; - работа с контейнеромЕсли вы освоите эти команды и будете уверенно ими пользоваться, то считайте, что на 70% освоили Docker на уровне пользователя.</p>
29 <p>docker ps - показать контейнеры, которые сейчас запущены на Docker-хосте.docker images - показать образы, скачанные локально.docker search &lt;&gt; - поиск образа в registry.docker pull &lt;&gt; - скачать образ из registry на машину.docker build &lt;&lt;/path/to/dir&gt;&gt; - собрать образ.docker run &lt;&gt; - запуск контейнер.docker rm &lt;&gt; - удалить контейнер.docker logs &lt;&gt; - логи контейнераdocker start/stop/restart &lt;&gt; - работа с контейнеромЕсли вы освоите эти команды и будете уверенно ими пользоваться, то считайте, что на 70% освоили Docker на уровне пользователя.</p>
30 Dockerfile - инструкция для создания образа. Почти каждая команда инструкции - новый слой. Посмотрим на примере.Примерно так выглядит Dockerfile: слева команды, справа - аргументы. Каждая команда, что здесь есть (и вообще пишется в Dockerfile), создаёт новый слой в Image.<p>Даже глядя на левую часть, можно примерно понять, что происходит. Мы говорим: "создай нам папку" - это один слой. "Сделай папку рабочей" - это ещё один слой, и так далее. Слоёный пирог упрощает жизнь. Если я создам ещё один Dockerfile и в последней строчке что-то изменю - запущу не "python" "main.py", а что-нибудь другое, или установлю зависимости из другого файла - то предыдущие слои будут переиспользованы, как кеш.</p>
30 Dockerfile - инструкция для создания образа. Почти каждая команда инструкции - новый слой. Посмотрим на примере.Примерно так выглядит Dockerfile: слева команды, справа - аргументы. Каждая команда, что здесь есть (и вообще пишется в Dockerfile), создаёт новый слой в Image.<p>Даже глядя на левую часть, можно примерно понять, что происходит. Мы говорим: "создай нам папку" - это один слой. "Сделай папку рабочей" - это ещё один слой, и так далее. Слоёный пирог упрощает жизнь. Если я создам ещё один Dockerfile и в последней строчке что-то изменю - запущу не "python" "main.py", а что-нибудь другое, или установлю зависимости из другого файла - то предыдущие слои будут переиспользованы, как кеш.</p>
31 Image - это упаковка контейнера, из образа запускаются контейнеры. Если смотреть на Docker с точки зрения пакетного менеджера (как будто мы работаем с deb или rpm-пакетами), то image - это по сути rpm-пакет. Через yum install мы можем поставить приложение, удалить его, найти в репозитории, скачать. Здесь примерно то же самое: из образа запускаются контейнеры, они хранятся в Docker registry (по аналогии с yum, в репозитории), и каждый image имеет хеш SHA-256, имя и тег.<p>Image собирается по инструкции из Dockerfile. Каждая инструкция из Dockerfile создаёт новый слой. Слои могут использоваться повторно.</p>
31 Image - это упаковка контейнера, из образа запускаются контейнеры. Если смотреть на Docker с точки зрения пакетного менеджера (как будто мы работаем с deb или rpm-пакетами), то image - это по сути rpm-пакет. Через yum install мы можем поставить приложение, удалить его, найти в репозитории, скачать. Здесь примерно то же самое: из образа запускаются контейнеры, они хранятся в Docker registry (по аналогии с yum, в репозитории), и каждый image имеет хеш SHA-256, имя и тег.<p>Image собирается по инструкции из Dockerfile. Каждая инструкция из Dockerfile создаёт новый слой. Слои могут использоваться повторно.</p>
32 Docker registry - это репозиторий образов Docker. По аналогии с ОС, у Docker есть общедоступный стандартный реестр - dockerhub. Но можно собрать свой репозиторий, свой Docker registry.Container - то, что запускается из образа. По инструкции из Dockerfile собрали образ, затем мы его из этого образа запускаем. Этот контейнер изолирован от остальных контейнеров, он должен содержать в себе всё необходимое для работы приложения. При этом один контейнер - один процесс. Случается, что приходится делать два процесса, но это несколько противоречит идеологии Docker.<p>Требование "один контейнер - один процесс" связано с PID Namespace. Когда в Namespace запускается процесс с PID 1, если он вдруг умрёт, то весь контейнер тоже умирает. Если же там запущено два процесса: один живёт, а второй умер, то контейнер всё равно продолжит жить. Но это к вопросу Best Practices, мы про них поговорим в других материалах.</p>
32 Docker registry - это репозиторий образов Docker. По аналогии с ОС, у Docker есть общедоступный стандартный реестр - dockerhub. Но можно собрать свой репозиторий, свой Docker registry.Container - то, что запускается из образа. По инструкции из Dockerfile собрали образ, затем мы его из этого образа запускаем. Этот контейнер изолирован от остальных контейнеров, он должен содержать в себе всё необходимое для работы приложения. При этом один контейнер - один процесс. Случается, что приходится делать два процесса, но это несколько противоречит идеологии Docker.<p>Требование "один контейнер - один процесс" связано с PID Namespace. Когда в Namespace запускается процесс с PID 1, если он вдруг умрёт, то весь контейнер тоже умирает. Если же там запущено два процесса: один живёт, а второй умер, то контейнер всё равно продолжит жить. Но это к вопросу Best Practices, мы про них поговорим в других материалах.</p>
33 <p>Более детально изучить особенности и полную программу курса можно по ссылке: "<a>Видеокурс по Docker</a>".</p>
33 <p>Более детально изучить особенности и полную программу курса можно по ссылке: "<a>Видеокурс по Docker</a>".</p>
34 <p><em>Автор: Марсель Ибраев, сертифицированный администратор Kubernetes, практикующий инженер в компании Southbridge, спикер и разработчик курсов Слёрм.</em></p>
34 <p><em>Автор: Марсель Ибраев, сертифицированный администратор Kubernetes, практикующий инженер в компании Southbridge, спикер и разработчик курсов Слёрм.</em></p>
35 <h2>Может быть интересно:</h2>
35 <h2>Может быть интересно:</h2>
36 <ul><li><a>Интенсив по Python для инженеров и разработчиков</a></li>
36 <ul><li><a>Интенсив по Python для инженеров и разработчиков</a></li>
37 <li><a>Курс по GoLang для инженеров</a></li>
37 <li><a>Курс по GoLang для инженеров</a></li>
38 </ul>
38 </ul>