Это третья часть серии статей про Docker и она всецело посвящена Docker-файлам. В первой части основные концепции Docker объясняются на простых примерах из жизни. Во второй статье — краткий обзор экосистемы Docker.
Docker-файл — сердце Docker’а. Он указывает Docker’у как построить образ, который будет использоваться при создании контейнера.
Каждый Docker-образ содержит файл с именем Dockerfile (он без расширения). При вызове docker build предполагается, что Dockerfile будет находиться в текущей рабочей директории. Но с помощью флага -f можно указать другое расположение.
https://tproger.ru/jobs/sistemnyj-administrator-linux/?utm_source=in_text
Контейнер состоит из ряда слоёв. Все слои доступны только для чтения, кроме последнего — он располагается над остальными. Docker-файл указывает порядок добавления слоёв.
Каждый слой — это просто файл с изменением предыдущего слоя. В Unix практически всё является файлом.
Базовый слой, его ещё называют родительским, — это начальный слой.
При загрузке Docker-образа из удалённого репозитория скачиваются только отсутствующие у вас слои. Docker экономит место и время, повторно используя уже существующие слои.
Инструкция Docker-файла — слово в верхнем регистре, которое стоит перед аргументом какой-либо команды. Каждая строка в Docker-файле может содержать инструкцию, все они обрабатываются сверху вниз. Инструкции выглядят так:
FROM ubuntu:18.04
COPY . /app
И только инструкции FROM, RUN, COPY и ADD создают слои в конечном образе. Другие инструкции производят настройку, добавляют метаданные или же просто говорят Docker’у сделать что-либо во время запуска (например открыть порт или выполнить команду).
Эта статья предполагает использование Unix Docker-образа. Вы, конечно, можете использовать и Windows Docker-образ, но он медленнее, менее удобный и, вообще, его не часто применяют. Так что, пользуйтесь Unix по возможности.
FROM ubuntu:18.04
В этом примере хранилище образов — Ubuntu. Ubuntu — название официального Docker-репозитория, в котором и содержится данная ОС.
Заметьте, что этот Docker-файл содержит тег для базового образа: 18.04, который указывает Docker’у, какую именно версию образа нужно использовать. Если тег не указан, по умолчанию берётся последняя версия образа. Но лучше всё же указывать тег базового образа. Когда Docker-файл, приведённый выше, используется для создания локального Docker-образа впервые, он загружает слои, указанные в образе Ubuntu.
При создании Docker-контейнера, вы помещаете наверх слой, который впоследствии можно будет изменить.
Когда образ запущен, и нужно произвести некоторые изменения, файл копируется на верхний слой, доступный для редактирования. Узнать, как это делается, можно здесь.
FROM python:3.7.2-alpine3.8
LABEL maintainer="jeffmshale@gmail.com"
ENV ADMIN="jeff"
RUN apk update && apk upgrade && apk add bash
COPY . ./app
ADD https://raw.githubusercontent.com/discdiver/pachy-vid/master/sample_vids/vid1.mp4 \
/my_app_directory
RUN ["mkdir", "/a_directory"]
CMD ["python", "./my_script.py"]
Но что же это всё обозначает?
В роли базового образа выступает официальный Python-образ с тегом 3.7.2-alpine3.8. Как вы можете увидеть из исходников, образ включает в себя Linux, Python и ничего более. Alpine-образы очень популярны, потому что они маленькие, быстрые и безопасные. Однако Alpine-образы не поставляются сразу со всеми компонентами, характерными для вашей ОС. Некоторые пакеты вам придётся установить самостоятельно.
ENV удобна для обозначения констант. Если константа используется в нескольких местах файла Dockerfile, и вам понадобится изменить её значение позднее, это можно будет сделать в одном месте.
Docker-файл зачастую предоставляет несколько путей решения одной задачи. Будет хорошо, если в вашем решении будет учитываться баланс Docker-соглашений, прозрачность и скорость. К примеру, RUN, CMD и ENTRYPOINT служат различным целям и могут использоваться для выполнения команд.
Чаще всего используется для установки нужных пакетов внутрь контейнера. В примере выше RUN apk update && apk upgrade говорит Docker’у обновить пакеты из базового образа. && apk add bash указывает на то, что для базового образа нужно установить bash.
apk — это сокращение от Alpine Linux package manager. Если вы используете базовый образ не Alpine Linux, то установка пакетов производится командой RUN apt-get.
RUN и её родственные инструкции: CMD, ENTRYPOINT — могут быть как форме оболочки, так и в форме shell-скрипта. Во втором случае используют JSON-синтаксис: RUN ["my_executable", "my_first_param1", "my_second_param2"]. А в примере выше использовалась форма оболочки: RUN apk update && apk upgrade && apk add bash.
Позднее в вашем Docker-файле вы будете создавать новую директорию, используя ["mkdir", "/a_directory"]. Не забывайте, что в JSON нужно использовать двойные кавычки!
В примере выше ADD копировала файлы по URL внутрь директории контейнера. Но официальныя документация не рекомендует использовать ADD так, потому что потом вы попросту не сможете удалить файлы. А дополнительные файлы увеличивают размер образа.
Ещё официальная документация для ясности рекомендует использовать, когда это возможно, COPY вместе ADD. Жаль только, что в Docker’е невозможно использовать ADD и COPY в одной команде.
Заметьте, инструкция содержит символ \. Это нужно для лучшей читаемости — так вы разбиваете длинную инструкцию на несколько строк.
Ещё пара моментов о CMD:
FROM python:3.7.2-alpine3.8
LABEL maintainer="jeffmshale@gmail.com"
# Install dependencies
RUN apk add --update git
# Set current working directory
WORKDIR /usr/src/my_app_directory
# Copy code from your local context to the image working directory
COPY . .
# Set default value for a variable
ARG my_var=my_default_value
# Set code to run at container run time
ENTRYPOINT ["python", "./app/my_script.py", "my_var"]
# Expose our port to the world
EXPOSE 8000
# Create a volume for data storage
VOLUME /my_volume
В Docker-файле вы можете добавлять комментарии. Комментарии начинаются со знака #.
Обычно установка пакетов — приоритетная задача для Docker’а. Как говорилось ранее, есть несколько способов загрузки пакетов при помощи инструкции RUN.
Для Alpine Docker-образа вы используете apk. apk для типичной Linux-сборки — apt-get. Например, пакеты для базового Ubuntu-образа могут быть установлены и обновлены так: RUN apt-get update && apt-get install my_package.
В дополнение к apk и apt-get, Python-пакеты могут быть установлены через pip, wheel и conda. Методы варьируются в зависимости от языка.
Нижележащие слои должны предоставить свое средство установки и управления пакетами. Если возникнет проблема с установкой пакетов, убедитесь, что у вас установлен менеджер пакетов.
Можно использовать RUN вместе с pip и списком нужных пакетов. Для этого объедините команды установки пакетов в одну инструкцию и разделите их символом продолжения строки (\). Этот метод позволяет улучшить читаемость и уменьшить количество слоев (из-за отсутствия возможности использовать несколько RUN инструкций).
Также вы можете запустить установщик, указав ему файл, содержащий все зависимости для вашего образа. Обычно он называется requirements.txt.
Несколько замечаний:
В отличие от ENV-переменных, ARG-переменные не доступны для запущенных контейнеров. Однако вы можете использовать их для установки дефолтных значений для ENV-переменных, когда вы создаёте образ. И затем ENV-переменные сохраняются. Больше про это вы найдёте здесь.
Вместо этого аргументы командной строки, передаваемые docker run myimagename, добавляются к аргументам инструкции ENTRYPOINT. Например, docker run my_image bash добавляет аргумент bash в конец, ко всем другим аргументам ENTRYPOINT.
Docker-файл обязательно должен содержать либо CMD-инструкцию, либо ENTRYPOINT-инструкцию.
В официальной документации есть несколько советов, которые помогут сделать выбор между CMD и ENTRYPOINT для начальной команды:
Как правило, Docker рекомендует вам использовать исполняемую форму с JSON-синтаксисом ENTRYPOINT ["executable", "param1", "param2"].
Используйте команду docker run с флагом -p для пробрасывания и сопоставления нескольких портов во время запуска. Флаг в верхнем регистре -P будет пробрасывать все открытые порты.
Источник статьи: https://tproger.ru/translations/docker-instuction/
Docker-образы
Docker-образ создаётся во время сборки, а Docker-контейнер — во время запуска приложения.Docker-файл — сердце Docker’а. Он указывает Docker’у как построить образ, который будет использоваться при создании контейнера.
Каждый Docker-образ содержит файл с именем Dockerfile (он без расширения). При вызове docker build предполагается, что Dockerfile будет находиться в текущей рабочей директории. Но с помощью флага -f можно указать другое расположение.
https://tproger.ru/jobs/sistemnyj-administrator-linux/?utm_source=in_text
Контейнер состоит из ряда слоёв. Все слои доступны только для чтения, кроме последнего — он располагается над остальными. Docker-файл указывает порядок добавления слоёв.
Каждый слой — это просто файл с изменением предыдущего слоя. В Unix практически всё является файлом.
Базовый слой, его ещё называют родительским, — это начальный слой.
При загрузке Docker-образа из удалённого репозитория скачиваются только отсутствующие у вас слои. Docker экономит место и время, повторно используя уже существующие слои.
Инструкция Docker-файла — слово в верхнем регистре, которое стоит перед аргументом какой-либо команды. Каждая строка в Docker-файле может содержать инструкцию, все они обрабатываются сверху вниз. Инструкции выглядят так:
FROM ubuntu:18.04
COPY . /app
И только инструкции FROM, RUN, COPY и ADD создают слои в конечном образе. Другие инструкции производят настройку, добавляют метаданные или же просто говорят Docker’у сделать что-либо во время запуска (например открыть порт или выполнить команду).
Эта статья предполагает использование Unix Docker-образа. Вы, конечно, можете использовать и Windows Docker-образ, но он медленнее, менее удобный и, вообще, его не часто применяют. Так что, пользуйтесь Unix по возможности.
Несколько Docker-инструкций
- FROM — задаёт родительский (главный) образ;
- LABEL — добавляет метаданные для образа. Хорошее место для размещения информации об авторе;
- ENV — создаёт переменную окружения;
- RUN — запускает команды, создаёт слой образа. Используется для установки пакетов и библиотек внутри контейнера;
- COPY — копирует файлы и директории в контейнер;
- ADD — делает всё то же, что и инструкция COPY. Но ещё может распаковывать локальные .tar файлы;
- CMD — указывает команду и аргументы для выполнения внутри контейнера. Параметры могут быть переопределены. Использоваться может только одна инструкция CMD;
- WORKDIR — устанавливает рабочую директорию для инструкции CMD и ENTRYPOINT;
- ARG — определяет переменную для передачи Docker’у во время сборки;
- ENTRYPOINT — предоставляет команды и аргументы для выполняющегося контейнера. Суть его несколько отличается от CMD, о чём мы поговорим ниже;
- EXPOSE — открывает порт;
- VOLUME — создаёт точку подключения директории для добавления и хранения постоянных данных.
Инструкции и примеры к ним
Docker-файл чисто теоретически может содержать только одну строчку:FROM ubuntu:18.04
FROM
Docker-файл должен начинаться с инструкции FROM или ARG, за которой следует FROM. Команда FROM говорит Docker’у использовать базовый образ, который соответствует репозиторию и тегу.В этом примере хранилище образов — Ubuntu. Ubuntu — название официального Docker-репозитория, в котором и содержится данная ОС.
Заметьте, что этот Docker-файл содержит тег для базового образа: 18.04, который указывает Docker’у, какую именно версию образа нужно использовать. Если тег не указан, по умолчанию берётся последняя версия образа. Но лучше всё же указывать тег базового образа. Когда Docker-файл, приведённый выше, используется для создания локального Docker-образа впервые, он загружает слои, указанные в образе Ubuntu.
При создании Docker-контейнера, вы помещаете наверх слой, который впоследствии можно будет изменить.
Когда образ запущен, и нужно произвести некоторые изменения, файл копируется на верхний слой, доступный для редактирования. Узнать, как это делается, можно здесь.
Подробнее про Docker-файл
Кроме того, что ваш однострочный образ сжат, он ещё и медленный, предоставляет мало информации и ничего не делает во время запуска контейнера. Посмотрите на более длинный Docker-файл, который запускает более легковесный образ, а также выполняет скрипт во время запуска.FROM python:3.7.2-alpine3.8
LABEL maintainer="jeffmshale@gmail.com"
ENV ADMIN="jeff"
RUN apk update && apk upgrade && apk add bash
COPY . ./app
ADD https://raw.githubusercontent.com/discdiver/pachy-vid/master/sample_vids/vid1.mp4 \
/my_app_directory
RUN ["mkdir", "/a_directory"]
CMD ["python", "./my_script.py"]
Но что же это всё обозначает?
В роли базового образа выступает официальный Python-образ с тегом 3.7.2-alpine3.8. Как вы можете увидеть из исходников, образ включает в себя Linux, Python и ничего более. Alpine-образы очень популярны, потому что они маленькие, быстрые и безопасные. Однако Alpine-образы не поставляются сразу со всеми компонентами, характерными для вашей ОС. Некоторые пакеты вам придётся установить самостоятельно.
LABEL
Следующая инструкция — LABEL. LABEL добавляет метаданные к образу, предоставляет контактную информацию. Она не замедляет процесс запуска и не занимает много места, наоборот, обеспечивает образ полезной информацией, так что обязательно используйте её. Больше про LABEL читайте здесь.ENV
ENV создаёт переменную окружения, которая становится доступной во время запуска контейнера. В примере выше вы могли видеть использование переменной ADMIN при создании контейнера.ENV удобна для обозначения констант. Если константа используется в нескольких местах файла Dockerfile, и вам понадобится изменить её значение позднее, это можно будет сделать в одном месте.
Docker-файл зачастую предоставляет несколько путей решения одной задачи. Будет хорошо, если в вашем решении будет учитываться баланс Docker-соглашений, прозрачность и скорость. К примеру, RUN, CMD и ENTRYPOINT служат различным целям и могут использоваться для выполнения команд.
RUN
RUN создаёт слой во время запуска. Docker фиксирует состояние образа после каждой инструкции RUN.Чаще всего используется для установки нужных пакетов внутрь контейнера. В примере выше RUN apk update && apk upgrade говорит Docker’у обновить пакеты из базового образа. && apk add bash указывает на то, что для базового образа нужно установить bash.
apk — это сокращение от Alpine Linux package manager. Если вы используете базовый образ не Alpine Linux, то установка пакетов производится командой RUN apt-get.
RUN и её родственные инструкции: CMD, ENTRYPOINT — могут быть как форме оболочки, так и в форме shell-скрипта. Во втором случае используют JSON-синтаксис: RUN ["my_executable", "my_first_param1", "my_second_param2"]. А в примере выше использовалась форма оболочки: RUN apk update && apk upgrade && apk add bash.
Позднее в вашем Docker-файле вы будете создавать новую директорию, используя ["mkdir", "/a_directory"]. Не забывайте, что в JSON нужно использовать двойные кавычки!
COPY
Инструкция COPY . ./app говорит Docker’у, что нужно скопировать файлы и папки из вашей локальной сборки в рабочую директорию образа. COPY создаст все нужные папки, если они отсутствуют.ADD
ADD делает то же самое, что и COPY, но с двумя отличиями. ADD может загружать файлы по URL, а также извлекать локальные TAR-файлы.В примере выше ADD копировала файлы по URL внутрь директории контейнера. Но официальныя документация не рекомендует использовать ADD так, потому что потом вы попросту не сможете удалить файлы. А дополнительные файлы увеличивают размер образа.
Ещё официальная документация для ясности рекомендует использовать, когда это возможно, COPY вместе ADD. Жаль только, что в Docker’е невозможно использовать ADD и COPY в одной команде.
Заметьте, инструкция содержит символ \. Это нужно для лучшей читаемости — так вы разбиваете длинную инструкцию на несколько строк.
CMD
CMD — инструкция для запуска чего-либо во время запуска самого контейнера. По ходу сборки она не фиксирует никакого результата. В примере выше во время сборки запускался скрипт my_script.py.Ещё пара моментов о CMD:
- Только одна CMD-инструкция на весь Docker-файл. Иначе все кроме последней будут проигнорированы;
- CMD может включать исполняемый файл;
- Если же CMD не содержит никакого файла, обязательно должна быть инструкция ENTRYPOINT. В этом случает обе инструкции должны быть в формате JSON;
- Аргументы командной строки для запуска Docker переопределяют аргументы, предоставленные CMD в Docker-файле.
Готовы к большему?
В следующем примере представлены ещё несколько Docker-инструкций:FROM python:3.7.2-alpine3.8
LABEL maintainer="jeffmshale@gmail.com"
# Install dependencies
RUN apk add --update git
# Set current working directory
WORKDIR /usr/src/my_app_directory
# Copy code from your local context to the image working directory
COPY . .
# Set default value for a variable
ARG my_var=my_default_value
# Set code to run at container run time
ENTRYPOINT ["python", "./app/my_script.py", "my_var"]
# Expose our port to the world
EXPOSE 8000
# Create a volume for data storage
VOLUME /my_volume
В Docker-файле вы можете добавлять комментарии. Комментарии начинаются со знака #.
Обычно установка пакетов — приоритетная задача для Docker’а. Как говорилось ранее, есть несколько способов загрузки пакетов при помощи инструкции RUN.
Для Alpine Docker-образа вы используете apk. apk для типичной Linux-сборки — apt-get. Например, пакеты для базового Ubuntu-образа могут быть установлены и обновлены так: RUN apt-get update && apt-get install my_package.
В дополнение к apk и apt-get, Python-пакеты могут быть установлены через pip, wheel и conda. Методы варьируются в зависимости от языка.
Нижележащие слои должны предоставить свое средство установки и управления пакетами. Если возникнет проблема с установкой пакетов, убедитесь, что у вас установлен менеджер пакетов.
Можно использовать RUN вместе с pip и списком нужных пакетов. Для этого объедините команды установки пакетов в одну инструкцию и разделите их символом продолжения строки (\). Этот метод позволяет улучшить читаемость и уменьшить количество слоев (из-за отсутствия возможности использовать несколько RUN инструкций).
Также вы можете запустить установщик, указав ему файл, содержащий все зависимости для вашего образа. Обычно он называется requirements.txt.
WORKDIR
Меняет текущую рабочую директорию в контейнере для инструкций: COPY, ADD, RUN и ENTRYPOINT.Несколько замечаний:
- Предпочтительно задать абсолютный путь с помощью WORKDIR, а не перемещаться по файловой системе с помощью команд cd в Docker-файле;
- WORKDIR автоматически создаёт директорию, если её ещё нет;
- Можно использовать несколько WORKDIR-инструкций. Если используются относительные пути — каждая инструкция поменяет рабочую директорию.
ARG
Определяет переменную для передачи из командной строки в образ. Для ARG можно указать значение по умолчанию: ARG my_var=my_default_value.В отличие от ENV-переменных, ARG-переменные не доступны для запущенных контейнеров. Однако вы можете использовать их для установки дефолтных значений для ENV-переменных, когда вы создаёте образ. И затем ENV-переменные сохраняются. Больше про это вы найдёте здесь.
ENTRYPOINT
ENTRYPOINT тоже позволяет вам задавать дефолтные команды и аргументы во время запуска контейнера. Она похожа на CMD, но параметры ENTRYPOINT не переопределяются, если контейнер запущен с параметрами командной строки.Вместо этого аргументы командной строки, передаваемые docker run myimagename, добавляются к аргументам инструкции ENTRYPOINT. Например, docker run my_image bash добавляет аргумент bash в конец, ко всем другим аргументам ENTRYPOINT.
Docker-файл обязательно должен содержать либо CMD-инструкцию, либо ENTRYPOINT-инструкцию.
В официальной документации есть несколько советов, которые помогут сделать выбор между CMD и ENTRYPOINT для начальной команды:
- Если вам нужно запускать одну и туже команду несколько раз, выбирайте ENTRYPOINT;
- Используйте ENTRYPOINT, когда ваш контейнер выступает в роли исполняющейся программы;
- При наличии дополнительных дефолтных аргументов, которые могут быть изменены через командную строку, лучше подойдёт CMD.
Как правило, Docker рекомендует вам использовать исполняемую форму с JSON-синтаксисом ENTRYPOINT ["executable", "param1", "param2"].
EXPOSE
Инструкция EXPOSE показывает, какой порт пробрасывать из контейнера.Используйте команду docker run с флагом -p для пробрасывания и сопоставления нескольких портов во время запуска. Флаг в верхнем регистре -P будет пробрасывать все открытые порты.
VOLUME
VOLUME определяет, где контейнер будет хранить постоянные данные и получать к ним доступ.Заключение
В этой статье не были упомянуты такие инструкции, как USER, ONBUILD, STOPSIGNAL, SHELL, и HEALTHCHECK, информацию про них вы сможете найти здесь.Источник статьи: https://tproger.ru/translations/docker-instuction/