Рубрики
Uncategorized

Использование Ansible-Container для создания следующего базового изображения приложения

Статья описывает подход для Anisible-Conticer, который будет использоваться для создания и создания изображений приложений в Docker. В частности, выбирая систему init, запускаю несколько услуг в контейнере.

Автор оригинала: Vyacheslav.

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

Обычно те, кто включает, но не ограничивается:

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

Возможно, каждая компания или агентство, посвященное докеренным приложениям, имеют или реализовано такое. До сих пор вы можете найти его в виде сложной оболочки и макияжа, особенно если BaseImage выделяется для нескольких ОС-эс.

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

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

Изображение здание ботистота с непревзойденным контейнером

Папки и файлы организации

Вы можете запустить процесс здания, используя любой инструмент, который вам нравится. С моего опыта — я нахожу до сих пор со следующим подходом: https://github.com/Voronenko/container-image-boilerplate

требования .txt — Определяет любые конкретные инструменты PY & libs, которые вы хотите использовать вместе с Anisible-Container. .Projmodules — Список зависимостей (ролей, развертываемых, и т. Д.) Необходимо скомпилировать базовое изображение. Формат, похожий на GitModules, но без прямых ссылок для совершения. Пример:

[submodule "roles/sa-nginx-container"]
        path = roles/softasap.sa-nginx-container
        url = https://github.com/softasap/sa-nginx-container.git
[submodule "roles/sa-uwsgi-container"]
        path = roles/softasap.sa-uwsgi-container
        url = https://github.com/softasap/sa-uwsgi-container.git
[submodule "roles/sa-include"]
        path = roles/softasap.sa-include
        url = https://github.com/softasap/sa-include.git
[submodule "deployables/application"]
        path = deployables/application
        url = https://github.com/voronenko-p/django-sample.git

init.sh && init_quick.sh — разрешить внешние зависимости в определенных местах (роли под ролями, развертывами под развертывами, и т. Д.)

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

version.txt — информационный файл Gitflow на основе выпуска (x.y.z)

image.txt — Дополнительная информация о изображении, построенном для метки и толкания деталей.

Makefile && Docker-helper.sh — Оркестровские коммунальные услуги, обсуждаемые в следующей главе.

Docker-Compose.yml — Обычно я также предоставляю конфигурацию Docker-Compose, поэтому изображение может быть немедленно попробовать.

Container.yml — определение изображения, которое вы собираетесь построить

И, конечно, .gitignore. — Мы определенно не хотим совершать внешние ресурсы. P-ENV — Виртуальная среда, созданная во время сборки, Несеменное развертывание — Переходный выход, производимый самим асетим-контейнером.

roles/*
ansible-deployment/*
p-env/*
deployables/*
*.retry

Создание процесса оркестора

Makefile Image Fallements после фаз: инициализация

чистый

Сбрасывает проект до начального состояния, удалив все строить каталоги и артефакты

clean:
        @rm -rf .Python p-env roles ansible-deployment

Инициализация

Анализируют .Projmodules и проверяет необходимые роли и развертываемые

initialize:
        @init_quick.sh

P-Env/Bin/Ansible-Container

Внутренняя задача — создает и инициализирует виртуальную среду с помощью Ansible-Container под P-ENV/Directory.

p-env/bin/ansible-container: p-env/bin/pip
        @touch $@

p-env/bin/pip: p-env/bin/python
        p-env/bin/pip install -r requirements.txt

p-env/bin/python:
        virtualenv -p $(python) --no-site-packages p-env
        @touch $@

строить

Выполняет Ansible-Container для Container.yml, обеспечивая путь к ролям. Название проекта влияет на то, как будет называться изображения.

build:  p-env/bin/ansible-container
        @p-env/bin/ansible-container --debug --project-name $(ROLE_NAME) build --roles-path ./roles/ -- -vvv
        @echo "Application docker image was build"

пробежать и остановиться

Потенциально, Ansible-Container позволяет немедленно запустить и останавливать изображения таким образом, как Docker-Compose. Из моего опыта, это не всегда работает,

  • Container.yml основан на 2-й версии спецификации Docker-compose, в то время как мне обычно нужно как минимум 3.1 в производстве. В любом случае предусмотрены шаги — они могут работать в вашем случае. Я обычно заканчиваю с отдельным docker-compose.yml v3.1 + в каталоге.
run:  p-env/bin/ansible-container
        @echo p-env/bin/ansible-container --debug --project-name $(ROLE_NAME) run --roles-path ./roles/ -- -vvv
        @p-env/bin/ansible-container --debug --project-name $(ROLE_NAME) run --roles-path ./roles/ -- -vvv
        @echo "Application environment was started"

stop:   p-env/bin/ansible-container
        @echo p-env/bin/ansible-container --debug --project-name $(ROLE_NAME) stop
        @p-env/bin/ansible-container --debug --project-name $(ROLE_NAME) stop
        @echo "Application environment was stopped"

Тег и толчок

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

Пример. Пример: правильно теги API и изображения Nginx построены и подталкивают их в Docker Hub.

tag:
        @docker tag $(ROLE_NAME)-api:latest softasap/sa-container-box-examples:$(ROLE_NAME).api.$(ROLE_VERSION)
        @docker tag $(ROLE_NAME)-api:latest softasap/sa-container-box-examples:$(ROLE_NAME).api.latest
        @docker tag $(ROLE_NAME)-nginx:latest softasap/sa-container-box-examples:$(ROLE_NAME).nginx.$(ROLE_VERSION)
        @docker tag $(ROLE_NAME)-nginx:latest softasap/sa-container-box-examples:$(ROLE_NAME).nginx.latest

push:
        @docker push softasap/sa-container-box-examples:$(ROLE_NAME).api.$(ROLE_VERSION)
        @docker push softasap/sa-container-box-examples:$(ROLE_NAME).api.latest
        @docker push softasap/sa-container-box-examples:$(ROLE_NAME).nginx.$(ROLE_VERSION)
        @docker push softasap/sa-container-box-examples:$(ROLE_NAME).nginx.latest


Составные помощники

Запуск, остановка и демонстрация Docker-Compose управляемых контейнеров.

compose-up:
        @docker-compose up --no-recreate

compose-stop:
        @docker-compose stop

compose-down: compose-stop
        @docker-compose rm --force

Это все. Вернуться к первичной цели.

Для базового изображения я обычно хочу:

  • Согласованная организация папки (я не хочу догадаться каждый раз, когда и как мне нужен логика для бега),
  • Уплотняя система init.
  • Дополнительная поддержка для работы нескольких процессов на контейнер (до тех пор, пока контейнер остается односторонним логическим блоком — это не противоречит Docker Philosophy).
  • В зависимости от проекта, который я хочу использовать разные базовые изображения и не хотеть погружаться в специфику с компиляцией каждый раз.
  • Возможность запустить логику под пользовательскими пользователями внутри контейнера и синхронизировать, при необходимости файлов и папок с хост-системой.

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

Почему действительный init для контейнеров важен

Хотя люди говорят, что надлежащим докерским микромервицем следует запускать один выделенный процесс, не всегда достижимо в реальном мире. Более правильно сказать, что Docker предлагает философию проведения единой логической службы на контейнер. Логическая служба может состоять из множественных процессов ОС. Иногда вам действительно нужно бежать более одного сервиса в контейнере докера. Это особенно верно, если вы адаптируете некоторое приложение, которое ранее работало в автономной среде VPS.

Почему процесс INIT важен: работающие процессы могут быть визуализированы на дереве: каждый процесс может порождать дочерние процессы, и каждый процесс имеет родитель, кроме максимального процесса. Этот максимальный процесс — это процесс инициализации. Он начинается, когда вы запускаете свой контейнер и всегда имеете PID 1. Этот процесс INIT отвечает за запись остальной части системы, включая запуск вашего приложения. Когда какой-то процесс завершается, он превращается в SMTH, называемый «несущественным процессом», также известный как «процессом зомби» (https://en.wikipedia.org/wiki/zombie_process). По простым словам, это те, которые расторжены, но не были (все же) ждали их родительских процессов.

Но что, если родительский процесс прекращается (намеренно или непреднамеренно)? Что происходит, тогда к его порожденным процессам? У них больше нет родительского процесса Итак, они становятся «сиротами» (https://en.wikipedia.org/wiki/orphan_process).

И именно здесь инициативный процесс пинает. Это становится новым родителем (принимает) детские детские процессы, даже если они никогда не были созданы непосредственно процессом INIT. Ядро операционной системы автоматически обрабатывает усыновление. Более того: операционная система ожидает, что процесс инициативы тоже пожинать детей.

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

Больше чтения на тему:

  • https://medium.com/@gchudnov/trapping-signals-in-docker-containers-7a57fdda7d86
  • https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/

Upstart, Systemd, Sysv обычно слишком тяжелыми (излишек), который должен использоваться внутри докера (+ не всегда легко возможно). Каковы варианты?

Кандидаты для процесса инициализации контейнера

В момент написания статьи чаще всего использовали подходы понижению:

Пользовательский письменный скрипт init

Согласно Docker Documentation, https://docs.docker.com/engine/admin/multi-service_container/посмотрите на пример доказательства концепции такого скрипта ниже

#!/bin/bash

# Start the first process
./my_first_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_first_process: $status"
  exit $status
fi

# Start the second process
./my_second_process -D
status=$?
if [ $status -ne 0 ]; then
  echo "Failed to start my_second_process: $status"
  exit $status
fi

# Naive check runs checks once a minute to see if either of the processes exited.
# This illustrates part of the heavy lifting you need to do if you want to run
# more than one service in a container. The container will exit with an error
# if it detects that either of the processes has exited.
# Otherwise it will loop forever, waking up every 60 seconds

while /bin/true; do
  ps aux |grep my_first_process |grep -q -v grep
  PROCESS_1_STATUS=$?
  ps aux |grep my_second_process |grep -q -v grep
  PROCESS_2_STATUS=$?
  # If the greps above find anything, they will exit with 0 status
  # If they are not both 0, then something is wrong
  if [ $PROCESS_1_STATUS -ne 0 -o $PROCESS_2_STATUS -ne 0 ]; then
    echo "One of the processes has already exited."
    exit -1
  fi
  sleep 60
done

Будет работать, но на самом деле не гарантирует пожинать … Давайте рассмотрим более надежные альтернативы.

Глупость

Dumb-init — это простой процессорный руководитель и система init, предназначенная для работы в виде PID 1 внутри минимальных контейнеров (таких как Docker). Он развернут как маленький, статически связанный двоичный бинарный в C.

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

Project Repo: https://github.com/yelp/dumb-init

Тихо

Tini рекламирует себя как крошечный, но действительный init для контейнеров. Обещания:

  • Защита от программного обеспечения, которое случайно создает процессы зомби
  • Обеспечивает работу обработчиков сигналов по умолчанию для программного обеспечения, которое вы запускаете в своем документе Docker.
  • Легко ввести: Docker Images, работаю без TINI, будет работать с TINI без каких-либо изменений.

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

Project Repo: https://github.com/krallin/tini

Запустить его

Runit — это кроссплатформенная схема init inix с руководством обслуживания, замена Sysvinit и других схем init. Он работает на GNU/Linux, BSD, может быть легко адаптирован к другим операционным системам Unix. Руководство программы предназначена для запуска в качестве процесса UNIX NO 1, он автоматически запускается автоматически заменой init/sbin/init, если это запускается ядром.

Сайт проекта: http://smarden.org/runit/

S6.

S6 является проектом, фактически бравшими руками по адресу http://skarnet.org/software/s6/overview.html. S6 содержит коллекцию коммунальных услуг, вращающихся вокруг контроля и управления процессором, регистрацией и инициализацией системы. Более того, специально для Docker существует вспомогательный проект, так называемый «S6-наложение» https://github.com/just-containers/s6-verlay

S6 предоставляет:

  • Легкий процесс инициатива с поддержкой инициализации (CONT-INIT.D), доработка (cont-final.d), а также исправления прав собственности (Fix-attrs.d).
  • S6-наложение обеспечивает правильную функциональность PID 1 внутри контейнера Docker. Процессы зомби будут правильно очищены.
  • Поддержка нескольких процессов в одном контейнере («Услуги»)
  • Пригодным для использования со всеми базовыми изображениями — Ubuntu, Centos, Fedora
  • Распределен как один файл .tar.gz, чтобы сохранить количество слоев вашего изображения.
  • Целый набор коммунальных услуг, включенных в S6 и S6-портативные Utils. Они включают удобные и композитные утилиты.
  • Журнал Вращающийся вне коробки через Logutil-Service, который использует S6-журнал под капотом.

My_init.

Часть проекта Phance BaseImage Project https://github.com/phusion/BaseImage-Docker, который в настоящее время нацелен на Ubuntu 16:04, Ubuntu 14:04 OS-ES. Состоит из пользовательских письменных файлов PY и обернутая необязательного рутина.

Предоставляет

  • Защита от программного обеспечения, которое случайно создает процессы зомби — пожинает, реализуется как часть скрипта управления.
  • Кроме того, поддерживает файлы запуска в каталогах init.d и rc.local.
  • Поддерживает дополнительные дополнительные услуги внутри контейнера через Runit: Cron, SSH
  • обрабатывает дополнительную магию с окружающей средой

Требуется: Python внутри вашего контейнера. В настоящей форме только ограничена базовая система Ubuntu.

Руководство?

Это известный менеджер процессов обычно используется с приложениями Python. Я часто видел людей, пытающихся использовать его как систему init. Но: Supervisor явно упоминает, что это не должно управлять своим процессом INIT. Если у вас есть какой-то сам подпроцесс Fork, он не будет очищен руководителем. Таким образом, вы в любом случае должны выбрать другую систему init.

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

Более ?

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

Кандидаты для работы нескольких услуг внутри контейнера.

От упомянутых выше и в то же время легкий, хуже, чтобы упомянуть:

Супервизор

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

Запустить его

Рукослины с швейцарским ножом набор утилит, один из них runsvdir. (http://smarden.org/runit/runsvdir.8.html) Это позволяет определять набор «обслуживания определений» в некоторых каталогах и ухаживает на запуск их при запуске.

Типичные примеры взаимодействия:

/usr/bin/sv статус/etc/Сервис/ — Получить статус услуг, перечисленных в папке конфигурации

/usr/bin/sv -w 10 down/etc/service/* — Выключить все услуги с таймаутом 10

S6 (в объеме проекта S6-Overlay)

В отличие от супервайзера S6 использует структуру папки для управления службами, аналогичной руганию. S6-наложение требует их под/etc/services.d перед запуском init (затем копирует их в/var/run/s6/services).

services
    └ nginx
        └ run

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

#!/bin/bash
set -e
exec nginx -c /etc/nginx/nginx.conf

Услуги контролируются двоичными S6-SVC. Он имеет количество вариантов, но основная идея заключается в том, что вы даете ей каталог службы. Так, например, если я хотел отправить SIGHUP в Nginx, я бы сделал S6-SVC -H/var/run/s6/services/nginx. Примечание: это/var/run, а не/etc/services.d; Это хуг отличия от рутина. И, наконец, то -h для SIGHUP.

S6-Overlay поставляется с несколькими встроенными версиями, поэтому вы можете загрузить тот, который соответствует вашу настройку Linux. Если вы хотите использовать S6 напрямую, пользователи Alpine и несколько других ароматизаторов Linux могут просто установить его из своего менеджера по пакетам. Мы бегаем Debian, и для этого нет PPA, поэтому нам придется компилировать S6 самостоятельно

Более ?

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

Рабочие процессы как другой пользователь

По умолчанию контейнеры Docker работают как пользователь root. Это плохо, потому что:

  • Приложение может изменить вещи, которые оно не должно быть
  • Если приложение делится папкой с базовым хостом, все созданные файлы будут принадлежать корню
  • Если контейнер скомпрометируется — ну, все же плохо, если они root.

Если вы хотите понять, насколько UID и GID работают в контейнерах Docker, посмотрите на эту статью: https://medium.com/@mccode/understanding-how-uid-and-gid-work-in-docker-containers-c37a01d01cf

Каковы варианты:

Докерский родной

Установить на уровне докерафила

# Create an app user so our program doesn't run as root.
RUN groupadd -r app &&\
    useradd -r -g app -d /home/app -s /sbin/nologin -c "Docker image user" app
...
USER app

или пройти как параметры на Docker Run

docker run --rm --group-add audio --group-add nogroup --group-add 777 busybox id
uid=0(root) gid=0(root) groups=10(wheel),29(audio),99(nogroup),777

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

каприз

Это утилита, которая поставляется с руганием (http://smarden.org/runit/chpst.8.html) — вы можете легко использовать его, если у вас уже есть Runit в рамках вашей системы init.

Phance’s Setuser

Если вы выбрали образ Phance в качестве основы, у вас есть setuser по пути https://github.com/phuse/baseimage-docker/blob/master/image/bin/setuser.

Sudo.

Ну, вы можете установить Sudo внутри контейнера. Некоторые люди делают. Но ты хочешь?

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

Извините за повторение, но позвольте мне еще раз подчеркнуть: если вы хотите альтернативу пользовательским макияжам и тоннам сложных файлов Shell, попробуйте Аналимный контейнер. Анализируемый контейнер обеспечивает лучшую альтернативу command && command && command (и так далее) синтаксис вы боролись с созданием контейнеров. Поскольку Anisible находится в основе неисправного контейнера, вы можете сделать контейнер, полностью предсказуемый и повторяемый и более читаемый.

Я должен признать, что, хотя он уже прошел 0.9.1, несовместный контейнер по-прежнему в ранних возрастах с некоторыми громоздкими побочными эффектами время от времени (https://medium.com/@v_voronenko/evaluation-ansible-container -AS-A-Tool-for-custom-docker-Containers-build-500A0395A4C8), но он действительно становится более надежным каждому незначительному выпуску, поэтому, если вы попробуете его сейчас — ваше производство будет готово к понятию, когда он выпущен .. Отказ

Ранее беглый внутренний контейнер требуется установку многих ненужных пакетов, что вызывает большие размеры изображения. Ansible-Cointainer ввел другой подход: комбинация дирижера (управление контейнером с помощью аварийных и необходимых инструментов) и целевой контейнер. Это позволяет сохранить целевой размер изображения небольшого размера, и этот подход будет работать на любом базовом изображении, что позволяет устанавливать Anbible и Python.

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

Мы хотим: выберите предпочитаемую систему init: Tini, Dumb-init или init подход к Phance (Phusice-init)

container_init: "phusion-init" # "dumb-init" "tini-init" 
container_init_directory: /etc/my_init.d

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

container_svc: "runit" # "supervisord"

После концепции базового изображения Phance мы хотим дополнительных услуг CRON, SSHD и SYLLOG в контейнере.

option_container_cron: true
option_container_sshd: true
option_container_syslog_ng: true

Если мы когда-нибудь хотели SSH внутри контейнера, давайте предоставляем KeyPair доверять.

container_ssh_private_key: "{{role_dir}}/files/keys/insecure_key"
container_ssh_public_key: "{{role_dir}}/files/keys/insecure_key.pub"

Полученная игра компактна и читабена, как ваша обычная источника.

  - include: tasks_system_services.yml

  - include: tasks_cron.yml
    when: option_container_cron

  - include: tasks_sshd.yml
    when: option_container_sshd

  - include: tasks_syslog_ng.yml
    when: option_container_syslog_ng

Более того — мы не ограничиваемся одним подходом — мы можем бесплатно выбрать систему INITY и SERVICE из списка поддерживаемых. Вы всегда можете добавить новый.

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

а) Поместите бегунов услуг в/etc/service//run — это поддерживает как работать через оболочку, runit, s6. Руководитель может повторно выполнить тот же сценарий. b) Положите предварительную инициализацию изображений в/etc/myinit.d/*.sh c) Всегда имейте точку ввода имени как docker-entrypoint.sh d) ваша роль, благодаря ошибке, MIGTH DECTECT и TARGES Например, часто используются альпийские или Джесси.

Взгляните на пример роли, который может использоваться для создания такого базового изображения: https://github.com/softasap/sa-container-bootstrap

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

Система init init основана с руководителем в качестве менеджера услуг

version: "2"
settings:
  conductor_base: ubuntu:16.04
  volumes:
   - temp-space:/tmp   # Used to copy static content between containers

services:

   tini-supervisord:
     from: ubuntu:16.04
     container_name: api
     roles:
       - {
           role: "softasap.sa-container-bootstrap",
           container_init: "tini-init",
           container_svc: "supervisord"
         }
       - {
           role: "softasap.sa-nginx-container",
           container_init: "tini-init",
           container_svc: "supervisord"
         }
       - {
           role: "../custom-roles/app-nginx-stub-deploy",
           container_init: "tini-init",
           container_svc: "supervisord"
         }
     expose:
       - '8000'
       - '22'
     volumes:
        - temp-space:/tmp   # Used to copy static content between containers
     environment:
        IN_DOCKER: "1"         

volumes:
  temp-space:
    docker: {}

Система init init основана с руководителем в качестве менеджера услуг

version: "2"
settings:
  conductor_base: ubuntu:16.04
  volumes:
   - temp-space:/tmp   # Used to copy static content between containers

services:

   dumb-runit:
     from: ubuntu:16.04
     container_name: api
     roles:
       - {
           role: "softasap.sa-container-bootstrap",
           container_init: "dumb-init"
         }
       - {
           role: "softasap.sa-nginx-container",
           container_init: "dumb-init" # optionally uses runit for services management and upstart.
         }
       - {
           role: "../custom-roles/app-nginx-stub-deploy",
           container_init: "dumb-init"
         }
     expose:
       - '8000'
       - '22'
     volumes:
        - temp-space:/tmp   # Used to copy static content between containers
     environment:
        IN_DOCKER: "1"         

volumes:
  temp-space:
    docker: {}

Близко к базовому изображению Фюзии

version: "2"
settings:
  conductor_base: ubuntu:16.04
  volumes:
   - temp-space:/tmp   # Used to copy static content between containers

services:

   phusion-runit:
     from: ubuntu:16.04
     container_name: api
     roles:
       - {
           role: "softasap.sa-container-bootstrap"
         }
       - {
           role: "softasap.sa-nginx-container",
           container_init: "phusion-init" # uses runit for services management and upstart.
         }
       - {
           role: "../custom-roles/app-nginx-stub-deploy"
         }
     expose:
       - '8000'
       - '22'
     volumes:
        - temp-space:/tmp   # Used to copy static content between containers
     environment:
        IN_DOCKER: "1"         

volumes:
  temp-space:
    docker: {}

Еще примеры на https://github.com/voronenko/devops-docker-baseimage-demo

Немногие цифры на произведенные размеры

Base system:                               ubuntu 16.04
Init system:                               phusion_init
Base image with all services:              268 MB / 101 MB on docker.hub 
Base image with demo nginx app installed:  313 MB / 133 MB on docker hub

phusion/baseimage:                         225 MB / 84 MB on docker hub

Резюме

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

Оригинал: «https://www.codementor.io/@slavko/using-ansible-container-to-build-your-next-application-base-image-c4eq2ise1»