Збіраць Docker-выявы ў werf зараз можна і па звычайным Dockerfile

Лепш позна чым ніколі. Ці як мы ледзь не дапусцілі сур'ёзную памылку, не маючы падтрымкі звычайных Dockerfiles для зборкі выяў прыкладання.

Збіраць Docker-выявы ў werf зараз можна і па звычайным Dockerfile

Гаворка пойдзе пра werf - GitOps-утыліту, якая інтэгруецца з любой CI/CD-сістэмай і забяспечвае кіраванне ўсім жыццёвым цыклам прыкладання, дазваляючы:

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


Філасофія праекта – сабраць нізкаўзроўневыя інструменты ў адзіную уніфікаваную сістэму, якая дае DevOps-інжынерам кантроль над праграмамі. Па магчымасці павінны быць задзейнічаны ўжо існуючыя ўтыліты (накшталт Helm і Docker). Калі ж рашэння нейкай задачы няма - мы можам стварыць і падтрымліваць усё неабходнае для гэтага.

Перадгісторыя: свой зборшчык вобразаў

Так і здарылася са зборшчыкам выяў у werf: звыклага Dockerfile нам бракавала. Калі бегла акунуцца ў гісторыю праекту, то гэтая праблема выявілася ўжо ў першых версіях werf (тады яшчэ вядомага як dapp).

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

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

На сённяшні дзень у нашым зборшчыку ёсць і многія іншыя магчымасці, але першапачатковыя жаданні і пазывы былі такія.

Увогуле, нядоўга думаючы, мы ўзброіліся выкарыстоўванай мовай праграмавання (гл. ніжэй) і адправіліся ў шлях - рэалізоўваць уласны DSL! Адпавядаючы пастаўленым задачам, ён быў прызначаны для апісання працэсу зборкі па стадыях і азначэнні залежнасцяў гэтых стадый ад файлаў. А дапаўняў яго уласны зборшчык, які ператвараў DSL у канчатковую мэту — сабраны вобраз. Спачатку DSL быў на Ruby, а па меры пераходу на Golang - канфіг нашага зборшчыка стаў апісвацца ў YAML-файле.

Збіраць Docker-выявы ў werf зараз можна і па звычайным Dockerfile
Стары канфіг для dapp на Ruby

Збіраць Docker-выявы ў werf зараз можна і па звычайным Dockerfile
Актуальны канфіг для werf на YAML

Механізм працы зборшчыка таксама мяняўся з часам. Спачатку мы проста генеравалі на лёце нейкі часовы Dockerfile з нашай канфігурацыі, а потым сталі запускаць зборачныя інструкцыі ў часавых кантэйнерах і рабіць commit.

NB: На дадзены момант наш зборшчык, які працуе са сваім канфігам (у YAML) і называецца Stapel-зборшчыкам, ужо развіўся ў дастаткова магутную прыладу. Яго разгорнутае апісанне заслугоўвае асобных артыкулаў, а асноўныя падрабязнасці можна даведацца з дакументацыі.

Усведамленне праблемы

Але мы зразумелі, прычым не адразу, што здзейснілі адну памылку: не дадалі магчымасць збіраць выявы праз стандартны Dockerfile і інтэграваць іх у тую ж інфраструктуру комплекснага кіравання дадаткам (г.зн. збіраць вобразы, дэплоіць і чысціць іх). Як можна было зрабіць прыладу для дэплою ў Kubernetes і не рэалізаваць падтрымку Dockerfile, г.зн. стандартнага спосабу апісання выяў для большасці праектаў?..

Замест адказу на такое пытанне мы прапануем яго вырашэнне. Што рабіць, калі ў вас ужо маецца Dockerfile (ці набор Dockerfile'ов) і вы жадаеце выкарыстоўваць werf?

NB: Дарэчы, з чаго б вам увогуле захацець выкарыстоўваць werf? Асноўныя фічы зводзяцца да наступных:

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

З больш поўным іх спісам можна азнаёміцца ​​на старонцы праекта.

Такім чынам, калі раней мы б прапанавалі перапісаць Dockerfile на наш канфіг, то зараз з радасцю скажам: "Дазвольце werf сабраць вашыя Dockerfile'ы!"

Як выкарыстоўваць?

Поўная рэалізацыя гэтай магчымасці з'явілася ў рэлізе werf v1.0.3-beta.1. Агульны прынцып просты: карыстач паказвае шлях да існага Dockerfile у канфігу werf, пасля чаго запускае каманду werf build… і ўсё – werf збярэ выяву. Разгледзім на абстрактным прыкладзе.

Аб'явім наступны Dockerfile у корані праекта:

FROM ubuntu:18.04
RUN echo Building ...

І аб'явім werf.yaml, які выкарыстоўвае гэты Dockerfile:

configVersion: 1
project: dockerfile-example
---
image: ~
dockerfile: ./Dockerfile

Усё! Засталося запусціць werf build:

Збіраць Docker-выявы ў werf зараз можна і па звычайным Dockerfile

Акрамя таго, можна аб'явіць наступны werf.yaml для зборкі адразу некалькіх выяў з розных Dockerfile'ов:

configVersion: 1
project: dockerfile-example
---
image: backend
dockerfile: ./dockerfiles/Dockerfile-backend
---
image: frontend
dockerfile: ./dockerfiles/Dockerfile-frontend

Нарэшце, падтрымліваецца і перадача дадатковых параметраў зборкі - такіх як --build-arg и --add-host - Праз канфіг werf. Поўнае апісанне канфігурацыі Dockerfile image даступна на старонцы дакументацыі.

Як гэта працуе?

Падчас зборкі функцыянуе стандартны кэш лакальных пластоў у Docker. Аднак, што важна, werf таксама інтэгруе канфігурацыю Dockerfile у сваю інфраструктуру. Што гэта азначае?

  1. Кожная выява, сабраны з Dockerfile, складаецца з аднаго stage пад назовам dockerfile (падрабязней пра тое, што такое stages у werf, можна пачытаць тут).
  2. Для stage'а dockerfile werf разлічвае сігнатуру, якая залежыць ад змесціва канфігурацыі Dockerfile. Пры змене канфігурацыі Dockerfile адбываецца змена сігнатуры стадыі dockerfile і werf ініцыюе перазборку гэтай стадыі з новым канфігам Dockerfile. Калі ж сігнатура не змяняецца, то werf бярэ выяву з кэша. (падрабязней аб выкарыстанні сігнатур у werf распавядалася ў гэтым дакладзе).
  3. Далей сабраныя выявы можна апублікаваць камандай werf publish (Або werf build-and-publish) і выкарыстоўваць для дэплою ў Kubernetes. Апублікаваныя выявы ў Docker Registry будуць чысціцца стандартнымі сродкамі ачысткі werf, г.зн. адбудзецца аўтаматычная ачыстка старых вобразаў (старэй за N дзён), вобразаў, звязаных з неіснуючымі Git-галінкамі, і па іншых палітыках.

Падрабязней пра апісаныя тут моманты можна даведацца з дакументацыі:

Нататкі і засцярогі

1. Вонкавы URL у ADD не падтрымліваецца

На дадзены момант не падтрымліваецца выкарыстанне вонкавага URL у дырэктыве ADD. Werf не будзе ініцыяваць перазборку пры змене рэсурсу па паказаным URL. У хуткім часе плануецца даданне гэтай магчымасці.

2. Нельга дадаваць .git у выяву

Наогул кажучы, даданне дырэкторыі .git у вобраз - заганная дрэнная практыка і вось чаму:

  1. Калі .git застаецца ў фінальнай выяве, гэта парушае прынцыпы 12 factor app: паколькі выніковая выява павінна быць звязана з адным коммітам, не павінна быць магчымасці зрабіць git checkout адвольнага комміта.
  2. .git павялічвае памер выявы (рэпазітар можа быць вялікім з-за таго, што ў яго калісьці дадалі вялікія файлы, а потым выдалілі). Памер жа work-tree, злучанага толькі з вызначаным коммітам, не будзе залежаць ад гісторыі аперацый у Git. Пры гэтым даданне і наступнае выдаленне .git з фінальнай выявы не спрацуе: выява ўсё роўна набудзе лішні пласт — так працуе Docker.
  3. Docker можа ініцыяваць лішнюю перазборку, нават калі ідзе зборка аднаго і таго ж коміта, але з розных work-tree. Напрыклад, GitLab стварае асобныя скланаваныя дырэкторыі ў /home/gitlab-runner/builds/HASH/[0-N]/yourproject пры ўключанай паралельнай зборцы. Лішняя перазборка будзе звязана з тым, што дырэкторыя .git адрозніваецца ў розных скланаваных версіях аднаго і таго ж рэпазітара, нават калі збіраецца адзін і той жа коміт.

Апошні пункт мае наступства і пры выкарыстанні werf. Werf патрабуе, каб сабраны кэш прысутнічаў пры запуску некаторых каманд (напрыклад, werf deploy). Падчас працы такіх каманд werf разлічвае сігнатуры стадый для выяў, паказаных у werf.yaml, і яны павінны быць у зборачным кэшы - інакш каманда не зможа працягнуць працу. Калі ж сігнатура стадый будзе залежаць ад змесціва .git, то мы атрымліваем няўстойлівы да змен у нерэлевантных файлах кэш, і werf не зможа прабачыць такі промах (падрабязней гл. у дакументацыі).

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

Вынік

Наш першапачатковы шлях з напісаннем свайго зборшчыка для вызначаных запатрабаванняў быў цяжкім, сумленным і прамалінейным: замест выкарыстання мыліц па-над стандартным Dockerfile мы напісалі сваё рашэнне з кастамным сінтаксісам. І гэта дало свае плюсы: Stapel-зборшчык выдатна спраўляецца са сваёй задачай.

Аднак падчас напісання ўласнага зборшчыка мы выпусцілі з-пад увагі падтрымку ўжо існых Dockerfile'ов. Цяпер гэты недахоп выпраўлены, а ў далейшым мы плануем развіваць падтрымку Dockerfile нараўне з нашым кастамным зборшчыкам Stapel для размеркаванай зборкі і для зборкі з выкарыстаннем Kubernetes (г.зн. зборкі на runner'ах усярэдзіне Kubernetes, як гэта зроблена ў kaniko).

Так што, калі ў вас раптам закачалася пара Dockerfile'ов… паспрабуйце werf!

PS Спіс дакументацыі па тэме

Чытайце таксама ў нашым блогу: «werf – наш інструмент для CI/CD у Kubernetes (агляд і відэа даклада).

Крыніца: habr.com

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