Маленечкія выявы Docker, якія верылі ў сябе*

[Дасылка да амерыканскай дзіцячай казкі "Маленькі паравозік, які верыў у сябе" ("The Little Engine That Could") - заўв. зав.]*

Маленечкія выявы Docker, якія верылі ў сябе*

Як аўтамагічна ствараць маленечкія docker-вобразы для сваіх патрэб

Незвычайная апантанасць

Апошнія пару месяцаў я быў апантаны дакучлівай ідэяй: наколькі можна паменшыць выяву Docker, так каб пры гэтым прыкладанне працавала?

Разумею, ідэя дзіўная.

Перш чым паглыбіцца ў дэталі і тэхнічныя нетры, я б хацеў растлумачыць, чым гэтая праблема так мяне ўчапіла, і як яна датычыцца вас.

Чаму памер мае значэнне

Скарачаючы змесціва выявы Docker, мы тым самым скарачаем спіс уразлівасцяў. Дадаткова мы робім выявы чысцей, бо яны ўтрымоўваюць толькі тое, што трэба для запуску прыкладанняў.

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

Звярніце ўвагу: Калі вас клапоціць памер, вобразы Alpine самі па сабе малыя і напэўна падыдуць вам.

Distroless-вобразы

Праект Distroless прапануе падборку базавых «distroless»-вобразаў, яны не ўтрымоўваюць мэнэджараў пакетаў, абалонак і іншых утыліт, якія вы абвыклі бачыць у камандным радку. У выніку выкарыстоўваць менеджэры пакетаў накшталт pip и apt не атрымаецца:

FROM gcr.io/distroless/python3
RUN  pip3 install numpy

Dockerfile, які выкарыстоўвае distroless-вобраз Python 3

Sending build context to Docker daemon  2.048kB
Step 1/2 : FROM gcr.io/distroless/python3
 ---> 556d570d5c53
Step 2/2 : RUN  pip3 install numpy
 ---> Running in dbfe5623f125
/bin/sh: 1: pip3: not found

Pip у выяве няма

Звычайна такая праблема вырашаецца шляхам шматэтапнай зборкі:

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/

Шматэтапная зборка

У выніку атрымліваецца выява памерам 130МВ. Не так ужо і дрэнна! Для параўнання: выява Python па змаўчанні важыць 929МВ, а схуднелы3,7-slim) - 179МВ, вобраз alpine (3,7-alpine) - 98,6MB, тады як базавы distroless-выява, выкарыстаны ў прыкладзе, - 50,9МВ.

Можна справядліва ўказаць на тое, што ў папярэднім прыкладзе мы капіюем цэлы каталог /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 важыць усяго 35МВ (я больш за ўпэўнены, што ў будучыні яго можна будзе палегчыць яшчэ больш). Выходзіць, з distroless-выявы атрымалася згаліць яшчэ 15МВ.

Усе сабраныя на дадзены момант выявы паглядзець можна тут.

Праект - тут.

Калі вам не хапае функцый, проста стварыце заяўку - буду рады дапамагчы 🙂 Нават больш, я ў дадзены момант працую над інтэграцыяй у fetchy іншых пакетных мэнэджараў, так каб патрэба ў шматэтапных зборках адпала.

Крыніца: habr.com

Дадаць каментар