Как создать dockerfile ubuntu
Перейти к содержимому

Как создать dockerfile ubuntu

  • автор:

Создаём и расширяем образы Docker с функциями middleware

Для переноса IT-среды в облако используют технологии контейнеризации, в первую очередь Docker. Такой подход помогает оптимизировать потребление ресурсов и ещё больше автоматизировать операционные процессы. Однако для поддержки энтерпрайз-приложений требуются дополнительные службы, которые называют функциями промежуточной обработки (middleware functions). Такие службы применяют для интеграции, обмена сообщениями, размещения приложений в контролируемой серверной среде и др. В статье рассказываем, как создавать и расширять образы Docker, содержащие функции промежуточной обработки.

Заглянем внутрь образа Docker

Образ — главный элемент в контейнеризации Docker. В нём содержатся процессы и зависимости, необходимые для нормальной работы приложения. На базовый образ Docker накладываются доступные для чтения слои, которые образуются после любых изменений. Каждый новый слой представляет собой актуальную версию образа. А финальный образ — это объединение всех слоев в один. Подробно писали об этом здесь.

При развёртывании нового контейнера Docker вы указываете имя и тег образа, который хотите использовать. Хост Docker проверяет, доступен ли этот образ локально. Если недоступен — загружает все слои, необходимые для конкретного образа.

Важно: слои никогда не загружаются дважды. Предположим, вы хотите запустить один контейнер с WordPress и другой с MySQL. Оба контейнера основаны на базовом образе Ubuntu, и слои, составляющие его, загружаются только один раз. Такое разделение упрощает доступ, поскольку образ Docker не является одним большим монолитным файлом.

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

Хотя образ Docker может содержать только те файлы, которые необходимы для запуска операционной системы, следует избегать развёртывания «пустого образа». Ожидается, что контейнер представляет приложение или, по крайней мере, часть приложения (например, микросервис). Нельзя развёртывать контейнер, на котором работает Ubuntu, а затем пытаться удалённо войти в него, чтобы вручную установить другое программное обеспечение. Образ Ubuntu на Docker hub был и остаётся одним из самых популярных. Однако обычно он используется в качестве основы для других образов, несущих в себе функции более высокого уровня.

Аналогично, контейнер Docker должен запускать только один процесс. Каждый образ Docker определяет команду, которая выполняется при запуске контейнера. Эта команда запускает приложение или сервис, предлагаемые контейнером. Вы можете указать дополнительные параметры для этой команды или определить свою собственную команду при запуске контейнера (описано в разделе «Docker image customization»).

Dockerfile

Новые образы Docker создаются с использованием Dockerfile, где указаны следующие элементы:

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

Dockerfile передаётся команде docker build, которая создаёт новый образ. В примере показан простой Dockerfile, который описывает образ, основанный на Ubuntu, предоставляет порт 80 и запускает пользовательский сценарий оболочки:

 FROM ubuntu EXPOSE 80 COPY myscript.sh /usr/local/bin/ CMD ["myscript.sh"]

Более реалистичные примеры образов вы можете найти на GitHub. Рекомендации по созданию Dockerfile на Docker и Project Atomic.

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

Запускаем middleware в контейнерах

Образ Docker существует с минимальным набором библиотек и представляет приложение или службу, а не операционную систему. Пример — образ Ubuntu, который представляет собой базовый образ, предназначенный для расширения, а не для запуска в контейнере.

Между операционной системой и приложением находится middleware — промежуточное или связующее программное обеспечение. Наиболее распространенными примерами промежуточного программного обеспечения считаются серверы приложений или среды обмена сообщениями. Скажем, чтобы использовать промежуточное ПО в контексте среды Dockerized, вы должны создать образы Docker, содержащие это промежуточное ПО в качестве дополнительных слоев. Однако эти образы не предназначены для окончательного развёртывания в контейнере. Поэтому вы должны создавать их таким образом, чтобы упростить расширение middleware с помощью реального приложения.

На рисунке показано, как контейнеры используют образы Docker, состоящие из нескольких слоев, охватывающих части операционной системы и middleware:

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

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

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

Чтобы продемонстрировать идею повторного использования и расширения образов, рассмотрим серию образов, которые строятся один на другом, переходя от промежуточного программного обеспечения к образу. На рисунке показаны примеры IBM WebSphere Liberty и Tradelite. В этом сценарии образ Docker — актив с добавленной стоимостью, который передаётся командам или организациям, которые затем дополнительно настраивают образ, прежде чем передать его другой команде:

Образы, которые используются в примере:

  • WebSphere Liberty — образ был создан группой IBM и предоставляет middleware для сервера приложения. Является расширением базового образа, который содержит необходимые файловые системы операционной системы.
  • Tradelite — образ создан независимым поставщиком решений. Обеспечивает основные функции приложения, оставаясь при этом нейтральным к облаку.
  • Tradelite4MyCo — приложение для образа, который относится к вымышленному облаку MyCo.

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

Настраиваем образ Docker

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

Переменные среды

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

Чтобы определить переменную среды во время сборки образа, используйте инструкцию ENV Dockerfile:

ENV myName="John Doe" myDog=Rex\ The\ Dog myCat=fluffy

Если та же переменная окружения указана позже в файле Dockerfile или в расширяемом Dockerfile, значение будет перезаписано. Устанавливается новое значение среды, которое сохраняется в образе. Переменная среды также может быть установлена при создании контейнера:

docker run –e "myName=\"Bob\"

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

Аргументы командной строки

Docker разбивает то, что традиционно считается командной строкой процесса, на две части: точку входа и команду. Точка входа представляет процесс, который нужно запустить, а команда состоит из аргументов, переданных этому процессу. Например, общая точка входа в образ базовой операционной системы — /bin/bash –c , а командная строка может быть ls . Результатом запуска такого контейнера считается запуск процесса:

/bin/bash –c ls

Аналогично переменным среды, точка входа и параметры команды могут быть предоставлены инструкцией Dockerfile или при создании контейнера. Однако интерфейс командной строки (CLI) для конкретного процесса обычно чётко определён. Следовательно, его наиболее распространенное использование — изменение характеристик целевого процесса.

Файлы и тома

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

Процесс сборки Docker предлагает два механизма добавления файлов в файловую систему контейнера: ADD и COPY. ADD остаётся в наборе инструкций, которые понимает сборка Docker. Однако COPY считается более предпочтительной, поскольку её легче понять.

Чтобы использовать COPY, укажите источник и место назначения в Dockerfile:

COPY [source] [destination]

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

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

Что даёт использование инструкции VOLUME:

  • Тома не удаляются после создания. Если том не имеет смысла для следующего образа расширения, просто отложите его создание на более позднее время.
  • Сборка Docker создаёт новый контейнер для каждой инструкции в Dockerfile. Результатом является перенос данных из файловой системы многоуровневого контейнера в новый том, что может снизить производительность сборки.
  • Многоуровневая файловая система становится недоступной. Любые файлы, которые вы добавляете или изменяете в каталогах тома, не сохраняются.

Вы также можете создавать тома с помощью команды volume или переключателя среды выполнения –v :

docker run –v [volume]:[path]

Применяем настройки

К этому моменту у вас уже должно появиться представление, как Docker использует переменные среды, аргументы командной строки и уровни образов. Теперь разберём, как применять эти знания на практике на примере Tradelite — приложения, которому требуется сервер для предоставления необходимых функций.

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

Выбор базового образа

Контейнер Docker — просто процесс, который запускается на хосте, но с приписываемым ему особым поведением. Одним из вариантов поведения считается видимая файловая система. Поскольку контейнер запускается после монтирования файловой системы образа, эта система должна содержать целевой файл, который, в свою очередь, может содержать дополнительные файлы.

Для WebSphere Liberty процесс начальной загрузки запускается сценарием оболочки и запускает среду выполнения Java (JRE). Чтобы поддерживать оболочку, нужно выбрать базовый образ, содержащий среду оболочки, а также предоставить общие библиотеки Linux (libpthread, libc и ld-linux).

В нашем примере используется образ Liberty Docker, который можно найти в Docker hub или IBM Containers. Учитывая, что контейнер в основном использует библиотеки, поддерживаемые ядром Linux и совместимые с дистрибутивами Linux, нам не нужно пересобирать образ, чтобы выбрать другую базовую операционную систему. Если этот образ повторно используется в других приложениях Java EE в целевой среде, результатом будет большая согласованность между образами Java EE, а также более эффективное использование памяти и пропускной способности передачи.

Объявление томов

WebSphere Liberty image имеет широкую аудиторию. Важной характеристикой этого образа считается то, что любые выполняемые в нём действия, могут быть отменены или заменены в следующем Dockerfile.

Как упоминалось ранее, вы не можете удалить том после его создания. Поэтому команда WebSphere Liberty решила не объявлять никаких томов, оставив выбор за расширителем или оператором.

Добавление двоичных файлов программного обеспечения и данных конфигурации

Каждому Dockerfile из нашего примера может потребоваться добавление нескольких двоичных файлов ПО. Мы можем добавить их к образу с помощью инструкций ADD или COPY.

Добавление двоичных файлов обычно не вызывает трудностей. Каждый уровень имеет тенденцию добавлять больше двоичных файлов или заменять существующий двоичный файл. Поэтому вам не нужно редактировать двоичный файл или напрямую влиять на его содержимое на диске во время выполнения. Достаточно встраивать удалённое извлечение двоичных файлов ПО в образ. Запущенный контейнер не должен загружать двоичные обновления, но вместо этого должен пытаться сохранить двоичное содержимое идемпотентным. Если двоичный файл необходимо обновить — подготовьте для этого новый образ.

В нашем примере большая часть содержимого конфигурации связана с файлом WebSphere Liberty server.xml и соответствующим ему набором файлов. Часть этого контента должна быть предоставлена в следующих слоях. Например, нам может потребоваться объявить файл EAR и связанные с ним атрибуты развёртывания. При этом другой контент может быть связан со средой развёртывания.

Оператору немного проще определить переменные среды. Поэтому оператор должен определять данные с помощью переменных среды. В качестве альтернативы элементы развёртывания приложения должны предоставляться одновременно с двоичными файлами. Эти файлы настраиваются путем редактирования или предоставления содержимого server.xml в сборке Docker.

Затем с помощью Dockerfile добавляется пользовательский файл server.xml:

COPY ./server.xml /opt/ibm/wlp/usr/servers/defaultServer/server.xml

Файл server.xml конфигурирует файл EAR и показывает переменные среды оператора для базы данных:

  ' user='DB2_USER' password='$' portNumber='$' serverName='$'/>  /lib' includes='db2jcc.jar'/> 

Файл server.xml показывает оператору следующие переменные среды:

  • DB2_USER;
  • DB2_PASS;
  • DB2_PORT;
  • DB2_HOST;

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

Про расположение environment-specific конфигурации в образе

Механизм переменных среды хорошо работает для простых значений, но как насчёт сложной конфигурации структурных данных? Примеры данных такого типа — LDAP (протокол, используемый для хранения и извлечения данных из иерархической структуры каталогов) и TLS (протокол, поддерживающий защищённую передачу данных между клиентом и сервисом). Можно попытаться сопоставить некоторые из этих данных с переменными среды, однако почти всегда их сертификаты передаются через файловый механизм.

Безусловно, самый простой способ работы с содержимым файла — добавить его непосредственно к образу. Однако это может нарушить переносимость образа приложения в облако и повысить уязвимости. Реестры Docker не подходят для хранения секретных данных, поэтому их нужно предоставлять непосредственно во время выполнения.

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

Коротко о главном

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

Как создать собственный образ Docker с помощью Dockerfile

Как создать собственный образ Docker с помощью Dockerfile

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

Docker предоставляет простой способ настроить любой образ docker и создать свой собственный пользовательский образ с помощью dockerfile.

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

Создание пользовательского образа docker

Итак, в этом примере вы будете использовать образ Alpine Linux, который по умолчанию не включает редактор Vim. Вы измените этот образ для создания нового образа Docker в Alpine Linux, который по умолчанию включает редактор Vim.

[gn_box title=»Необходимое условие» box_color=»#fff48c» title_color=»#000000″]Если вы еще этого не сделали, пожалуйста, установите Docker в Ubuntu или в любом дистрибутиве Linux, который вы используете. Убедитесь, что вы добавили себя в группу Docker, чтобы вы могли запускать Docker без sudo.[/gn_box]

Для загрузки образа базового Docker вам понадобится активное интернет-соединение.

Шаг 1: Получить образ Docker [необязательно]

Мы выбрали Alpine Linux в этом примере, потому что он очень маленький. Размер образа Docker Alpine едва ли составляет 5 МБ. Вы можете в это поверить? Это идеальный дистрибутив Linux для контейнеров.

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

Извлеките последний образ Docker Alpine Linux с помощью команды docker pull:

docker pull alpine

Шаг 2: Создайте Dockerfile с необходимой настройкой

Теперь давайте создадим новый пустой файл с именем Dockerfile с помощью команду touch.

touch Dockerfile

Теперь вам нужно отредактировать этот файл и эти три строки и сохранить его. Вы можете использовать текстовый редактор, такое как Vim или Nano, или команду cat, чтобы добавить эти строки в Dockerfile.

FROM alpine:latest RUN apk update RUN apk add vim

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

Как и apt, Alpine использует менеджер пакетов apk. Поэтому следующие две команды в основном сообщают Alpine linux обновить имеющийся кеш пакета (apk update) и затем установить Vim (apk add vim).

Как вы можете видеть, с помощью RUN в Dockerfile вы можете настроить свой базовый образ докера, выполнив определенные команды.

Шаг 3. Создайте собственный образ Docker с помощью Dockerfile

Команда для создания пользовательского образа из Dockerfile выглядит следующим образом:

docker build -t new_docker_image_name PATH_to_Dockerfile

С помощью тега -t вы указываете имя своего настраиваемого образа Docker.

Учитывая, что ваш Dockerfile находится в вашем текущем каталоге, вы можете создать новый образ Docker Alpine Linux с установленным Vim следующим образом:

docker build -t alpine-with-vim

Давайте теперь посмотрим доступные образы Docker в системе:

andreyex@destroyer:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE alpine-with-vim latest fa8255cf0de0 4 seconds ago 32.1MB alpine latest a187dde48cd2 2 weeks ago 5.4MB

Вы можете видеть, что базовый образ Docker размером чуть более 5 МБ теперь составляет 33 МБ с установленным Vim (и обновленным кэшем пакетов).

Теперь давайте проверим, что на ваших модифицированных образах Docker установлен vim, запустив из него контейнер :

docker container run -ti alpine-with-vim /bin/sh

Как только вы окажетесь внутри контейнера, вы можете убедиться, что Vim установлен, проверив его версию:

/ # vim --version VIM - Vi IMproved 8.2 (2019 Dec 12, compiled Dec 12 2019 19:30:49) Compiled by Alpine Linux

Выйдите из контейнера, набрав команду exit в терминале. Остановите контейнер, удалите контейнер и удалите образы Docker (если хотите), чтобы освободить место на диске.

Отлично! Вы только что узнали, как создать свой собственный настроенный образ Docker.

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

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

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

Установка и настройка Docker в Ubuntu

Docker — программное обеспечение для облегчения создания, развертывания и запуска приложений. Разработчик может упаковать приложение и все его зависимости в изолированную среду. Managed Kubernetes помогает разворачивать контейнерные приложения в инфраструктуре Selectel. Сосредоточьтесь на разработке, а мы займемся рутинными операциями по обеспечению работы вашего кластера Kubernetes. Создавая аналогичную изолированную среду, Docker схож с виртуальным сервером. Однако, […]

Изображение записи

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

Managed Kubernetes помогает разворачивать контейнерные приложения в инфраструктуре Selectel. Сосредоточьтесь на разработке, а мы займемся рутинными операциями по обеспечению работы вашего кластера Kubernetes.

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

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

В этой статье мы разберемся с установкой Docker на операционную систему Ubuntu, создадим образ контейнера на Docker Hub и запустим собственный репозиторий. Также расскажем об утилите Docker Compose для работы с мультиконтейнерными приложениями.

Перед началом установки всех необходимых компонентов, подготовим сервер. Это будет облачный сервер с готовой конфигурацией.

В консоли управления Selectel перейдем в представление Облачная платформа и нажмем на кнопку Создать сервер.

На следующем представлении вводим имя сервера, выбираем образ операционной системы (в нашем случае это Ubuntu 18.04 LTS 64-bit) и фиксированную конфигурацию сервера с 1 vCPU и 2 ГБ RAM. Для тестовых целей будет достаточно диска с 10 ГБ. Еще раз проверяем конфигурацию сервера и нажимаем Создать.

Подождем минуту или две пока сервер не перейдет в состояние Active.

Теперь можем приступать к установке Docker. Поехали!

Docker: системные требования для установки

Один из компонентов окружения Docker — Docker Engine. Эти клиент-серверное приложение, которое обеспечивает следующие компоненты:

  • серверная часть с процессом-демоном dockerd;
  • API-интерфейсы, которые программы могут использовать для взаимодействия с демоном Docker;
  • клиента интерфейса командной строки (CLI), вызываемый командой docker.

Docker Engine поставляется в виде .deb и .rpm пакетов и может быть установлен на любые дистрибутивы семейства Linux (CentOS, Debian, Fedora, Raspbian, Ubuntu). Также есть специальная утилита Docker Desktop, которая позволяет исполнять Docker Engine на операционных системах Windows и MacOS. В обоих случаях, все равно будет использоваться ядро Linux.

Установка Docker на Ubuntu

Чтобы установить Docker на Ubuntu, выполним подготовительные действия. Для начала, обновим состав установочных пакетов, чтобы иметь представление об их актуальных версиях:

sudo apt update

Предварительно установим набор пакетов, необходимый для доступа к репозиториям по протоколу HTTPS:

  • apt-transport-https — активирует передачу файлов и данных через https;
  • ca-сertificates — активирует проверку сертификаты безопасности;
  • curl — утилита для обращения к веб-ресурсам;
  • software-properties-common — активирует возможность использования скриптов для управления программным обеспечением.
sudo apt install apt-transport-https ca-certificates curl software-properties-common

Далее добавим в систему GPG-ключ для работы с официальным репозиторием Docker:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Теперь добавим репозиторий Docker в локальный список репозиториев:

sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

Повторно обновим данные о пакетах операционной системы:

sudo apt update

Приступаем к установке пакета Docker.

sudo apt install docker-ce -y

После завершения установки запустим демон Docker и добавим его в автозагрузку:

sudo systemctl start docker
sudo systemctl enable docker

На этом установка Docker завершена и можно начинать с ним работу.

Установка Docker Compose на Ubuntu

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

Посмотрим последнюю сборку Docker Compose в репозитории на Github и загрузим ее при помощи утилиты curl со следующими параметрами:

  • –L разрешает редиректы, если файл перемещен;
  • –o модифицирует имя файла для удобства его запуска и указывает каталог для сохранения.
sudo curl -L "https://github.com/docker/compose/releases/download/1.28.6/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

После завершения загрузки, добавим загруженному бинарному файлу права на выполнение:

sudo chmod +x /usr/local/bin/docker-compose

Заметим, что выполнить установку Docker Compose можно было из репозитория Ubuntu командой sudo apt-get install docker-compose. Однако, в репозитории может быть не самая последняя версия. Способ, который мы описали выше, позволит загрузить актуальную версию утилиты Docker Compose.

Чтобы проверить корректность работы утилиты, выполним проверку ее версии:

sudo docker–compose –version

Если команда вернула номер версии, значит Docker Compose готов к работе.

Когда нужно удалить Docker Compose, достаточно выполнить команду удаления файла:

sudo rm /usr/local/bin/docker-compose

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

sudo apt purge docker-compose

И следом удалить все невостребованные зависимости:

sudo apt autoremove

Команды Docker и работа с ним

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

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

Создадим новую директорию, перейдем в нее и создадим Dockerfile:

mkdir docker_images
cd docker_images
touch Dockerfile

Откроем Dockerfile и добавим в него несколько строк:

nano Dockerfile
FROM ubuntu MAINTAINER selectel RUN apt-get update CMD ["echo", "Hello World"]
  • FROM определяет основу создаваемого изображения. Можно начать с родительского (как в примере выше) или базового образа. При использовании родительского образа вы используете существующий образ, на котором основан новый. Использование базового образа означает, что вы начинаете с нуля (именно так его и определяют: FROM scratch).
  • MAINTAINER указывает автора образа. Здесь вы можете ввести ваше имя и/или фамилию (или добавить адрес электронной почты). Также сюда можно вписать инструкцию по добавлению метаданных (LABEL) к образу.
  • RUN определяет инструкции по выполнению команды при построении образа в слоях поверх него. В этом примере система ищет обновления репозитория после начала сборки образа Docker. В Dockerfile может быть несколько инструкций RUN.
  • CMD отвечает за значение команды по умолчанию, которая будет исполнено. Система выполнит ее, если вы запустите контейнер без указания команды. Внутри Dockerfile может быть только одна инструкция CMD.

Сохраним изменения и выйдем из режима редактирования. Теперь можно приступать к сборке контейнера. Для этого используем утилиту Docker. Базовый синтаксис выглядит так:

sudo docker build [OPTIONS] PATH | URL | -

Запустим утилиту с параметром -t, который указывает на имя образа. Это упростит управление образами, когда их станет несколько.

sudo docker build -t my_image .

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

sudo docker images
REPOSITORY TAG IMAGE ID CREATED SIZE my_image latest 889af78121ad 4 seconds ago 100MB ubuntu latest 4dd97cefde62 2 weeks ago 72.9MB

Казалось бы мы создали только один образ. Откуда там появилось два? Все просто — мы создавали свой контейнер my_ubuntu на на базе образа ubuntu, поэтому вначале скачался образ ubuntu и лишь потом был создан my_image.

Запустим новый контейнер Docker на основе образа, созданного на предыдущих шагах. Назовем контейнер «test» и получим вывод «Hello world» в результате выполнения команды docker run. Ubuntu, CentOS или Debian — операционная система значения не имеет, синтаксис везде будет одинаковый.

sudo docker run --name test my_image
Hello World

После выключения контейнера, все данные, которые он генерировал за время работы удаляются. Чтобы этого не происходило, предусмотрена возможность монтирования внешних хранилищ. Docker автоматически создает каталог /var/lib/docker/volume, в который можно сохранять данные на постоянной основе и совместно их использовать между несколькими контейнерами. Создадим новое хранилище с именем «selectel»:

sudo docker volume create selectel

Теперь запустим контейнер с примонтированным внешним хранилищем:

sudo docker run --name=test --mount source=selectel,destination=/selectel my_image

Таким образом, все данные, которые появятся в директории /selectel внутри контейнера будут надежно храниться на файловой системе сервера.

Контейнеры Docker предназначены для обеспечения изолированной среды со всеми библиотеками и конфигурациями, необходимыми для работы программного обеспечения. Во время разработки их количество может хаотично, в результате появятся устаревшие и неиспользуемые контейнеры. Ниже мы покажем как удалить ненужные контейнеры.

Предварительно выведем в терминал запущенные контейнеры:

sudo docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b52480dd6110 my_image "echo 'Hello World'" 4 minutes ago Exited (0) 4 minutes ago test

Увидим контейнер, который мы только что запустили. Еще один вариант получить список запущенных контейнеров — добавить параметр -a. Так мы увидим список id контейнеров:

sudo docker container ls –aq
b52480dd6110

Можно остановить один контейнер:

sudo docker container stop [container_id]

А можно все разом:

sudo docker container stop $(docker container ls –aq)

Чтобы очистить все данные, созданные контейнером, можно выполнить следующую команду:

sudo docker container stop $(docker container ls –aq) && docker system prune –af ––volumes

Команда выполняет остановку контейнеров, перечисленных в круглых скобках. Атрибут && предписывает Docker удалить все остановленные контейнеры и тома. Параметры –af указывает, что это должно применяться ко всем контейнерам (a) без необходимости подтверждения (f).

А теперь удалим контейнер. Один или все сразу:

sudo docker container rm [container_id]
sudo docker container rm $(docker container ls –aq)

При удалении ненужных контейнеров можно также задавать фильтры. Например, в примере ниже мы удалим все контейнеры без метки мейнтейнера «selectel».

sudo docker container prune --filter=”label!=maintainer=selectel”

Фильтры имеют следующий синтаксис:

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

sudo docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE my_image latest 889af78121ad 24 hours ago 100MB ubuntu latest 4dd97cefde62 2 weeks ago 72.9MB

Чтобы удалить неиспользуемые образы, нужно воспользоваться их идентификатором из колонки IMAGE ID.

docker image rm [image_id1] [image_id2]

Аналогичным контейнерам образом, удаляемые образы можно фильтровать по меткам или по дате создания. Первая команда удаляет образы с меткой «selectel», а вторая все образы, созданные за последние 24 часа.

sudo docker image prune ––filter=”label=selectel”
sudo docker image prune –a ––filter “until=24h”

Так как контейнеры после остановки не сохраняют внутри себя никакие данные. Например, если в контейнере работала база данных и там за время работы контейнера были созданы объекты и данные, после остановки они пропадут. Для этого, к контейнеру монтируются каталоги, расположенные, непосредственно на диске операционной системы. Чтобы просмотреть все такие каталоги, выполним команду:

sudo docker volume ls

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

sudo docker volume rm [VolumeName]

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

sudo docker network ls
NETWORK ID NAME DRIVER SCOPE 1e31297e1d6a bridge bridge local 783575476ed4 host host local c7c5d2496494 none null local

Чтобы удалить ненужные сети Docker, воспользуемся командой:

sudo docker network rm [networkID]

Команда prune автоматически удаляет все ресурсы, не связанные с контейнером. Это упрощенный способ очистки неиспользуемых образов, контейнеров, томов и сетей.

sudo docker system prune

Можно использовать дополнительные параметры:

  • -a — для удаления всех остановленных контейнеров и неиспользуемых образов.
  • -f — Обойти диалоговое окно подтверждения
  • —volumes — Удаляет все неиспользуемые тома.

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

sudo docker container prune
sudo docker image prune
sudo docker volume prune
sudo docker network prune

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

Работа с репозиторием Docker Hub

Docker Hub — это общедоступный репозиторий образов контейнеров Docker. Каждый раз когда вы создаете собственный контейнер (в примере выше мы делали контейнер на основе операционной системе Ubuntu), с Docker Hub загружается соответствующий образ. Но образы можно не только загружать, но и выгружать. В этом разделе мы расскажем как это сделать.

Прежде чем начать, понадобится учетная запись на Docker Hub. Регистрация бесплатная. Сейчас в нашем тестовом окружении на Docker Hub нет ни одного репозитория. Прежде чем начинать выгрузку создадим один с помощью кнопки Create Repository.

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

sudo docker login -u [docker-hub-username]

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

sudo docker tag my_image [docker-hub-username]/my_image:0.0.1
sudo docker push [docker-hub-username]/my_image:0.0.1
The push refers to repository [docker.io/[docker-hub-username]/my_image] 8c25b6d14dcf: Pushed c20d459170d8: Pushed db978cae6a05: Pushed aeb3f02e9374: Pushed 0.0.1: digest: sha256: size: 1155

В результате, образ появится в репозитории.

Работа с частным репозиторием

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

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

docker run -d -p 5000:5000 --restart=always --name registry registry:2

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

docker tag my_image localhost:5000/my_image
docker push localhost:5000/my_image
docker pull localhost:5000/my_image

Частный репозиторий готов к работе.

Заключение

В статье мы рассмотрели работу с контейнерами на основе Docker, их создание, удаление и размещение в Docker Hub и локальном репозитории. Docker сильно упрощает работу разработчиков и системных администраторов. Легковесные контейнеры потребляют меньшее количество ресурсов (в отличие от виртуальных машин) и полноценно готовы к работе за считанные минуты.

Подготовка собственного образа — Docker: Основы

На Docker Hub выложено множество готовых образов, которые используются администраторами и разработчиками: интерпретаторы и компиляторы языков, веб-сервера, базы данных и многое другое. Большую часть из них можно использовать на серверах без изменений, передав какие-то переменные окружения. Но для любого разрабатываемого приложения нужно создавать свой собственный образ. В него войдет код приложения и все его зависимости. Даже когда нам будет нужно изменить всего лишь конфигурацию, например Nginx, все равно придется создать свой собственный образ, в который добавлен конфигурационный файл.

В этом уроке мы научимся создавать Docker-образ на примере JavaScript проекта: данный язык программирования достаточно распространен в среде разработчиков. Но все описанные принципы так же будут подходить и для других языков. Для создания образа будем использовать популярный микрофреймворк fastify .

Для начала создадим каркас приложения с помощью готового шаблона:

cd /var/tmp # можно выбрать любую директорию mkdir docker-fastify-example cd docker-fastify-example docker run --user $(id -u) -it -w /out -v `pwd`:/out node npm init fastify Need to install the following packages: create-fastify Ok to proceed? (y) y # введите y generated .gitignore generated README.md generated app.js generated .vscode/launch.json generated plugins/README.md generated routes/root.js generated test/helper.js generated plugins/sensible.js generated plugins/support.js generated routes/README.md generated routes/example/index.js generated test/routes/root.test.js generated test/plugins/support.test.js generated test/routes/example.test.js --> project example generated successfully run 'npm install' to install the dependencies run 'npm start' to start the application run 'npm run dev' to start the application with pino-colada pretty logging (not suitable for production) run 'npm test' to execute the unit tests 

Эта команда создаст шаблон приложения в директории /out запущенного контейнера, которая, на самом деле, является директорией /var/tmp/docker-fastify-example на нашей машине. В итоге у нас получается такая структура проекта:

. # docker-fastify-example ├── README.md ├── app.js ├── package.json ├── plugins ├── routes └── test 

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

# Если не стоит npm, # то сюда еще входит установка Node.js npm install npm start # или npm run dev в режиме разработки 

Установку зависимостей нужно выполнить еще до создания образа, так как во время первой установки формируется файл package-lock.json. Он нужен для фиксации зависимостей: с его помощью мы гарантируем, что в образе будут использоваться ровно те зависимости, которые мы подключали во время разработки. Сделать это можно следующим образом:

# внутри директории docker-fastify-example docker run -it -w /out -v `pwd`:/out node npm install added 398 packages, and audited 560 packages in 45s 

Теперь директория с приложением выглядит так:

. ├── README.md ├── app.js ├── node_modules # тут хранятся зависимости ├── package-lock.json # новый файл ├── package.json ├── plugins ├── routes └── test 

Сборка и публикация Docker-образа

Docker создает образ на основе файла Dockerfile, в котором описываются необходимые команды. Мы начнем сразу с примера:

FROM node:20 WORKDIR /app COPY package.json . COPY package-lock.json . RUN npm ci COPY . . ENV FASTIFY_ADDRESS 0.0.0.0 # Команда, которая запускается автоматически # при старте контейнера CMD ["npm", "start"] 

В основном, команды Dockerfile интуитивно понятны. Видно, что мы «упаковываем» приложение в образ, выполняем установку зависимостей и описываем то, как его запустить. Подробнее о командах мы поговорим позже, а сейчас посмотрим, как собирается, запускается и пушится образ в Docker Hub.

Для сборки образа в директории с Dockerfile нужно выполнить команду указанную ниже:

# -t, --tag - имя образа и тега. По умолчанию latest # Точка в конце важна, подробнее про нее дальше docker build -t hexlet/docker-fastify-example . [+] Building 26.4s (12/12) FINISHED => [internal] load build definition from Dockerfile => => transferring dockerfile: 190B => [internal] load .dockerignore => => transferring context: 2B => [internal] load metadata for docker.io/library/node:18 => [auth] library/node:pull token for registry-1.docker.io => [internal] load build context => => transferring context: 63.29MB => [1/6] FROM docker.io/library/node:18@sha256:e5b7b3 => [2/6] WORKDIR /app => [3/6] COPY package.json . => [4/6] COPY package-lock.json . => [5/6] RUN npm ci => [6/6] COPY . . => exporting to image => => exporting layers => => writing image sha256:52f6fe => => naming to docker.io/library/docker-fastify-example 

Сборка образа занимает какое-то время: нужно подождать, пока выполнятся все команды. Как результат, в списке образов появляется образ с именем hexlet/docker-fastify-example и тегом latest. Его можно запустить и убедиться в работоспособности:

# По умолчанию Fastify стартует на 3000 порту # Docker запускает команду npm start docker run -it -p 3000:3000 hexlet/docker-fastify-example "level":30,"time":1651503036761,"pid":22,"hostname":"a9b1ea7fc320","msg":"Server listening at http://0.0.0.0:3000"> 

Для полной проверки, откройте в браузере ссылку http://localhost:3000 и убедитесь что сайт открылся. Остался последний шаг — загрузить образ на Docker Hub. Для этого понадобится подготовительная работа:

  1. Регистрация https://hub.docker.com/
  2. Подключение к аккаунту через запуск команды docker login в терминале. Docker попросит ввести имя пользователя и пароль
  3. Создание репозитория с именем docker-fastify-example в личном кабинете

Теперь, чтобы загрузить образ в Docker Hub, мы должны дать ему правильное имя. По соглашению, часть имени Docker-образа до символа /, должна совпадать с именем вашего пользователя Docker Hub. Чтобы так сделать, вам необходимо запустить команду сборки еще раз:

-t /docker-fastify-example . 

Теперь можно пушить:

-t /docker-fastify-example . # По умолчанию отправляется тег latest docker push /docker-fastify-example 

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

Теги

Теги у Docker-репозиториев изменяемые. Если изменить образ и снова его запушить с тем же тегом, образ поменяется. Для тега latest это ожидаемое поведение, а вот для версий нет. За этим нужно следить самостоятельно и не менять образ для уже существующих тегов. Если меняется образ, то правильно создавать новый тег:

# Используем тег docker build -t /docker-fastify-example:v2 . docker push /docker-fastify-example:v2 

Команды Dockerfile

Dockerfile состоит из команд, которые выполнятся сверху вниз по очереди, формируя файловую систему образа. Каждая последующая команда «видит» результаты предыдущей команды. Ниже мы разберем наиболее популярные команды, которые встречаются в большинстве образов.

FROM

# Варианты # По умолчанию тег latest FROM ubuntu # С явно указанным тегом FROM node:18 

Образ — это в первую очередь файловая система, которая формируется на базе команд описанных в Dockerfile. Docker берет какую-то первоначальную файловую систему и затем изменяет ее в соответствии с описанием. Получившаяся структура файлов и становится образом. Откуда берется первоначальная файловая система?

Практически все образы в Docker формируются не с нуля, а на базе уже существующих образов. Образы формируют дерево, в котором одни образы наследуют файловые системы других образов начиная с базового образа scratch .

# Иерархия образов docker-fastify-example FROM node FROM buildpack-deps:bullseye FROM buildpack-deps:bullseye-scm FROM buildpack-deps:bullseye-curl FROM debian:bullseye FROM scratch 

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

WORKDIR

Команда WORKDIR задает рабочий каталог, относительно которого выполняются все действия во время формирования образа и при входе в контейнер:

-it hexlet/devops-fastify-app bash root@02d29c66ea06:/app# # мы оказались внутри /app 

WORKDIR автоматически создает директорию, если ее еще нет.

COPY

# файлы COPY package.json . # Аналогично # COPY package.json package.json COPY package-lock.json . # Копирование всех файлов внутрь COPY . . 

Команда COPY копирует файлы и директории с хост-машины внутрь Docker-образа. Она принимает два параметра: первый — что копируем, второй — куда копируем и под каким именем. Второй параметр может принимать три варианта:

  • Абсолютный путь, копирование происходит ровно по нему
  • Относительный путь, копирование происходит относительно установленной рабочей директории WORKDIR
  • Точка, файл или директория копируется как есть в рабочую директорию

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

Для полного понимания принципов работы команды COPY , нужно представлять что такое контекст. Помните, когда мы указывали точку во время сборки образа? Это и есть контекст:

-t hexlet/docker-fastify-example . 

Контекст — это директория, относительно которой работает первый параметр в COPY . Обычно контекстом указывают ту директорию, которая содержит Dockerfile. Но это не обязательно, ведь контекстом может быть и другая директория:

# Указана директория уровнем выше # Dockerfile должен лежать в текущей директории, из которой идет запуск docker build -t something .. 

Во время сборки образа, контекст целиком копируется внутрь системных директорий Docker, из которых в образ переносится все, что указано в команде COPY . Из-за этого иногда возникают проблемы. Контекст может содержать директории, которые не должны попадать в образ, например, .git , или зависимости установленные локально (node_modules), так как они все равно устанавливаются заново во время сборки. Чтобы избежать их попадания во внутрь, нужно создать файл .dockerignore и указать там те директории и файлы, которые не должны быть частью контекста. Принцип работы файла такой же, как и у .gitignore.

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

RUN

# Если базовый образ Ubuntu, то доступен apt RUN apt-get update && apt-get install -q curl RUN npm install 

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

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

# -q - ставить автоматически не задавая вопросов RUN apt-get install -q curl 

CMD

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

# Используется CMD docker run -it hexlet/docker-fastify-example # npm start # CMD не используется, так как явно указан bash docker run -it hexlet/docker-fastify-example bash 

ENV

Задает переменные окружения. Команды, выполняющиеся после ENV , видят эти переменные и могут их использовать.

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

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов

Наши выпускники работают в компаниях:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *