Docker: nid cyngor gwael

Yn y sylwadau i'm herthygl Dociwr: cyngor gwael Bu llawer o geisiadau i esbonio pam roedd y Dockerfile a ddisgrifiwyd ynddo mor ofnadwy.

Crynodeb o'r bennod flaenorolMae dau ddatblygwr yn gweithio ar Dockerfile o dan derfyn amser tynn. Daw'r Rheolwr Gweithrediadau Igor Ivanovich i mewn i'w gweld. Mae'r Dockerfile sy'n deillio o hyn mor ddrwg fel bod y deallusrwydd artiffisial ar fin cael trawiad ar y galon.

Docker: nid cyngor gwael

Nawr gadewch i ni ddarganfod beth sy'n bod ar y Dockerfile hwn.

Felly, mae wythnos wedi mynd heibio.

Mae Dev Petya yn cwrdd ag Ops Igor Ivanovich yn y ffreutur am baned o goffi.

P: Igor Ivanovich, wyt ti'n brysur iawn? Hoffwn i ddarganfod ble wnaethon ni gamgymeriad.

AI: Mae hynny'n dda, dydych chi ddim yn aml yn cwrdd â datblygwyr sydd â diddordeb mewn ecsbloetio.
Yn gyntaf, gadewch i ni gytuno ar ychydig o bethau:

  1. Ideoleg dociwr: un cynhwysydd - un broses.
  2. Po leiaf yw'r cynhwysydd, y gorau.
  3. Po fwyaf a gymerir o'r storfa, y gorau.

P: Pam y dylai fod un broses mewn un cynhwysydd?

AI: Pan fydd Docker yn cychwyn cynhwysydd, mae'n monitro cyflwr y broses gyda pid 1. Os bydd y broses yn marw, mae Docker yn ceisio ailgychwyn y cynhwysydd. Dyweder bod gennych chi nifer o gymwysiadau yn rhedeg yn y cynhwysydd, neu nad yw'r prif gymhwysiad yn rhedeg gyda pid 1. Os bydd y broses yn marw, ni fydd Docker yn gwybod.

Os nad oes gennych unrhyw gwestiynau pellach, dangoswch eich Dockerfile i mi.

A dangosodd Petya:

FROM ubuntu:latest

# Копируем исходный код
COPY ./ /app
WORKDIR /app

# Обновляем список пакетов
RUN apt-get update 

# Обновляем пакеты
RUN apt-get upgrade

# Устанавливаем нужные пакеты
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor

# Устанавливаем bundler
RUN gem install bundler

# Устанавливаем nodejs используется для сборки статики
RUN curl -sL https://deb.nodesource.com/setup_9.x | sudo bash -
RUN apt-get install -y nodejs

# Устанавливаем зависимости
RUN bundle install --without development test --path vendor/bundle

# Чистим за собой кэши
RUN rm -rf /usr/local/bundle/cache/*.gem 
RUN apt-get clean 
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 
RUN rake assets:precompile
# Запускаем скрипт, при старте контейнера, который запустит все остальное.
CMD ["/app/init.sh"]

AI: O, gadewch i ni gymryd hwn un ar y tro. Gadewch i ni ddechrau gyda'r llinell gyntaf:

FROM ubuntu:latest

Rydych chi'n cymryd y tag latestGan ddefnyddio'r tag latest Mae hyn yn arwain at ganlyniadau anrhagweladwy. Dychmygwch fod cynhaliwr y ddelwedd yn adeiladu fersiwn newydd o'r ddelwedd gyda rhestr wahanol o feddalwedd, a bod y ddelwedd hon wedi'i thagio "diweddaraf". Ar y gorau, mae eich cynhwysydd yn rhoi'r gorau i adeiladu, ac ar y gwaethaf, rydych chi'n dod ar draws bygiau nad oeddent yno o'r blaen.

Rydych chi'n tynnu delwedd o system weithredu lawn gyda llawer o feddalwedd ddiangen, sy'n chwyddo maint y cynhwysydd. A pho fwyaf o feddalwedd, y mwyaf o fylchau a gwendidau.

Yn ogystal, po fwyaf yw'r ddelwedd, y mwyaf o le y mae'n ei gymryd ar y gwesteiwr ac yn y gofrestrfa (rydych chi'n storio'r delweddau yn rhywle, iawn?)

P: Ydw, wrth gwrs, mae gennym ni gofrestrfa, chi sy'n ei sefydlu.

AI: Felly, beth oeddwn i'n sôn amdano? O ie, cyfrolau... Mae llwyth y rhwydwaith hefyd yn cynyddu. Ar gyfer un ddelwedd, mae'n anweledig, ond pan fyddwch chi'n adeiladu, profi a defnyddio'n gyson, mae'n amlwg. Ac os nad oes gennych chi fodd Duw ar AWS, byddwch chi hefyd yn cael bil uchel iawn.

Felly, mae angen i chi ddewis y ddelwedd fwyaf addas, gyda'r fersiwn union a'r feddalwedd leiaf posibl. Er enghraifft, cymerwch: FROM ruby:2.5.5-stretch

P: O, dw i'n gweld. A sut a ble alla i weld y delweddau sydd ar gael? Sut dw i'n gwybod pa un sydd ei angen arna i?

AI: Fel arfer mae'r delweddau'n cael eu cymryd o DockerHub, peidiwch â'i ddrysu â Pornhub :). Fel arfer mae sawl adeiladwaith ar gyfer pob delwedd:
AlpineMae'r delweddau wedi'u hadeiladu ar ddelwedd Linux finimalaidd, dim ond 5 MB o faint. Ei anfantais: mae wedi'i adeiladu gyda gweithrediad libc personol, felly nid yw pecynnau safonol yn gweithio gydag ef. Gall dod o hyd i'r pecyn gofynnol a'i osod gymryd cryn dipyn o amser.
CrafuDelwedd sylfaenol nad yw'n cael ei defnyddio i adeiladu delweddau eraill. Fe'i bwriedir yn unig ar gyfer rhedeg data deuaidd parod. Mae'n ddelfrydol ar gyfer rhedeg cymwysiadau deuaidd sy'n cynnwys yr holl gydrannau angenrheidiol, fel cymwysiadau Go.
Yn seiliedig ar ryw system weithredu, fel Ubuntu neu Debian. Wel, dw i'n meddwl nad oes angen esbonio hynny.

AI: Nawr mae angen i ni osod yr holl becynnau ychwanegol a chlirio'r storfeydd. Ac yna gallwn ei daflu i ffwrdd ar unwaith. apt-get upgradeFel arall, bydd pob adeiladwaith yn cynhyrchu delweddau gwahanol, er gwaethaf tag sefydlog y ddelwedd sylfaenol. Cyfrifoldeb y cynhaliwr yw diweddaru pecynnau mewn delwedd, ac mae'n gofyn am newid y tag.

P: Ie, ceisiais wneud hynny, ac fe drodd allan fel hyn:

WORKDIR /app
COPY ./ /app

RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - 
    && apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor nodejs 
    && gem install bundler 
    && bundle install --without development test --path vendor/bundle

RUN rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

AI: Ddim yn ddrwg, ond mae lle i wella o hyd yma. Edrychwch, y gorchymyn hwn:

RUN rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*  

…ddim yn tynnu data o'r ddelwedd derfynol, ond yn syml yn creu haen ychwanegol heb y data hwnnw. Y ffordd gywir yw:

RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - 
    && apt-get -y install libpq-dev imagemagick gsfonts nodejs 
    && gem install bundler 
    && bundle install --without development test --path vendor/bundle   
    && rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

Ond nid dyna'r cyfan. Beth sydd gennych chi yno, Ruby? Yna does dim angen i chi gopïo'r prosiect cyfan ar y dechrau. Copïwch y Gemfile a Gemfile.lock yn unig.

Gyda'r dull hwn, ni fydd gosod bwndel yn cael ei berfformio ar gyfer pob newid yn y cod ffynhonnell, ond dim ond os yw'r Gemfile neu Gemfile.lock wedi newid.

Mae'r un dulliau'n gweithio ar gyfer ieithoedd eraill gyda rheolwr dibyniaethau, fel npm, pip, cyfansoddwr, ac ieithoedd eraill sy'n seiliedig ar ffeiliau dibyniaeth.

Ac yn olaf, cofiwch sut y soniais am athroniaeth "un cynhwysydd, un broses" Docker ar y dechrau? Mae hynny'n golygu nad oes angen goruchwyliwr. Ni ddylech chi osod systemd chwaith, am yr un rhesymau. Yn ei hanfod, mae Docker ei hun yn oruchwyliwr. A phan geisiwch redeg prosesau lluosog ynddo, mae fel ceisio rhedeg cymwysiadau lluosog mewn un broses oruchwyliwr.
Wrth adeiladu, rydych chi'n creu un ddelwedd ac yna'n lansio'r nifer gofynnol o gynwysyddion, pob un yn rhedeg un broses.

Ond mwy am hynny yn ddiweddarach.

P: Dw i'n meddwl mod i'n ei ddeall. Edrychwch beth sy'n digwydd:

FROM ruby:2.5.5-stretch

WORKDIR /app
COPY Gemfile* /app

RUN curl -sL https://deb.nodesource.com/setup_9.x | bash - 
    && apt-get -y install libpq-dev imagemagick gsfonts nodejs 
    && gem install bundler 
    && bundle install --without development test --path vendor/bundle   
    && rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

COPY . /app
RUN rake assets:precompile

CMD ["bundle”, “exec”, “passenger”, “start"]

A allwn ni ddiystyru lansio daemonau wrth gychwyn cynhwysydd?

AI: Ie, dyna'n iawn. Gyda llaw, gallwch ddefnyddio naill ai CMD neu ENTRYPOINT. Dy waith cartref yw darganfod y gwahaniaeth. Mae yna edau dda ar y pwnc hwn ar Habr. erthygl.

Iawn, gadewch i ni symud ymlaen. Rydych chi'n lawrlwytho ffeil i osod nod, ond does dim sicrwydd y bydd yn cynnwys yr hyn sydd ei angen arnoch chi. Mae angen i chi ychwanegu rhywfaint o ddilysu. Er enghraifft, fel hyn:

RUN curl -sL https://deb.nodesource.com/setup_9.x > setup_9.x 
    && echo "958c9a95c4974c918dca773edf6d18b1d1a41434  setup_9.x" | sha1sum -c - 
    &&  bash  setup_9.x 
    && rm -rf setup_9.x 
    && apt-get -y install libpq-dev imagemagick gsfonts nodejs 
    && gem install bundler 
    && bundle install --without development test --path vendor/bundle   
    && rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

Gan ddefnyddio'r swm gwirio, gallwch wirio eich bod wedi lawrlwytho'r ffeil gywir.

P: Ond os bydd y ffeil yn newid, bydd yr adeiladwaith yn methu.

AI: Ie, ac yn rhyfedd ddigon, mae hynny hefyd yn fantais. Byddwch chi'n gwybod pryd mae ffeil wedi newid, a gallwch chi weld beth sydd wedi newid. Dydych chi byth yn gwybod, efallai eu bod nhw wedi ychwanegu sgript sy'n dileu popeth y gall ei gyrraedd, neu'n creu drws cefn.

P: Diolch. Felly, bydd y Dockerfile terfynol yn edrych fel hyn:

FROM ruby:2.5.5-stretch

WORKDIR /app
COPY Gemfile* /app

RUN curl -sL https://deb.nodesource.com/setup_9.x > setup_9.x 
    && echo "958c9a95c4974c918dca773edf6d18b1d1a41434  setup_9.x" | sha1sum -c - 
    &&  bash  setup_9.x 
    && rm -rf setup_9.x 
    && apt-get -y install libpq-dev imagemagick gsfonts nodejs 
    && gem install bundler 
    && bundle install --without development test --path vendor/bundle   
    && rm -rf /usr/local/bundle/cache/*.gem 
    && apt-get clean  
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 

COPY . /app
RUN rake assets:precompile

CMD ["bundle”, “exec”, “passenger”, “start"]

P: Igor Ivanovich, diolch am eich help. Mae'n rhaid i mi redeg nawr; mae gen i 10 ymrwymiad arall i'w gwneud heddiw.

Gan atal ei gydweithiwr brysiog gyda chipolwg, mae Igor Ivanovich yn cymryd sip o goffi cryf. Ar ôl myfyrio am ychydig eiliadau ynglŷn â SLA 99.9% a chod di-fygiau, mae'n gofyn cwestiwn.

AI: Ble ydych chi'n storio eich logiau?

P: Wrth gwrs, yn production.log. Gyda llaw, sut fyddwn ni'n eu cyrchu heb SSH?

AI: Os byddwch chi'n eu gadael mewn ffeiliau, mae ateb eisoes wedi'i greu i chi. Mae'r gorchymyn docker exec yn caniatáu ichi weithredu unrhyw orchymyn mewn cynhwysydd. Er enghraifft, gallwch chi gofnodi'r logiau. A defnyddio'r allwedd -hi a bydd rhedeg bash (os yw wedi'i osod yn y cynhwysydd) yn rhoi mynediad rhyngweithiol i chi i'r cynhwysydd.

Ond nid yw storio logiau mewn ffeiliau yn syniad da. O leiaf, mae hyn yn arwain at dwf cynhwysydd heb ei reoli, ac nid oes neb yn cylchdroi logiau. Dylid dympio pob log i stdout. O'r fan honno, gellir eu gweld gan ddefnyddio'r gorchymyn logiau dociwr.

P: Igor Ivanovich, efallai y gallech chi symud y logiau i gyfeiriadur wedi'i osod ar nod ffisegol, fel data defnyddwyr?

AI: Mae'n dda eich bod wedi cofio allforio'r data a lawrlwythwyd i ddisg y nod. Gallwch wneud yr un peth gyda logiau, ond peidiwch ag anghofio sefydlu cylchdro.
Iawn, gallwch chi redeg.

P: Igor Ivanovich, a allech chi argymell rhywbeth i'w ddarllen?

AI: Darllenwch yn gyntaf Argymhellion gan ddatblygwyr Docker, mae'n annhebygol bod unrhyw un yn adnabod Docker yn well na nhw.

Ac os ydych chi eisiau gwneud interniaeth, ewch i dwysWedi'r cyfan, mae damcaniaeth heb ymarfer yn farw.

Ffynhonnell: hab.com

Ychwanegu sylw