Docker build

Что такое Dockerfile

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

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

Файл Docker имеет следующую форму:

не чувствительна к регистру, но по соглашению для ее имен используется ЗАПИСЬ.

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

  • ARG — эта инструкция позволяет вам определять переменные, которые могут быть переданы во время сборки. Вы также можете установить значение по умолчанию.
  • FROM — базовое изображение для построения нового изображения. Эта инструкция должна быть первой инструкцией без комментариев в Dockerfile. Единственное исключение из этого правила — когда вы хотите использовать переменную в аргументе . В этом случае может предшествовать одна или несколько инструкций .
  • LABEL — используется для добавления метаданных к изображению, таких как описание, версия, автор и т. Д. Вы можете указать несколько , и каждая инструкция представляет собой пару «ключ-значение».
  • RUN — команды, указанные в этой инструкции, будут выполняться в процессе сборки. Каждая инструкция создает новый слой поверх текущего изображения.
  • ДОБАВИТЬ — используется для копирования файлов и каталогов из указанного источника в указанное место назначения в образе докера. Источником могут быть локальные файлы, каталоги или URL. Если источником является локальный tar-архив, он автоматически распаковывается в образ Docker.
  • КОПИРОВАТЬ — аналогично но источником может быть только локальный файл или каталог.
  • ENV — Эта инструкция позволяет вам определить переменную среды.
  • CMD — используется для указания команды, которая будет выполняться при запуске контейнера. Вы можете использовать только одну инструкцию в своем Dockerfile.
  • ENTRYPOINT — аналогично , эта инструкция определяет, какая команда будет выполняться при запуске контейнера.
  • WORKDIR — эта директива устанавливает текущий рабочий каталог для инструкций , , , и .
  • ПОЛЬЗОВАТЕЛЬ — Установите имя пользователя или для использования при выполнении любых следующих инструкций , , , и .
  • VOLUME — позволяет подключить каталог хост-машины к контейнеру.
  • EXPOSE — используется для указания порта, на котором контейнер прослушивает во время выполнения.

Чтобы исключить добавление файлов и каталогов в образ, создайте файл в контекстном каталоге. Синтаксис аналогичен файла Git.

Пункт 2.1 Многоступенчатые сборки

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

При многоступенчатой сборке вы создаете промежуточный контейнер-этап, со всеми необходимыми инструментами для компиляции или другого способа получения финального артефакта (то есть окончательного исполняемого файла или набора оных). Затем вы копируете полученный артефакт в конечный образ, отсекая дополнительные зависимости разработки, временные сборочные файлы и тд.

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

Так безопаснее и заодно мы еще и размер образа уменьшаем.

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

#This is the «builder» stage
FROM golang:1.15 as builder
WORKDIR /my-go-app
COPY app-src .
RUN GOOS=linux GOARCH=amd64 go build ./cmd/app-service
#This is the final stage, and we copy artifacts from «builder»
FROM gcr.io/distroless/static-debian10
COPY —from=builder /my-go-app/app-service /bin/app-service
ENTRYPOINT [«/bin/app-service»]

1
2
3
4
5
6
7
8
9

#This is the «builder» stage

FROM golang1.15asbuilder

WORKDIRmy-go-app

COPY app-src.

RUN GOOS=linux GOARCH=amd64 go build.cmdapp-service

#This is the final stage, and we copy artifacts from «builder»

FROM gcr.iodistrolessstatic-debian10

COPY—from=buildermy-go-appapp-servicebinapp-service

ENTRYPOINT»/bin/app-service»

Согласно указанным инструкциям, мы вначале создаем этап сборки, используя контейнер с образом  golang:1.15, который включает в себя весь необходимый инструментарий для GO

FROM golang:1.15 as builder
Мы можем скопировать в него исходный код и собрать его
WORKDIR /my-go-app
COPY app-src .
RUN GOOS=linux GOARCH=amd64 go build ./cmd/app-service

1
2
3
4
5

FROM golang1.15asbuilder

Мыможемскопироватьвнегоисходныйкодисобратьего

WORKDIRmy-go-app

COPY app-src.

RUN GOOS=linux GOARCH=amd64 go build.cmdapp-service

Затем мы определяем следующий этап, основываясь на образе Debian

FROM gcr.io/distroless/static-debian10

1 FROM gcr.iodistrolessstatic-debian10

Мы копируем (используя инструкцию copy) полученный в результате сборки исполняемый файл, используя опцию —from=builder flag

COPY —from=builder /my-go-app/app-service /bin/app-service

1 COPY—from=buildermy-go-appapp-servicebinapp-service

Конечный образ буде включать в себя только минимальный набор библиотек из образа distroless/static-debian-10и наше исполняемый файл приложения.

Никаких сборочных инструментов, никакого исходного кода.

Рекомендуется так же ознакомиться с примером для приложения на Nodejs и с эффективной многоступенчатой сборкой Python-Django приложения.

Взаимодействие с другими частями системы

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

Interactive mode

Самый простой вариант использования Докера, как мы уже убедились — поднять контейнер и выполнить внутри него какую-либо команду:

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

Дело в том, что запускает интерактивную сессию внутри контейнера. Для взаимодействия с ней нужно оставить открытым поток STDIN и запустить TTY (псевдо-терминал). Поэтому для запуска интерактивных сессий нужно не забыть добавить опции и . Как правило их добавляют сразу вместе как . Поэтому правильный способ запуска баша выглядит так: .

Ports

Если запустить nginx такой командой , то nginx не сможет принять ни один запрос, несмотря на то, что внутри контейнера он слушает 80 порт (напомню, что каждый контейнер по умолчанию живет в своей собственной сети). Но если запустить его так , то nginx начнет отвечать на порту 8080.

Флаг позволяет описывать как и какой порт выставить наружу. Формат записи расшифровывается так: пробросить порт 8080 снаружи контейнера в контейнер на порт 80. Причем, по умолчанию, порт 8080 слушается на , то есть на всех доступных интерфейсах. Поэтому запущенный таким образом контейнер доступен не только через , но и снаружи машины (если доступ не запрещен как-нибудь еще). Если нужно выполнить проброс только на loopback, то команда меняется на такую: .

Docker позволяет пробрасывать столько портов, сколько нужно. Например, в случае nginx часто требуется использовать и порт, и для HTTPS. Сделать это можно так: Про остальные способы пробрасывать порты можно прочитать в официальной документации.

Volumes

Другая частая задача связана с доступом к основной файловой системе. Например, при старте nginx-контейнера ему можно указать конфигурацию, лежащую на основной фс. Докер прокинет её во внутреннюю фс, и nginx сможет её читать и использовать.

При работе с Volumes есть несколько важных правил, которые надо знать:

  • Путь до файла во внешней системе должен быть абсолютным.
  • Если внутренний путь (то, что идет после ) не существует, то Докер создаст все необходимые директории и файлы. Если существует, то заменит старое тем, что было проброшено.

Кроме пробрасывания части фс снаружи, Докер предоставляет еще несколько вариантов создания и использования Volumes. Подробнее — в официальной документации.

Переменные окружения

Конфигурирование приложения внутри контейнера, как правило, осуществляется с помощью переменных окружения в соответствии с 12factors. Существует два способа их установки:

  • Флаг . Используется он так:
  • Специальный файл, содержащий определения переменных окружения, который пробрасывается внутрь контейнера опцией .

The Docker platform

Docker provides the ability to package and run an application in a loosely isolated
environment called a container. The isolation and security allow you to run many
containers simultaneously on a given host. Containers are lightweight and contain
everything needed to run the application, so you do not need to rely on what is
currently installed on the host. You can easily share containers while you work,
and be sure that everyone you share with gets the same container that works in the
same way.

Docker provides tooling and a platform to manage the lifecycle of your containers:

  • Develop your application and its supporting components using containers.
  • The container becomes the unit for distributing and testing your application.
  • When you’re ready, deploy your application into your production environment,
    as a container or an orchestrated service. This works the same whether your
    production environment is a local data center, a cloud provider, or a hybrid
    of the two.

High-level build options

Buildx also aims to provide support for high-level build concepts that go beyond
invoking a single build command.

BuildKit efficiently handles multiple concurrent build requests and de-duplicating
work. The build commands can be combined with general-purpose command runners
(for example, ). However, these tools generally invoke builds in sequence
and therefore cannot leverage the full potential of BuildKit parallelization,
or combine BuildKit’s output for the user. For this use case, we have added a
command called .

The command supports building images from compose files, similar to
, but allowing all the
services to be built concurrently as part of a single request.

There is also support for custom build rules from HCL/JSON files allowing
better code reuse and different target groups. The design of bake is in very
early stages and we are looking for feedback from users. Let us know your
feedback by creating an issue in the
Docker buildx
GitHub repository.

Docker, buildx, multi-arch

Создание приложения .NET Core

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

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

Команда создает папку с именем App и консольное приложение Hello World. Измените каталоги и перейдите в папку App из сеанса терминала. Используйте команду , чтобы запустить приложение. Приложение запустится и выведет под командой:

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

Совет

Если вы используете Visual Studio Code, в предыдущем сеансе терминала введите следующую команду:

Откроется папка App, которая содержит проект в Visual Studio Code.

Файл Program.cs должен выглядеть как следующий фрагмент кода C#:

Замените его кодом, который считает числа каждую секунду:

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

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

Важно!

Все параметры после не передаются команде , а передаются в приложение.

Избегать избыточных привилегий

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

1. Rootless контейнеры

Отчет sysdig показал, что 58% образов выполняют процесс в контейнере от root (UID 0). Рекомендуем избегать этого. Существует очень небольшой круг задач, для решения которых нужно запускать контейнер от root, поэтому не забывайте добавлять команду и менять UID пользователя на non-root.

Более того ваша среда выполнения контейнеров может по умолчанию блокировать запуск процессов в контейнере от имени root (например, Openshift требует дополнительные ).

Чтобы настроить non-root контейнер вам потребуется выполнить несколько дополнительных шагов в вашем Dockerfile.

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

  • Предоставить необходимы разрешения на объекты файловой системы, которые процесс читает или записывает.

Вы можете увидеть контейнеры, которые начинаются как root, а затем используют gosu или su-exec для перехода к обычному пользователю.

Если необходимо выполнить команду от имени root, вы можете использовать sudo.

Хотя эти две рекомендации, лучше запуска от имени root, они работают не во всех окружениях, например таких как OpenShift.

Work with builder instances

By default, Buildx uses the driver if it is supported, providing a user
experience very similar to the native . Note that you must use a
local shared daemon to build your applications.

Buildx allows you to create new instances of isolated builders. You can use this
to get a scoped environment for your CI builds that does not change the state of
the shared daemon, or for isolating builds for different projects. You can create
a new instance for a set of remote nodes, forming a build farm, and quickly
switch between them.

You can create new instances using the
command. This creates a new builder instance with a single node based on your
current configuration.

To use a remote node you can specify the or the remote context name
while creating the new builder. After creating a new instance, you can manage its
lifecycle using the ,
, and
commands.
To list all available builders, use .
After creating a new builder you can also append new nodes to it.

To switch between different builders, use .
After running this command, the build commands will automatically use this
builder.

Docker also features a
command that you can use to provide names for remote Docker API endpoints. Buildx
integrates with to ensure all the contexts automatically get a
default builder instance. You can also set the context name as the target when
you create a new builder instance or when you add a node to it.

Options

Name, shorthand Default Description
Add a custom host-to-IP mapping (host:ip)
Set build-time variables
Images to consider as cache sources
Optional parent cgroup for the container
Compress the build context using gzip
Limit the CPU CFS (Completely Fair Scheduler) period
Limit the CPU CFS (Completely Fair Scheduler) quota
, CPU shares (relative weight)
CPUs in which to allow execution (0-3, 0,1)
MEMs in which to allow execution (0-3, 0,1)
Skip image verification
, Name of the Dockerfile (Default is ‘PATH/Dockerfile’)
Always remove intermediate containers
Write the image ID to the file
Container isolation technology
Set metadata for an image
, Memory limit
Swap limit equal to memory plus swap: ‘-1’ to enable unlimited swap
API 1.25+Set the networking mode for the RUN instructions during build
Do not use cache when building the image
, API 1.40+Output destination (format: type=local,dest=path)
API 1.38+Set platform if server is multi-platform capable
Set type of progress output (auto, plain, tty). Use plain to show container output
Always attempt to pull a newer version of the image
, Suppress the build output and print image ID on success
Remove intermediate containers after a successful build
API 1.39+Secret file to expose to the build (only if BuildKit enabled): id=mysecret,src=/local/secret
Security options
Size of /dev/shm
API 1.25+Squash newly built layers into a single new layer
API 1.39+SSH agent socket or keys to expose to the build (only if BuildKit enabled) (format: default|<id>])
Stream attaches to server to negotiate build context
, Name and optionally a tag in the ‘name:tag’ format
Set the target build stage to build.
Ulimit options

Настройка Docker с помощью файла конфигурации

Предпочтительным способом настройки подсистемы Docker в Windows является использование файла конфигурации. Путь к файлу конфигурации — C:\ProgramData\Docker\config\daemon.json. Если этот файл еще не существует, его можно создать.

Примечание

Не все доступные параметры конфигурации Docker применяются к Docker в Windows. В примере ниже показаны параметры конфигурации, которые применяются. Дополнительные сведения о конфигурации подсистемы Docker см. в статье (Файл конфигурации управляющей программы Docker).

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

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

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

Базовый синтаксис

В исходной форме файл Dockerfile может быть очень простым. Следующий пример создает образ, включающий IIS и сайт «hello world». Этот пример включает комментарии (обозначенные с помощью ), поясняющие каждый шаг. В последующих разделах этой статьи более подробно рассматриваются правила синтаксиса Dockerfile и инструкции Dockerfile.

Примечание

Файл Dockerfile необходимо создавать без расширения. Чтобы сделать это в Windows, создайте файл с помощью удобного для вас редактора, а затем сохраните его, используя нотацию «Dockerfile» (вместе с кавычками).

Дополнительные примеры файлов Dockerfile для Windows см. в репозитории файлов Dockerfile для Windows.

Управление контейнерами

Картинка описывает жизненный цикл (конечный автомат) контейнера. Кружками на нём изображены состояния, жирным выделены консольные команды, а квадратиками показывается то, что в реальности выполняется.

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

Запустим nginx так, чтобы он работал в фоне. Для этого после слова run добавляется флаг :

После выполнения команды Докер выводит идентификатор контейнера и возвращает управление. Убедитесь в том, что nginx работает, открыв в браузере ссылку . В отличие от предыдущего запуска, наш nginx работает в фоне, а значит не видно его вывода (логов). Посмотреть его можно командой , которой нужно передать идентификатор контейнера:

Вы также можете подсоединиться к выводу лога в стиле . Для этого запустите . Теперь лог будет обновляться каждый раз, когда вы обновляете страницу в браузере. Выйти из этого режима можно набрав Ctrl + C, при этом сам контейнер остановлен не будет.

Теперь выведем информацию о запущенных контейнерах командой :

Расшифровка столбиков:

  • CONTAINER_ID — идентификатор контейнера. Так же, как и в git, используется сокращенная запись хеша.
  • IMAGE — имя образа, из которого был поднят контейнер. Если не указан тег, то подразумевается latest.
  • COMMAND — команда, которая выполнилась на самом деле при старте контейнера.
  • CREATED — время создания контейнера
  • STATUS — текущее состояние.
  • PORTS — проброс портов.
  • NAMES — алиас. Докер позволяет кроме идентификатора иметь имя. Так гораздо проще обращаться с контейнером. Если при создании контейнера имя не указано, то Докер самостоятельно его придумывает. В выводе выше как раз такое имя у nginx.

(Команда выводит информацию о том, сколько ресурсов потребляют запущенные контейнеры).

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

Если попробовать набрать , то там этого контейнера больше нет. Он удален.

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

Теперь выведем все контейнеры командой . Первыми тремя строчками вывода окажутся:

Здесь как раз два последних наших запуска. Если посмотреть на колонку STATUS, то видно, что оба контейнера находятся в состоянии Exited. То есть запущенная команда внутри них выполнилась, и они остановились. Разница лишь в том, что один завершился успешно (0), а второй с ошибкой (127). После остановки контейнер можно даже перезапустить:

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

New Docker Build secret information

The new flag for docker build allows the user to pass secret
information to be used in the Dockerfile for building docker images in a safe
way that will not end up stored in the final image.

is the identifier to pass into the . This identifier
is associated with the identifier to use in the Dockerfile. Docker
does not use the filename of where the secret is kept outside of the Dockerfile,
since this may be sensitive information.

renames the secret file to a specific file in the Dockerfile command
to use.

For example, with a secret piece of information stored in a text file:

And with a Dockerfile that specifies use of a BuildKit frontend
, the secret can be accessed when performing a :

The secret needs to be passed to the build using the flag.
This Dockerfile is only to demonstrate that the secret can be accessed. As you
can see the secret printed in the build output. The final image built will not
have the secret file:

Получение приложения

Перед запуском приложения необходимо получить исходный код приложения на компьютере. Для реальных проектов обычно клонируется репозиторий. Но в этом учебнике мы создали ZIP-файл, содержащий приложение.

  1. Если вы используете Windows, на локальном компьютере должно быть установлено приложение «Docker для Windows» или Docker Community Edition. См. документацию по установке Docker для Windows. Процесс установки создает ZIP-файл, содержащий пример, доступный по адресу localhost. Если вы используете Mac, установите Docker Desktop для Mac.

  2. Скачайте исходный код для приложения из репозитория Docker. Вы можете скачать для репозитория ZIP-файл. Чтобы скачать ZIP-файл, нажмите зеленую кнопку Code (Код) и выберите Download ZIP (Скачать ZIP). Откройте ZIP-файл и выберите «Извлечь все», чтобы извлечь исходный код приложения из папки app (приложение) в папку на жестком диске.

  3. После извлечения используйте любой редактор кода, чтобы открыть проект. Если вам требуется редактор, можно использовать Visual Studio Code. Вы должны увидеть и два подкаталога ( и ).

Список запущенных Docker контейнеров

Базовый формат Docker:

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

Как вы можете видеть, изображение выше указывает на отсутствие запущенных контейнеров.

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

Для вывода списка контейнеров по их идентификатору используйте параметр :

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

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

Команда предоставляет несколько столбцов информации:

  • Container ID — Уникальный буквенно-цифровой номер для каждого контейнера
  • Image — Образ базовой операционной системы, на котором основан контейнер
  • Command — команда, запустившая контейнер
  • Created — Как давно был создан контейнер
  • Status — Время работы или простои
  • Ports — Указывает любые порты, перенаправляемые в контейнер для работы в сети.
  • Name — Памятное имя, присвоенное программным обеспечением Docker

В бою

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

  1. Скачать новый образ.
  2. Остановить старый контейнер.
  3. Поднять новый контейнер.

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

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

Пункт 1.3. Сделайте root владельцем всех исполняемых файлов и запретите в них запись

Это одно из базовых “хороших практик Dockerfile” — для каждого исполняемого файла в контейнере, владельцем назначить root, даже если исполняется он не под рутом (заметьте — владельцем сделать, а не дать право только root — чувствуйте разницу с этими магическими битами доступа) и не позволяйте кому угодно их перезаписывать.

Это не позволит пользователям, исполняющим эти файлы (запускающим), вносить изменения в бинарники и скрипты, что в свою очередь может быть одним из способов атаки на нашу систему. Следование этой практике даст вам уверенность в неизменности вашего контейнера (Имеется ввиду в неизменности приложения внутри контейнера, внутри образа. А данные там и так и так храниться не должны, если мы только про статику речь не ведем). Неизменяемые контейнеры не обновляют свой код автоматически во время выполнения, и таким образом вы можете предотвратить случайное или злонамеренное изменение запущенного приложения.

Чтобы следовать этой практике, старайтесь избегать вот такого:


WORKDIR $APP_HOME
COPY —chown=app:app app-files/ /app
USER app
ENTRYPOINT /app/my-app-entrypoint.sh

1
2
3
4
5

WORKDIR$APP_HOME

COPY—chown=appapp app-filesapp

USER app

ENTRYPOINTappmy-app-entrypoint.sh

Большую часть времени вы можете просто не использовать опцию “—chown app:app” (или команду “RUN chown …”). Еще раз — пользователь приложения должен иметь права на исполнения файлов не но должен быть их владельцем!

Раздел 2 — уменьшайте поверхность атаки

Эта практика посвящена тому, чтобы минимизировать размер вашего Dockerfile

если вы будете стараться избегать привычки включать ненужные пакеты и открывать ненужные порты, тем самым вы уменьшите поверхность для атаки (да, на первый взгляд звучит капитанисто, но черт побери, давайте честно — а у вас не было такого что “а давайте это на всякий случай сюда запихнем?”, “зачем этот порт — а не знаю, давай оставим, он всегда был” и тп)

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

Приложение в контейнере

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

  1. Всё приложение — один контейнер, внутри которого поднимается дерево процессов: приложение, веб сервер, база данных и всё в этом духе.
  2. Каждый запущенный контейнер — атомарный сервис. Другими словами каждый контейнер представляет из себя ровно одну программу, будь то веб-сервер или приложение.

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

Первый подход крайне редко, но бывает нужен. Например, Хекслет работает в двух режимах. Сам сайт с его сервисами использует вторую модель, когда каждый сервис отдельно, но вот практика, выполняемая в браузере, стартует по принципу “один пользователь — один контейнер”. Внутри контейнера может оказаться всё что угодно в зависимости от практики. Как минимум, там всегда стартует сама среда Хекслет IDE, а она в свою очередь порождает терминалы (процессы). В курсе по базам данных в этом же контейнере стартует и база данных, в курсе, связанном с вебом, стартует веб-сервер. Такой подход позволяет создать иллюзию работы на настоящей машине и резко снижает сложность в поддержке упражнений. Повторюсь, что такой вариант использования очень специфичен и вам вряд ли понадобится.

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

Рейтинг
( Пока оценок нет )
Понравилась статья? Поделиться с друзьями:
Мой редактор ОС
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: