Дисклеймер
Вот мы и снова встретились, юный падаван. В этой части цикла статей про контейнеризацию я расскажу тебе про устройство Dockerfile-ов. Сегодня ты узнаешь много вкусной инфы про то, как создать свой собственный Docker — контейнер и забудешь ее и закрепишь знания щепоткой практики. Да, в этот раз желательно поработать руками.
Алсо, Часть 1
Напоминалка
Dockerfile содержит в себе набор инструкций с помощью которых конфигурируется твой будущий контейнер. Чаще всего он лежит в папке с кодом твоей великолепнейшей приложухи и упаковывает ее в красивую коробочку с помощью команды docker build.
Все инструкции в Dockerfile исполняются строго по порядку сверху вниз, пишутся на пендосском красивым капслоком и имеют длину от трех до 10 букв, так что препятствий к запоминанию и восприятию возникнуть не должно.
Шпаргалка со списком инструкций
Здесь их чёртова дюжина, все разные, почти все нужны, без них ничего не получится. Собственно, вот список, смотри, вникай.
- RUN — выполняет команду, заданную в качестве аргумента
- COPY — выполняет копирование файлов в указанное место контейнера
- ADD — аналогичен COPY,за исключением пары нюансов
- FROM — задаёт базовый образ контейнера
- LABEL — служит для записи метаданных. Сюда можно добавить все,что твоей душе угодно: имя автора, версию контейнера,номер мобильного телефона,размер МПХ.Обычно все-таки ограничиваются авторством,версией и датой
- ENV — устанавливает постоянные переменные среды
- CMD — описывает команду с аргументами, которую нужно выполнить при запуске контейнера. Одна на файл. Аргументы могут быть переопределены при запуске контейнера
- WORKDIR — определяет рабочую директорию для следующей инструкции
- ARG — задаёт переменные для передачи в Docker во время сборки образа
- ENTRYPOINT — предоставляет команду с аргументами для вызова во время выполнения контейнера, аргументы этой команды НЕ ПЕРЕОПРЕДЕЛЯЮТСЯ
- USER — определяет пользователя,от чьего имени будут выполняться команды
- EXPOSE — открывает для взаимодействия указанный порт Docker контейнера
- VOLUME — указывает путь к постоянному хранилищу
EXEC- и SHELL-формы
Для инструкций Dockerfile обычно принято прописывать команды. И для этого существует как минимум два типа синтаксиса, например, команды для инструкций RUN, CMD, ENTRYPOINT, FROM могут задаваться в двух формах: shell и exec.
Exec-форма позволяет задать команду в виде JSON-массива. Каждая команда в массиве должна выделяться с помощью «, а не ‘.
С синтаксисом exec-формы связаны следующие особенности:
- Она не вызывает командную оболочку, например, в команде, приведенной ниже, в переменную $HOME не подставится значение.
- Для вызова оболочки в exec-форме нужно исполнить что-то вроде этого:
- В exec-форме также необходимо экранировать «\», это тебе точно пригодится при сборке контейнера с windows-машины.
Shell-форма по стилю близка к привычным башовским командам. В этой форме поданная на вход команда выполняется с помощью дефолтной программной оболочки контейнера (обычно sh), оболочки передаваемой в качестве параметра или оболочки, задаваемой с помощью инструкции SHELL (не перепутай). В shell-форме с помощью «\» можно передавать несколько команд в оболочку сразу.
NOTE: Обязательно объединяй несколько логически связанных команд в одну инструкцию. Зачем — ниже.
We need to go deeper
Настало время узнать кое-какие нюансы о каждой из команд и понять, как, для чего и в каких случаях они применяются:
- FROM — любой Dockerfile начинается с этой команды, потому что она задает имя образа ОС, который будет взят за основу для нового контейнера.
- RUN — создает новый слой во время сборки Docker-образа, запускает в нем указанную команду и коммитит изменения после ее выполнения. Чаще всего нужна для загрузки и установки дополнительных пакетов.
- COPY — сообщает Docker о том, что нужно взять файлы и папки из локального контекста сборки и добавить их в текущую рабочую директорию образа. Если целевая директория не существует, эта инструкция её создаст.
- ADD — аналогична COPY но умеет немного больше. Во-первых, ADD может в добавление файлов из удаленных источников. Во-вторых — умеет распаковывать локальные tar-ники.
NOTE: Dockerfile при своем исполнении знает только про папку, в которой он лежит, и про дочерние относительно первой.
NOTE 2: Обрати свое пристальное внимание на инструкции RUN, ADD, COPY и FROM. Каждая из них создает новый слой в твоем контейнере, тем самым делая его немного больше. Поэтому не злоупотребляй ими.
Например,вот такой кусок кода:
Создаст вот такую структуру контейнера:
- ENV — задает переменные и их значения, которые доступны как на этапе сборки контейнера, так и во время его работы (в отличие от ARG-переменных). ENV-переменные могут быть перезаписаны при запуске контейнера. Рекомендуется использовать для задания констант, не содержащих чувствительной информации.
- ENTRYPOINT — задает команду, с которой запустится контейнер. Запускается в exec- и shell-формах, имеет статус «все очень сложно» с аргументами CMD.
- EXPOSE — показывает,какие порты откроются,если запустить контейнер с помощью команды docker run -P. Позволяет открывать TCP- и UDP-порты, TCP-порты являются дефолтными.
- USER — определяет пользователя/пользователя и группу от имени которого будут выполняться последующие RUN / CMD / ENTRYPOINT команды.
NOTE: Если ты задал группу у пользователя — он будет принадлежать ТОЛЬКО ей. Другие РАНЕЕ сконфигурированные группы будут игнорироваться. Дефолтная группа — рутовская.
- LABEL — инструкция для творческих людей.Позволяет выражать себя с помощью печатных символов на любом языке мира. LABEL-ы родительских образов наследуются дочерними. Опции задаются в формате ключ = значение.
- WORKDIR — задает папку в которой будет исполняться следующая за ней RUN / CMD / ENTRYPOINT / COPY / ADD команда. Можно извращаться по всякому:
Примеры
Рассуждать по поводу инструкций можно еще долго и подробно, но без примеров ты все равно хрен что запомнишь. А запоминать нужно, иначе я вообще не понимаю, зачем ты это читаешь. Тащемта, примеры:
- Бесполезный, но разъясняющий
- Чуть более полезный, даже Nginx есть
Итак, вот ты прочел про то, как собрать и заставить работать свой первый контейнер. Это маленький шаг для человека и мизерный для человечества, но с чего-то же надо начинать, к тому же, дальше будет только больше. Так что, я надеюсь, ты с пользой провел время и готов к продолжению)
Источник: IT Проповедник