Новичкам
October 13, 2021

Знакомство с Docker

1package & Let's Node

⠀Docker — это программное обеспечение, которое упрощает процесс создания, запуска, управления и распространения приложений.


Содержание

Знакомство с Docker

Создание Docker образа


Ход действий

К содержанию

  1. Прочитать теорию;
  2. Перечитать теорию, если что-то непонятно;
  3. Вникая в процесс, пошагово выполнить действия из остальных, практических разделов, за исключением раздела «Удаление»;
  4. При ощущении нехватки полученной информации посмотреть тематические видео/курсы на YouTube и/или найти ответы на интересующие вопросы в поисковике (желательно использовать Google на английском языке);
  5. При желании прочитать статью для продвинутых;
  6. Заглядывать в раздел «Полезные команды» при работе с 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 pull — команда для скачивания образа.
  • secord/education:cowsay — полное название образа, где:
    • secord — имя пользователя на Docker Hub.
    • education — название образа, заданное владельцем.
    • cowsay — тэг образа (по умолчанию используется latest). Тэги схожи с ветвями в 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 run — команда для создания контейнера;
  • secord/education:cowsay / 8f8314f90671 — название или ID образа, на базе которого создаётся контейнер;
  • "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!"

⠀То отобразится ошибка, сигнализирующая о том, что контейнер с таким названием уже существует

⠀В таком случае существует несколько решений:

  1. Задать другое название создаваемого контейнера в опции --name, например cow_2 вместо cow;
  2. Удалить существующий контейнер с таким названием, при этом все файлы и данные внутри контейнера будут удалены (будет рассмотрено в конце раздела);
  3. Переименовать существующий контейнер.

⠀Для переименования контейнера нужно сначала остановить его командой

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

⠀Однако она не работает с работающими контейнерами

⠀Удалить работающий контейнер можно двумя способами:

  1. Остановить контейнер рассмотренной ранее командой и удалить его командой выше;
  2. Удалить контейнер «силой».

⠀Для удаление контейнера «силой» к обычной команде добавляется опция -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, где:
    • CONTAINER_ID_OR_NAME — название или ID контейнера;
    • 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

⠀Короткие обозначения опций тажке можно объединять.

⠀В команде присутствуют опции:

  • -f — слежение за логом, которое прерывается сочетанием клавиш Ctrl+C;
  • -n 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
  • NAME_OR_ID — название или ID образа.

⠀Создать

docker build -t NAME PATH
  • NAME — название образа;
  • PATH — путь до папки, используемой для создания образа.

Контейнеры

  • NAME — название контейнера;
  • NAME_OR_ID — название или ID контейнера.

⠀Список запущенных

docker ps

⠀Список всех

docker ps -a

⠀Создать

docker run -dit --restart always --name NAME IMAGE_NAME_OR_ID
  • IMAGE_NAME_OR_ID - название или 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"
  • COMMAND... - выполняемая команда.

⠀Скачать или загрузить файлы

docker cp NAME_OR_ID:/FROM TO
  • FROM — откуда;
  • TO — куда.

⠀Остановить

docker stop NAME_OR_ID

⠀Переименовать

docker rename NAME NEW_NAME
  • NEW_NAME — новое название контейнера.

⠀Удалить

docker rm NAME_OR_ID

⠀Удалить «силой»

docker rm -f NAME_OR_ID

Реестр

  • NAME — название образа.

⠀Скачать образ

docker pull NAME

⠀Залогиниться

docker login

⠀Опубликовать образ

docker push NAME

Полезные ссылки

К содержанию

Официальная документация (EN) | Docker Hub | Курс по Docker

Статья про Docker | Основные команды Docker


Благодарности

К содержанию

Команда 1package — написание статьи

Выразить благодарность