[връзка към американската детска приказка „Малкият локомотив, който можеше“ („The Little Engine That Could“) — бел. ред.]*

Как автоматично да създадем малки docker образи за собствените си нужди
Ненормална обсесия
През последните месеци бях обсебен от една идея: колко малък може да бъде Docker образът, така че приложението да работи?
Разбирам, че идеята е странна.
Преди да навляза в подробностите и техническите дълбини, бих искал да обясня какво точно ме заинтригува и как това засяга вас.
Защо размерът има значение
Намалявайки съдържанието на Docker образа, по този начин намаляваме списъка с уязвимости. Освен това, правим образите по-чисти, тъй като те съдържат само това, което е необходимо за стартиране на приложения.
Има още едно малко предимство — образите се свалят малко по-бързо, но за мен това не е толкова важно.
Обърнете внимание: Ако размерът ви интересува, образите Alpine са сами по себе си малки и вероятно ще ви подхождат.
Distroless образи
предлага колекция от основни „distroless“ образи, които не съдържат мениджъри на пакети, шел или други инструменти, с които сте свикнали в командния ред. В резултат на това не можете да използвате мениджъри на пакети като pip и apt не е възможно:
FROM gcr.io/distroless/python3
RUN pip3 install numpyDockerfile, използващ distroless образ Python 3
Изпращане на контекста на изграждане до Docker демон 2.048kB
Стъпка 1/2 : FROM gcr.io/distroless/python3
---> 556d570d5c53
Стъпка 2/2 : RUN pip3 install numpy
---> Изпълнява се в dbfe5623f125
/bin/sh: 1: pip3: not foundPip не се среща в образа
Обикновено този проблем се решава чрез многостепенно изграждане:
FROM python:3 as builder
RUN pip3 install numpy
FROM gcr.io/distroless/python3
COPY --from=builder /usr/local/lib/python3.7/site-packages /usr/local/lib/python3.5/Многостепенно изграждане
В резултат на това получавате образ с размер 130MB. Не е толкова зле! За сравнение: стандартният образ на Python тежи 929MB, а „отслабналият“ (3.7-slim) — 179MB, образ alpine (3.7-alpine) — 98.6MB, докато основният distroless образ, използван в примера, е 50.9MB.
Може да се направи справедливо наблюдение, че в предишния пример копираме цяла директория /usr/local/lib/python3.7/site-packages, в която могат да се намират ненужни зависимости. Въпреки че е ясно, че разликата в размерите на всички съществуващи основни образи на Python варира.
Към момента на написване на тези редове Google distroless поддържа не толкова много образи: Java и Python — все още в експериментална фаза, а Python съществува само за 2.7 и 3.5.
Малки образи
Нека се върнем към моята мания за създаване на малки образи.
Всъщност исках да видя как са направени distroless образите. Проектът distroless използва инструмент за изграждане от Google bazel. Но за да инсталирам Bazel и да напиша собствени образи, трябваше да потрудя (а за да бъда напълно честен, налагаше се да изобретявам колелото отново — това е забавно и поучително). Исках да опростя създаването на намалени образи: актът на създаване на образ трябва да бъде съвсем прост, банален. За да няма никакви конфигурационни файлове, само една команда в конзолата: просто създайте образ за <приложение>.
И така, ако искате да създавате собствени образи, имайте предвид: съществува такъв уникален образ на docker, scratch. Scratch е "празен" образ, в него няма файлове, въпреки че по подразбиране тежи — ого! — 77 байта.
FROM scratchОбразът scratch
Идеята на образа scratch е, че можете да копирате всякакви зависимости от машината хост и или да ги използвате в Dockerfile (това е като да ги копирате в apt и да ги инсталирате от нулата), или по-късно, когато образът Docker се материализира. Това позволява напълно контролиране на съдържанието на контейнера Docker и, следователно, напълно контролиране на размера на образа.
Сега трябва да намерим начин да съберем тези зависимости. Съществуващи инструменти като apt позволяват сваляне на пакети, но те са свързани с текущата машина и, в крайна сметка, не поддържат Windows или MacOS.
И така, аз се заех да създам собствен инструмент, който автоматично би събирал базов образ с най-малък възможен размер и същевременно стартиране на всяко приложение. Използвах пакети от Ubuntu/Debian, извършвах селекция (получавайки пакети направо от хранилищата) и рекурсивно намирах зависимостите им. Програмата трябваше автоматично да сваля най-новата стабилна версия на пакета, минимизирайки рисковете за сигурността.
Инструментът го нарекох fetchy, защото той… намира и носи… каквото е нужно [от англ. «fetch», «приносить» — прим. прев.]. Инструментът работи чрез интерфейс на командния ред, но в същото време предлага и API.
За да създадете образ с помощта на fetchy (тази седмица вземаме образ Python), трябва просто да използвате CLI така: fetchy dockerize python. Може да ви бъде поискан целевият операционен система и кодовото име, тъй като fetchy все още използва само пакети с основа Debian и Ubuntu.
Сега можете да изберете кои зависимости не са необходими (в нашия контекст) и да ги изключите. Например, Python зависи от perl, въпреки че работи отлично без инсталиран Perl.
Резултати
Образът на Python, създаден с команда fetchy dockerize python3.5 тегли само 35MB (сигурен съм, че в бъдеще може да бъде направен дори по-лек). Оказва се, че с distroless образа успяхме да „отсечем“ още 15MB.
Всички събрани до момента образи можете да видите .
Проектът — .
Ако ви липсват функции, просто направете заявка — ще се радвам да помогна 🙂 Още повече, в момента работя върху интеграция на други пакетни мениджъри в fetchy, така че да отпадне необходимостта от многоетапни сборки.
Източник: habr.com
