Знакомство с Docker
⠀Docker — это программное обеспечение, которое упрощает процесс создания, запуска, управления и распространения приложений.
Содержание
Ход действий
- Прочитать теорию;
- Перечитать теорию, если что-то непонятно;
- Вникая в процесс, пошагово выполнить действия из остальных, практических разделов, за исключением раздела «Удаление»;
- При ощущении нехватки полученной информации посмотреть тематические видео/курсы на YouTube и/или найти ответы на интересующие вопросы в поисковике (желательно использовать Google на английском языке);
- При желании прочитать статью для продвинутых;
- Заглядывать в раздел «Полезные команды» при работе с Docker.
Теория
Что это и зачем нужно?
⠀Docker — это программное обеспечение, которое упрощает процесс создания, запуска, управления и распространения приложений. Docker можно установить на компьютеры с операционной системой (ОС) Windows, Linux или MacOS. Ключевым преимуществом данного инструмента является то, что он позволяет пользователям упаковать приложение со всеми его зависимостями в стандартизированный модуль, который можно запустить на любом другом компьютере с установленным Docker.
⠀Такая возможность особенно полезна для программистов, поскольку позволяет быстро и с наименьшим количеством ошибок разместить своё приложение на сервере для тестирования работы, виртуальном хостинге или на сервере клиента.
⠀Однако и в сфере криптовалют Docker будет полезен для людей, запускающих ноды, поскольку при грамотно созданном образе нода запускается без каких-либо ошибок за несколько действий.
Основные понятия
⠀В Docker используется несколько основных понятий:
- Хост — компьютер, на котором работает Docker.
- Образ — шаблон, доступный только для чтения и состоящий из слоёв, из которого создаются контейнеры. Он может как не использоваться, так и использоваться для создания других образов или контейнеров. Проводя простую аналогию, образ можно сравнить с флешкой, которая устанавливает операционную систему с предустановленными программами.
- Контейнер — единица, созданная на базе образа, которой можно управлять. Каждый контейнер изолирован от других, управление схоже с управлением сервисным файлом, может быть запущенным или остановленным. Контейнер аналогичен серверу, на котором работает программа. Удалён контейнер — удалены без возможности восстановления все созданные в нём файлы.
Структура
⠀Архитектура Docker включает в себя:
- Сервер (Server) или Docker демон (dockerd) — процесс, отвечающий за создание и управление образами, контейнерами, сетями и томами на платформе Docker.
- Реестр (Registry) — хранилище образов, из которого можно скачать или в которое можно загрузить образы. Реестры бывают публичными или приватными. Основной публичный реестр — это Docker Hub, аналог GitHub, в котором пользователь может воспользоваться поиском по выложенным другими пользователями образами или, после регистрации, может опубликовать свой образ.
- Клиент (Client) — инструмент, позволяющий пользователю при помощи команд взаимодействовать с Сервером и Реестром. Среди команд можно выделить три основные группы, для взаимодействия с: образами, контейнерами и реестром.
Dockerfile
⠀У каждого образа есть файл, при помощи которого он был создан — Dockerfile
. Название пишется именно так — с большой буквы и без расширения. Этот файл содержит заранее прописанный набор инструкций (команд), которые выполняются построчно, добавляя слои, и в итоге собираются в образ, доступный для использования.
⠀Если перевести содержимое файла на человеческий язык, то в нём будет что-то похожее на:
- Взять за основу образ: …
- Добавить в систему переменные: …
- Создать папку и работать в ней: …
- Установить пакеты: …
- Скачать файлы с сайта: …
- Скопировать с хоста в образ файлы: …
- Образ использует порты: …
- Для запуска контейнеров использовать команду: …
Преимущества
- Возможность развёртывания образов на любом ПК с Docker;
- Быстрое развёртывание образов;
- Удобное управление контейнерами;
- Изолированность контейнеров друг от друга;
- Возможность запуска большого количества приложений (контейнеров) в одном месте;
- Упрощённый запуск нескольких копий приложения на одном ПК;
- Экономия дискового пространства.
Недостатки
- Не так много пользователей;
- Сложность в освоении;
- Если приложение предназначено для запуска в контейнере Docker с Windows, то оно не может работать в Linux или наоборот.
Установка
⠀Docker можно установить на все популярные ОС:
⠀На Linux Ubuntu (на других дистрибутивах не проверялось) можно установить скриптом
. <(wget -qO- https://raw.githubusercontent.com/SecorD0/utils/main/installers/docker.sh)
Простое приложение
⠀В качестве элементарного примера, отображающего большинство принципов работы Docker образов и контейнеров, рассматривается говорящая корова.
⠀Для начала можно посмотреть установленные образы командой
docker images
⠀Изначально список будет пустым, поскольку не установлено ни одного образа
⠀Для скачивания образа говорящей коровы необходимо выполнить команду
docker pull secord/education:cowsay
⠀Эта команда позволяет скачивать образы из регистра. По умолчанию используется Docker Hub, аналог GitHub.
⠀После выполнения команды начнётся скачивание образа
⠀Открыв список образов можно обнаружить только что скачанный
docker images
⠀В данной таблице присутствуют следующие столбцы:
REPOSITORY
— название образа, которое используется для управления. Может иметь вид какUSER/IMAGE_NAME
, так и простоIMAGE_NAME
в случае локального размещения.TAG
— тэг образа.IMAGE ID
— уникальный ID образа, который используется для управления.CREATED
— время последней сборки (создания) образа.SIZE
— занимаемое образом место на диске.
⠀Говорящая корова будет обитать в контейнере, для просмотра запущенных контейнеров используется команда
docker ps
⠀Изначально список будет пустым, поскольку не запущено ни одного контейнера
⠀Чтобы говорящая корова что-то сказала необходимо создать контейнер с необходимым текстом, например
docker run secord/education:cowsay "Hello, World!"
⠀Контейнер был запущен и корова сказала то, что нужно. После этого можно повторно выполнив команду для просмотра запущенных контейнеров
docker ps
⠀Список будет пустым из-за того, что контейнер был запущен, выполнил действие и завершил работу. Для просмотра не только запущенных на текущий момент контейнеров, но и тех, что уже завершили свою работу, необходимо добавить в команду опцию -a
docker ps -a
⠀В данной таблице присутствуют следующие столбцы:
CONTAINER ID
— уникальный ID контейнера, который используется для управления.IMAGE
— название образа, на базе которого создан контейнер.COMMAND
— команда запуска контейнера.CREATED
— когда контейнер был создан.STATUS
— статус контейнера:Up ...
— запущен уже в течение указанного времени;Exited (...) ... ago
— завершил работу с указанным в скобках кодом выхода указанное время назад;Restarting (...) ... ago
— завершил работу с указанным в скобках кодом выхода и перезапустился указанное время назад.PORTS
— открытые порты (подробнее в более сложном примере).NAMES
— уникальные названия контейнера, которые используются для управления.
⠀Корова сказала «Hello, World!» один раз. Для того, чтобы повторить это действие, необходимо вновь запустить контейнер командой (подставить своё название или ID контейнера)
docker start relaxed_shirley
⠀Для обращения к контейнеру можно использовать как название, так и ID, например: relaxed_shirley
или c0a2ec6be6e5
.
⠀При этом, введя часть названия контейнера и нажав Tab
, название допишется до конца.
⠀Однако, если контейнер уже запущен (например, работает непрерывно), то данная команда не сработает, поэтому стоит использовать универсальную команду перезагрузки, которая сработает как в случае работающего, так и в случае завершившего работу контейнера (подставить своё название или ID контейнера)
docker restart relaxed_shirley
⠀Контейнер был запущен дважды, однако говорящая корова ни разу не появилась. Всё это из-за того, что запуск произошёл в фоновом режиме. Для того, чтобы увидеть всех коров, нужно открыть лог контейнера командой (подставить своё название или ID контейнера)
docker logs relaxed_shirley
⠀Ранее была рассмотрена элементарная команда создания, теперь можно осуществить создание ещё одного контейнера более сложной командой
docker run -dit --restart always --name cow secord/education:cowsay \ "I'm a cow!"
⠀Короткие обозначения опций можно как объединить, например в -dit
, так и использовать по отдельности: -d -i -t
-d
— запустить контейнер в фоновом режиме (выведет только ID контейнера).-i
— запуск контейнера в интерактивном режиме, что позволяет выполнять команды внутри контейнера.-t
— подключение драйвера терминала, чтобы оболочка контейнера, в которой будут выполняться команды, была похожа на обычный терминал (подробнее в более сложном примере).--restart
— в каком случае перезапускать контейнер:no
— не перезапускать (используется по умолчанию);on-failure
/on-failure[:max_retries]
— перезапускать в случае завершения работы с ненулевым статусом выхода (ошибка);always
— перезапускать бесконечно, вне зависимости от статуса выхода и несмотря на перезапуск Docker Daemon.unless-stopped
— аналогичноalways
, однако при перезагрузке Docker Daemon контейнер не продолжает перезапускаться.--name
— присвоить название контейнеру (по умолчанию генерируется случайное).
⠀Поскольку контейнеру было указано перезагружаться постоянно, он будет отображаться в списке запущенных контейнеров
docker ps
⠀Открыв лог контейнера можно увидеть, как корова непрерывно повторяет фразу «I’m a cow!»
docker logs cow
⠀Если попытаться создать ещё один контейнер той же командой
docker run -dit --restart always --name cow secord/education:cowsay \ "I'm a cow!"
⠀То отобразится ошибка, сигнализирующая о том, что контейнер с таким названием уже существует
⠀Для переименования контейнера нужно сначала остановить его командой
docker stop cow
docker rename cow cow_2
⠀Теперь при повторном выполнении той же команды контейнер будет успешно создан, поскольку уже нет контейнера с идентичным названием
docker run -dit --restart always --name cow secord/education:cowsay \ "I'm a cow!"
⠀Если открыть список всех контейнеров, то можно увидеть, что один контейнер был остановлен и переименован, а другой создан с именем cow
и непрерывно перезагружается
docker ps -a
⠀Основные команды были рассмотрены, поэтому можно почистить Docker от простого приложения и перейти к более сложному.
docker images
⠀А затем попытаться удалить образ командой
docker rmi 8f8314f90671
⠀То появится ошибка, указывающая на то, что данный образ используется указанным контейнером
⠀Образ не может быть удалён, пока существуют созданные на его базе контейнеры. Поэтому перед удалением образа необходимо удалить все такие контейнеры.
⠀Для того, чтобы удалить все контейнеры, завершившие работу, нужно выполнить команду и подтвердить действие
⠀Все данные внутри завершивших работу контейнеров будут удалены.
docker container prune
⠀Открыв список всех контейнеров можно удостовериться, что все, прекратившие работу контейнеры, были остановлены
docker ps -a
⠀Остался только рабочий контейнер. Для удаления контейнеров используется команда
docker rm cow
⠀Однако она не работает с работающими контейнерами
⠀Для удаление контейнера «силой» к обычной команде добавляется опция -f
docker rm -f cow
⠀После удаления всех контейнеров можно удалить образ
docker rmi 8f8314f90671
⠀И удостовериться, что список образов пустой
docker images
Сложное приложение
⠀В качестве сложного примера рассматривается сайт, через который можно записывать текст в файл.
⠀Для начала необходимо открыть порт для корректной работы сайта
. <(wget -qO- https://raw.githubusercontent.com/SecorD0/utils/main/miscellaneous/ports_opening.sh) 8000
⠀Далее можно создать контейнер, минуя команду скачивания образа
docker run -dit --restart always -p 8000:8000 --name writer secord/education:writer
⠀Команда создания контейнера ищет образ локально и, если не находит, то начинает скачивать его из Docker Hub.
⠀В команду добавлена новая опция:
-p HOST_PORT:DOCKER_PORT
— это сопоставление портов хоста с портами контейнера Docker. Это нужно для доступа к некоторым приложением, запущенным в контейнере — если порт не будет открыт, то будет невозможно подключиться к приложению. Таких опций может быть несколько: одно сопоставление портов — одна опция.
⠀В контейнере запустился сайт, удостовериться в этом можно выполнив команду
docker ps
⠀Чтобы узнать адрес сайта необходимо выполнить команду
echo "http://`wget -qO- eth0.me`:8000"
⠀При помощи этой ссылки можно зайти на запущенный сайт из браузера с любого устройства
⠀Сайт позволяет ввести какой-нибудь текст и затем сохранить его в файл, нажав кнопку «Сохранить текст в файл». Для дальнейшего рассмотрения команд нужно выполнить эту процедуру несколько раз.
⠀В большинстве контейнеров, как и на обычном Linux, можно выполнять команды, сделать это можно несколькими способами.
⠀Контейнер должен быть запущен состоянии, иначе все команды далее не сработают.
⠀Первый способ — запустить Bash оболочку контейнера
docker exec -it writer bash
⠀В оболочке команды выполняются как в обычном Linux, а для выхода используется сочетание клавиш Ctrl+C
или команда exit
.
ls -a cd writer/ ls -a cd .. mkdir del ls -a cd del/ echo "Hello, World!" echo "Hello, World!" > text.txt ls -a cat text.txt cd .. rm -rf del/ cat saved_text.txt exit
⠀Второй способ — выполнение команд при помощи sh
, что удобно при необходимости выполнить одну-две команды
docker exec writer sh -c "cat saved_text.txt; ls -a"
⠀Помимо этого можно скачивать файлы и папки из контейнера на хост
cd; mkdir writer docker cp writer:/writer/saved_text.txt $HOME/writer/saved_text.txt cat $HOME/writer/saved_text.txt
⠀Команда состоит из нескольких частей:
docker cp
— команда скачивания;writer:/writer/saved_text.txt
— путь к папке или файлу, который необходимо скачать, выглядит какCONTAINER_ID_OR_NAME:/FILE_PATH
, где:$HOME/writer/saved_text.txt
— путь к папке или файлу на хосте, куда будет скачан.
⠀При этом в пути файла была добавлена папка writer
потому что она является рабочей, понять это можно выполнив команду
docker exec writer sh -c "pwd"
⠀Той же командой можно загружать файлы или папки с хоста в контейнер
echo "Hello, World!" > $HOME/writer/text.txt docker cp $HOME/writer/text.txt writer:/writer/text.txt docker exec writer sh -c "cat text.txt; ls -a"
⠀Команда для просмотра логов имеет дополнительные опции, некоторые из которых будут особенно полезны, например:
docker logs writer -fn 10
⠀Слежение за логом подразумевает, что, при выводе приложением какого-либо текста в лог, не нужно будет заново выполнять команду — отображение происходит в режиме реального времени. Удостовериться в этом можно добавив в файл через сайт несколько текстов и взглянув на лог
⠀Как описывалось в теоретической части — если отменить аренду сервера, то к нему потеряется доступ и все файлы будут удалены, аналогичное произойдёт при удалении контейнера.
⠀Чтобы удостовериться в этом, можно удалить контейнер
docker rm -f writer
docker run -dit --restart always -p 8000:8000 --name writer secord/education:writer
⠀И посмотреть содержимое созданного контейнера
docker exec writer sh -c "ls -a"
⠀Поэтому, при удалении контейнеров необходимо сохранить все важные файлы на хост рассмотренной ранее командой.
⠀Все основные команды были рассмотрены, поэтому можно почистить Docker от сайта
docker rm -f writer docker rmi secord/education:writer
Полное удаление
⠀Если при каких-то обстоятельствах необходимо полностью удалить Docker на Linux Ubuntu, то сделать это можно скриптом
. <(wget -qO- https://raw.githubusercontent.com/SecorD0/utils/main/installers/docker.sh) -u
⠀О том, как удалить на других ОС можно узнать у поисковика
Читать далее
⠀Если стоит задача создать свой собственный образ, а может вдобавок опубликовать его на Docker Hub, то будет полезна статья для продвинутых.
Полезные команды
Образы
docker images
docker rmi NAME_OR_ID
docker build -t NAME PATH
Контейнеры
docker ps
docker ps -a
docker run -dit --restart always --name NAME IMAGE_NAME_OR_ID
docker restart NAME_OR_ID
docker logs NAME_OR_ID -fn 100
docker exec -it NAME_OR_ID bash
docker exec NAME_OR_ID sh -c "COMMAND_1; COMMAND_2"
docker cp NAME_OR_ID:/FROM TO
docker stop NAME_OR_ID
docker rename NAME NEW_NAME
docker rm NAME_OR_ID
docker rm -f NAME_OR_ID
Реестр
docker pull NAME
docker login
docker push NAME
Полезные ссылки
Официальная документация (EN) | Docker Hub | Курс по Docker
Статья про Docker | Основные команды Docker
Благодарности
Команда 1package — написание статьи