Каталог статей

Изучайте Docker – легкий путь

Изучайте Docker – легкий путь

Docker захватил индустрию программного обеспечения, став стандартом де-факто. Я думаю, большинство из нас могут согласиться с этим.

Docker облегчает жизнь не только разработчикам, но и операторам и обычным пользователям. Не так много лет назад установка программного обеспечения могла быть хлопотной, на установку и настройку таких вещей, как базы данных и т.д. уходили часы. Сегодня это так же просто, как нажать кнопку Start на Docker Desktop или выполнить однострочную команду с помощью Docker CLI.

Эта статья представляет собой учебник по использованию Docker и изучению основ для начала работы.

Если вы хотите посмотреть видеозапись этого урока, вы можете посмотреть ее на моем канале YouTube.

Что такое Docker

Docker используется для создания отгружаемых образов, которые могут быть отправлены и выполнены на любой системе, где установлен docker. Это возможно благодаря контейнеризации программного обеспечения – набору программ, в которых есть все необходимое для работы.

Это контейнеризированное программное обеспечение может быть запущено любым, кто им владеет. Представьте, что вы устанавливаете PostgreSQL на машину Ubuntu и настраиваете его для работы, это занимает время, но с помощью docker вы можете контейнеризировать эту установку и операционную систему, и в следующий раз, когда она вам понадобится, просто запустите ее.

Образы Docker – это не виртуальные машины, а скорее самодостаточные единицы программного обеспечения, и эта самодостаточная единица содержит все, что ей нужно для работы. И когда я говорю “все”, я имею в виду все: операционную систему, зависимости, сети, конфигурации.

Если вы ищете более подробное объяснение того, как это работает, я рекомендую прочитать официальную документацию docker.

Нужно ли говорить, что Docker написан на языке Go?

Установка Docker

Скачайте и установите движок docker, посетив их сайт загрузки. Docker-desktop теперь доступен для всех платформ и может послужить отличным началом для изучения и поддержки движка docker.

Если вы используете Linux, не забудьте выполнить команду

Это позволит загрузить криптографический ключ docker и добавить его в качестве доверенного источника.

Если вы используете Linux, вы также захотите добавить своего пользователя в группу docker, что позволит вам запускать docker без sudo.

Образы и контейнеры

Все использование docker начинается с образа. Ваш образ – это коробка, содержащая все необходимое для работы операционной системы и других зависимостей. Считайте, что это коробка, в которую поместили все файлы, необходимые для запуска этой коробки.

Образ контейнера Docker – это легкий, автономный, исполняемый пакет программного обеспечения, который включает все необходимое для запуска приложения: код, время выполнения, системные инструменты, системные библиотеки и настройки.

В docker мы часто говорим о двух типах образов.

Точка, в конце концов, не опечатка, последним параметром, задаваемым при построении изображения, является контекст. Подробнее о контексте позже.

Вы можете посмотреть, какие образы у вас есть, используя инструмент Docker CLI.

Как вы можете видеть, вам будут представлены все текущие образы, расположенные на вашей машине. Вы увидите репозиторий, из которого взят образ, и тег – тег версии. Image id – это автоматически генерируемый идентификатор, который можно использовать для ссылки на определенный образ. Также присутствует дата его создания и общий размер всего образа.

Образ используется docker для запуска его в контейнер. Всякий раз, когда мы используем docker run для запуска контейнера, он использует образ и превращает его в контейнер. Контейнер – это запущенный образ.

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

Или, если вы знакомы с ООП, образ можно рассматривать как класс, а контейнер – как объект.

Это означает, что вы можете иметь множество контейнеров, работающих с одним и тем же образом. Важно понимать, что два контейнера, запущенные из одного образа, являются совершенно разными. Если у нас есть образ, называемый базовым, и мы запускаем два контейнера из него, то изменения, внесенные в контейнер A, не отразятся в контейнере B. Также как и изменения, внесенные в контейнер, не отразятся в образе.

Контейнеры запускаются с помощью команды docker run. Команда run берет образ и превращает его в контейнер.

Помните, что контейнеры являются экземплярами образа, но любые изменения в контейнере не сохраняются в образе.

Однако в Docker есть одна замечательная вещь: если мы запустим контейнер из чистого образа Ubuntu и добавим в него нужные нам программы и файлы, мы можем сохранить этот контейнер как образ с помощью команды docker commit .

Проще говоря, у нас есть docker build, используемый для создания образа, есть docker run, создающий контейнеры из образов, и docker commit, создающий образы из контейнеров.

Это позволяет нам создавать высоконастроенные образы, которые отвечают всем требованиям для успешного запуска программного обеспечения.

DockerHub – это хранилище образов, место, где любая организация или разработчик может опубликовать свои образы. Docker будет автоматически использовать dockerhub для поиска любых образов, которые вы пытаетесь использовать, но не имеете локально.

Запуск и управление контейнерами

Давайте запустим контейнер, чтобы изучить его.

Запуск docker осуществляется с помощью команды docker run. Если вы выполните ее, то увидите, что она имеет довольно простой в использовании синтаксис.

Где OPTIONS – это флаги поведения, изменяющие способ запуска контейнера. Imagename и Tag – это просто имя и тег, которые нужно использовать.

COMMAND – это команды, которые мы хотим передать в контейнер после его запуска, за которыми следуют любые ARGS .

Давайте запустим контейнер Ubuntu и заставим его распечатать все файлы, которые присутствуют в текущем рабочем каталоге. Не волнуйтесь, если у вас не установлен контейнер Ubuntu, при попытке запустить несуществующий контейнер, docker автоматически посмотрит на DockerHub и загрузит его для вас.

В команде я не указываю, какой тег использовать, он автоматически использует специальный тег latest, который является самым последним загруженным изображением с таким именем.

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

Теперь, когда мы создали два контейнера для печати содержимого каталога, мы можем найти эти контейнеры с помощью команды ps. Мы добавим флаг a, чтобы перечислить все контейнеры, в противном случае будут перечислены только запущенные контейнеры.

Вы должны увидеть там контейнеры. Пока вы можете удалить их, используя их ID.

Использование ID контейнера довольно муторно, и они длинные, я обычно запускаю свои контейнеры с параметром –name, который позволяет вам создать пользовательское имя для вашего контейнера. Это имя может быть использовано для ссылки на docker в других командах, например, если вы захотите его удалить.

Есть еще несколько флагов, которые могут пригодиться при работе с запущенными контейнерами.

–rm обеспечит удаление контейнера после закрытия процесса.

-it для запуска с интерактивной оболочкой.

Помните, что если вы запустите docker run без –rm, вы не удалите контейнер, и это займет место на вашем жестком диске.

Попробуйте открыть оболочку ubuntu, а затем выйти из нее и перечислить ваши контейнеры, они должны были быть удалены. Использование интерактивной оболочки очень полезно при отладке того, почему программное обеспечение не работает так, как задумано.

Конечно, мы можем держать контейнер docker запущенным в течение длительного времени, мы можем использовать фла г-d, чтобы заставить контейнер работать в отделенном процессе. Это очень распространено, когда в docker запускается ваше программное обеспечение.

Вы можете легко опробовать все это, просто выполнив следующую команду. В этом примере мы хотим запустить более одной внутренней команды в bash, поэтому вместо того, чтобы просто передать sleep прямо в docker, мы используем bas h-c, чтобы вставить несколько команд для последовательного запуска. Каждая команда отделяется друг от друга символом ; .

Вы уже должны понимать, что делает эта команда, но для развлечения, она создаст контейнер с именем myUbuntuContainer из образа ubuntu, запустится в фоновом режиме (detache d-d ), а затем последовательно выполнит команды в-c. Обратите внимание, что я не использую –rm, чтобы этот контейнер не удалился после завершения выполнения.

Вы можете просмотреть список всех существующих контейнеров, выполнив команду docker p s-a .

В результате вы увидите ID контейнера, который используется для ссылки на контейнер, например, если вы хотите удалить контейнер, но вы также можете использовать имя. ps также показывает, какие порты открыты из контейнера на хост-компьютер, в настоящее время их нет.

Если вы хотите посмотреть, что происходит в отсоединенном контейнере, вы можете просмотреть STDOUT контейнера, выполнив команду . Это полезно, когда вы хотите устранить неполадки или понять, почему контейнер не работает.

Обратите внимание, что у нас есть ошибка при выходе, это опечатка в первой команде sleep. Давайте удалим этот контейнер, чтобы он не занимал лишнего места, да, если оставить контейнер, то он займет столько же места, сколько и размер образа.

Мы можем удалить контейнер с помощью команды docker container rm, за которой следует ID контейнера или его имя. Обратите внимание, если ваш контейнер все еще запущен, вы должны передать фла г-f, чтобы принудительно удалить его.

Одним из важных аспектов при запуске docker является ограничение количества ресурсов, таких как память и процессор, разрешенных для использования определенным контейнером. Вы можете добавить эти ресурсы с помощью следующих флагов.

–memory – используется для установки максимально допустимого объема памяти, например –memory=6m (6 мегабайт – это минимум для контейнера).

–cpus – Используется для ограничения количества ресурсов процессора, которые разрешено использовать контейнеру, и т.д. –cpus=1 .

Вы можете проверить любую конфигурацию контейнера с помощью команды inspect . Попробуйте запустить контейнер и установить ограничение памяти, а затем проинспектировать его.

Работа в сети в контейнерах

По умолчанию ваши контейнеры работают в частной сети. Вы можете заставить контейнеры работать в одной сети или сделать их изолированными.

Одним из наиболее распространенных способов является открытие портов из контейнера.

Вы можете легко добавить флаг publish в команду docker run. Сокращенно флаг называетс я-p и принимает порт хост-машины и порт контейнера для связи, разделенные символом : .

Представьте, что вы размещаете API на порту 8080 в своем контейнере, но хотите открыть этот API на хост-машине, на которой запущен контейнер, на порту 8099.

Вы можете сделать это, выполнив следующую команду

Вы можете просмотреть открытый порт, используя docker container ps или docker port $CONTAINERID .

Обратите внимание, что docker по умолчанию использует TCP, вы можете указать протокол, добавив /tcp или /udp после портов.

Еще одна замечательная вещь заключается в том, что вы можете заставить docker динамически назначать порты хоста для вас. Если вы уберете часть хоста из флаг а-p, он найдет любой доступный порт и будет использовать его.

Попробуйте это, укажите тольк о-p 8080 и посмотрите, какой порт он выберет для вас.

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

Вы можете просмотреть все текущие виртуальные сети с помощью команды docker network ls . Вы увидите как минимум три сети.

Сеть хоста используется, если вам не нужна изоляция, она будет работать в той же сети, что и хост-компьютер, на котором запущен контейнер. none используется, если вам вообще не нужна сеть.

Вы можете создать новую виртуальную сеть с помощью следующей команды

Создав ее, мы можем указать контейнерам работать в этой сети с помощью флага –net при запуске контейнера.

Чтобы проверить это, мы откроем два контейнера, назначим их на skynet и посмотрим, сможем ли мы пинговать друг друга. Однако нам нужно установить ping в контейнер ubuntu, и ВЫ НИКОГДА НЕ ДОЛЖНЫ ДЕЛАТЬ ЭТО ВНУТРИ КОНТЕЙНЕРА. Мы просто устанавливаем программу ping, чтобы продемонстрировать работу сети. Позже в статье мы рассмотрим, как это можно было сделать при сборке нашего контейнера.

Всегда устанавливайте зависимости при сборке образа

Давайте начнем с загрузки первого контейнера и его подготовки, мы назовем этот первый контейнер sky-client .

После установки ping попробуйте выполнить ping на sky-server . Вы должны увидеть ошибку, говорящую, что он не существует в DNS.

Мы можем исправить это, откройте второй терминал и запустите второй контейнер с именем sky-server . Обратите внимание, как мы можем использовать имена контейнеров для определения их местоположения в сети.

После запуска sky-server попробуйте снова выполнить пинг с sky-client.

Отлично, теперь у нас есть два контейнера, работающих в одной виртуальной сети. Следует помнить, что в одном контейнере может быть несколько сетей.

Тома

Иногда требуется разделить данные между хостом и контейнером. Часто это происходит, когда, например, в контейнере запущена база данных, и нужно, чтобы база данных сохранялась между перезагрузками.

Вы можете добавить тома между контейнерами и хостом, используя фла г-v. Опять же, как и в случае с сетевыми портами, вы указываете путь на хост-машине, а затем путь на контейнере для монтирования. Пути разделяются с помощью : , как и в большинстве случаев в docker.

Давайте попробуем открыть контейнер и открыть общий доступ к папке с

Реестры используются для управления и распространения образов. Существует официальный реестр docker, который используется по умолчанию, но вы можете создать и свой собственный реестр.

Вы можете искать образы в реестрах с помощью docker search . Если вас интересует определенное программное обеспечение, вы всегда можете поискать, есть ли для него образ. Скажем, вы хотите запустить контейнер PostgreSQL.

Обратите внимание, что вы найдете много образов, потому что любой может загрузить образ в официальный реестр. При выборе образа следует обратить внимание на тег OFFICIAL и количество звезд.

Поскольку любой может создать изображение и загрузить его, при выборе изображения могут возникнуть риски.

Если вам нужен пользовательский интерфейс, вы можете просмотреть официальный реестр, посетив Docker Hub. В Hub обычно можно найти readme о том, как использовать образ.

Реестр можно рассматривать как хранилище кода.

Создание настраиваемых образов

Существует два способа настройки образов, первый – это использование docker commit, который сохраняет контейнер как новый образ. Второй способ – использование Dockerfiles, о которых мы узнаем больше совсем скоро.

Давайте сначала посмотрим, как мы можем использовать Docker commit, чтобы легко сохранить образ с любыми изменениями, сделанными в контейнере. Помните, мы загружали Ping внутри контейнера? Это не сохраняет и не является правильным способом сделать это, но если мы протестировали его и знаем, что этот контейнер правильный и мы хотим сохранить его как изображение, мы можем зафиксировать контейнер.

Откройте новый контейнер Ubuntu и снова установите Iputils-ping.

Как только это будет сделано, выйдите из оболочки и откройте терминал на хост-машине.

Docker commit принимает несколько опций, мне нравится добавлять –message, которая представляет собой сообщение о фиксации изменений. Мне также нравится добавлять –author, чтобы другие разработчики знали, к кому обращаться.

Итак, давайте зафиксируем контейнер, в котором находится нужное нам программное обеспечение.

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

До сих пор мы использовали предопределенные образы, но еще не коснулись самой прекрасной части Docker. Мы можем создавать собственные образы с помощью Dockerфайлов. Dockerfile – это файл, содержащий язык сценариев, который мы можем использовать для создания и оформления наших образов.

Файлы Docker должны иметь имя dockerfile, это позволяет docker автоматически обнаруживать файлы при выполнении docker в каталоге.

Файлы Dockerfiles очень легко читать и понимать, они идут последовательно сверху вниз. Важно помнить, что каждая строка в dockerfile – это выполнение docker run и docker commit. Это называется слоем, и иногда для экономии места можно сгруппировать действия в одну строку.

Пример того, как мы можем создать пользовательский образ ubuntu, содержащий предустановленный FFmpeg, будет выглядеть следующим образом.

FFMPEG – это инструмент, используемый для модификации и работы с видео- и аудиопотоками.

Синтаксис довольно прост, и сейчас мы рассмотрим только основы.

В строке 1 вы видите FROM, который указывает на родительский образ, с которого будет начинаться наш процесс сборки. В данном случае будет использован образ u

Это новое временное изображение будет использоваться в строке 4, загрузите FFmpeg и добавьте его в контейнер, затем сохраните контейнер как изображение.

Теперь вы можете начать задаваться вопросом, почему он воссоздает изображения каждого шага в виде слоя, это суперэффективно и не о чем беспокоиться. Если слой не будет использоваться в дальнейшем, он будет удален после использования. Главное преимущество заключается в том, что docker будет кэшировать эти слои и повторно использовать их во всех сборках. Таким образом, если вы что-то измените, вам не придется ждать, пока все перестроится.

В строке 5 вы видите одну из многих интересных функций docker. CMD позволяет нам указать исполняемый файл внутри образа, который контейнер будет выполнять при запуске. Это позволяет нам сказать, что, когда кто-то запустит этот образ, выполните FFmpeg. Итак, мы упаковали FFmpeg в образ docker, который может быть запущен на любом компьютере, поддерживающем docker, windows, mac и т.д.

Прежде чем вы сможете попробовать, нам нужно собрать образ. Мы только определили в dockerfile КАК его собрать.

Для сборки образа мы используем команду docker build. Мы передадим флаг тег а-t, чтобы указать имя для нашего образа. Мы также завершим команду символом . , точка многих смущает, поэтому попробуйте следовать за ней.

Последний параметр команды docker build – это контекст сборки. Это PATH к месту, которое docker должен использовать при сборке образа. Единственный параметр . указывает docker на использование текущей директории и является наиболее распространенным подходом, но теоретически вы можете собрать этот образ в другом месте, указав путь. Почему, вы можете подумать, потому что иногда вы хотите, чтобы локальные файлы с вашего компьютера присутствовали в образе, мы еще не рассматривали этот вопрос, но вы можете включить файлы с хост-машины в образ docker.

Запустите команду сборки и дождитесь ее завершения, это может занять некоторое время, и именно по этой причине я выбрал FFmpeg. Не для того, чтобы утомить вас, а чтобы показать механизм кэширования.

Во время сборки вы увидите все слои, которые создаются и удаляются, пока не будет готово окончательное изображение. Первая сборка займет некоторое время, но я рекомендую вам попробовать выполнить ту же команду после этого. Вы должны увидеть, что слои кэшируются, а время построения действительно мгновенное.

Теперь вы можете запустить ваш удивительный образ FFmpeg с помощью команды docker run, чтобы запустить FFmpeg там, где вы захотите.

Существует множество других утверждений docker, доступных для Dockerfile. Одним из самых распространенных является оператор ADD. Он позволяет указать папку или файл на хост-машине (той, на которой создается образ) для копирования в образ.

Синтаксис очень прост: вы указываете путь на хосте, а затем путь на образе.

ADD также принимает URL, поэтому вы можете сказать docker получить файл с URL и поместить его в образ.

Еще одним важным параметром является ENV, что является сокращением от переменной окружения.

Теперь в нашем образе есть небольшая ошибка. Мы использовали оператор CMD для запуска FFmpeg, который работает, но он не позволяет нам добавить дополнительные параметры в FFmpeg, которые нам понадобятся.

Пора переходить к

Пересборка образа теперь должна позволить пользователям добавлять входные файлы и т.д. и т.п. командой docker run demo/ffmpe g-inputfile и т.д.

Давайте попробуем добавить файлы, мы будем использовать ранее упомянутую команду ADD для получения демонстрационного видео. Мы возьмем демонстрационное видео из URL, чтобы мы могли попробовать преобразовать видео. Мы сохраним файл в /videos внутри изображения.

Я не рекомендую хранить видео в изображении, это просто для того, чтобы показать, как это работает.

В следующем gist я также изменил все команды RUN в один слой, это обычная техника, используемая для экономии места путем группировки связанных слоев в один. && – это bash для AND, а – это просто новая строка без разрыва команды.

Далее мы перестроим изображение, затем выполним FFmpeg для ускорения видео, а затем выведем его в смонтированную папку.

После выполнения команды вы должны иметь возможность просматривать ускоренную версию видео на хост-машине.

Вот список наиболее популярных команд, используемых в Dockerfiles.

RUN – Используется для выполнения команды в терминале. Для Linux это Bash, для windows – cmd.

ENV – Используется для назначения переменных окружения внутри контейнера.

LABEL – Используется для добавления метаданных к контейнеру. Метки от родительских образов наследуются.

COPY – копирует файл с хоста в контейнер. Может копировать только файлы с хоста.

ADD – Очень похож на COPY, он также копирует файлы в наш контейнер. Разница в том, что ADD может также использовать файлы с удаленного компьютера, по URL. Он также может извлекать локальные TAR-файлы в контейнер.

ARG – Переменные, которые могут быть установлены во время сборки тем, кто собирает образ. ARGS можно использовать внутри Dockerfile во время сборки, но после сборки образа их нельзя использовать или изменить, если только не пересобрать образ.

VOLUME – добавляет точку монтирования между хостом и контейнером. Синтаксис – VOLUME path. Это часто используется при сохранении данных между перезагрузками контейнера, например, баз данных. Фактические данные хранятся на хосте, но используются в контейнере.

EXPOSE – сообщает движку Docker, что контейнер прослушивает определенный порт и протокол. Формат: порт/протокол (UDP/TCP).

CMD – Определяет команду и параметры, которые контейнер Docker должен выполнить при запуске. Обычно это указывает на двоичный файл с набором значений по умолчанию. CMD следует использовать, когда пользователям разрешено изменять команду.

ENTRYPOINT – часто используется, когда контейнер должен быть запущен как исполняемый файл. Делает то же самое, что и CMD, но при использовании ENTRYPOINT пользователю не разрешается изменять команду.

Выполните команду docker images, чтобы просмотреть конечный образ, мой оказался размером 1,95 МБ, что очень мало. Это потому, что единственное, что находится внутри образа – это наш двоичный файл, ничего другого, что могло бы раздуть образ.

Вы даже можете попробовать запустить образ, чтобы убедиться, что он работает.

Итак, почему мы прошли через все это вместо одной сборки, давайте сравним образы.

Вы можете остановить многоэтапную сборку на определенном шаге сборки с помощью опции –target в docker build. Это позволит нам запустить первый этап сборки и создать из него образ, мы передадим имя нашего этапа, builder .

После завершения можно запустить образы docker для сравнения размеров.

Оркестровка контейнеров

Теперь легко представить, что когда мы начинаем использовать docker, он быстро развивается, мы можем легко настроить базу данных, Redis и т.д. для начала работы. Если вы создаете систему, которая полагается на эти контейнеры, нам необходимо их оркестровать.

Система оркестровки используется для запуска и перезапуска контейнеров при сбоях, управления ресурсами, а также позволяет контейнерам обнаруживать друг друга.

Существует множество сервисов оркестровки, самым простым для начала является docker-compose, который обычно используется для того, чтобы помочь разработчикам запустить несколько контейнеров очень простым способом. Docker-compose часто используется на этапах разработки, чтобы упростить тестирование и запуск всего локально. Причина, по которой docker-compose не подходит для более широкого развертывания, заключается в том, что он работает только на одном компьютере.

В производственных средах чаще всего используется Kubernetes. Kubernetes используется на локальном оборудовании, а также легко развертывается у облачных провайдеров с помощью управляемых сервисов.

Я рекомендую изучить Kubernetes, а если вы хотите начать работу с ним, у меня есть статья Learning Kubernetes – The Easy Way, которую вы можете прочитать.

Заключение

В этом руководстве вы узнали об образах и контейнерах, двух ключевых компонентах Docker.

Мы узнали, как создавать образы и как писать спецификации образов с помощью Dockerfiles.

Мы рассмотрели, как можно настроить сеть между контейнерами.

Мы узнали, как монтировать тома между хостом и контейнерами, а также между контейнерами.

Я надеюсь, что вам было предоставлено достаточно основ для того, чтобы вы могли начать работать с Docker самостоятельно.

В своих проектах я почти всегда сохраняю dockerfile, который упаковывает и контейнеризирует программное обеспечение. Я также рекомендую добавить файл docker-compose, который запускает все необходимые сопутствующие сервисы. Например, если вы разрабатываете API, который использует базу данных, очень полезно иметь compose, который запускает ваш API, а также базу данных. Это поможет другим разработчикам быстро приступить к работе и снизит необходимость устанавливать базу данных или поддерживать экземпляр для разработки.

Docker действительно изменил мою жизнь как разработчика, сделав ее намного проще.

Я надеюсь, что вам понравилось это руководство, и я буду рад услышать от вас ваши идеи, отзывы или мнения об этом руководстве.

Спасибо за прочтение и не стесняйтесь связаться со мной в любой из моих социальных сетей.

Пинг запущенного контейнера в той же сети с использованием имени контейнера

Exit mobile version