Në komente për artikullin tim kishte shumë kërkesa për të shpjeguar se çfarë është aq e keqe në Dockerfile-in e përshkruar.
Përmbledhje e serisë paraprake: dy zhvillues në një afat të ngushtë po përgatisin Dockerfile-in. Në atë proces, tek ata hyn Ops Ijor Ivanoviç. Dockerfile-i përfundimtar është kaq i keq sa që II përfundon në prag të infarktit.

Tani do të shohim se çfarë nuk shkon me këtë Dockerfile.
Pra, ka kaluar një javë.
Dev Petja takon në kafene Ops Ijor Ivanoviçin për një filxhan kafe.
P: Ijor Ivanoviç, jeni shumë i zënë? Do të doja të zgjidhnim se ku e kemi bërë gabim.
II: Kjo është mirë, nuk takon shpesh zhvillues që interesohen për operimin.
Fillimisht le të biem dakord për disa gjëra:
- Ideologjia e Docker: një konteiner - një proces.
- Sa më i vogël të jetë konteineri, aq më mirë.
- Sa më shumë të merret nga keƥa, aq më mirë.
P: Pse në një konteiner duhet të jetë një proces?
II: Docker gjatë nisjes së konteinerit ndjek gjendjen e procesit me pid 1. Nëse procesi vdes, Docker përpiqet të rilokojë konteinerin. Le të themi, që keni disa aplikacione të nisura në konteiner ose aplikacioni kryesor nuk është i nisur me pid 1. Nëse procesi vdes, Docker nuk do ta dijë këtë.
Nëse nuk ka më pyetje, tregoni Dockerfile-in tuaj.
Dhe Petja e tregoi:
FROM ubuntu:latest
# Kopjojmë kodin burimor
COPY .\/ \/app
WORKDIR \/app
# Përshtasim listën e paketave
RUN apt-get update
# Përshtasim paketat
RUN apt-get upgrade
# Instalojmë paketat e nevojshme
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor
# Instalojmë bundler
RUN gem install bundler
# Instalojmë nodejs që përdoret për ndërtimin e statikëve
RUN curl -sL https:\/\/deb.nodesource.com\/setup_9.x | sudo bash -
RUN apt-get install -y nodejs
# Instalojmë varësitë
RUN bundle install --without development test --path vendor\/bundle
# Pastroni pas vetes caches
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
# Nisjmë skriptin, kur konteneri fillon, i cili do të nisë gjithçka tjetër.
CMD ["\/app\/init.sh"]II: Oh, le të merremi me radhë. Le të fillojmë me rreshtin e parë:
FROM ubuntu:latestMerrni etiketën latest. Përdorimi i etiketës latest ndihmon në pasojat e paparashikueshme. Imagjinoni, mbajtësi i figurës ndërton një version të ri të figurës me një listë tjetër software, ky figurë merr etiketën latest. Dhe konteineri juaj në rastin më të mirë ndalon së ndërtuari, dhe në rastin më të keq merrni defekte që nuk kanë qenë më parë.
Po merrni një imazh me një sistem operativ të plotë me shumë software të panevojshëm, gjë që zgjeron volumet e kontejnerit. Sa më shumë software, aq më shumë hapësira dhe dobësi.
Përveç kësaj, sa më i madh të jetë imazhi, aq më shumë hapësirë zë në host dhe në registry (ku e ruan imazhet)?
P: Po, sigurisht, kemi registry, ju e keni konfiguruar atë.
IA: Pra, pĂ«r çfarĂ« po flasĂ«?.. Ah po, volumet⊠Po ashtu rritet ngarkesa nĂ« rrjet. PĂ«r njĂ« imazh tĂ« vetĂ«m kjo Ă«shtĂ« e padukshme, por kur ka ndĂ«rtim tĂ« vazhdueshĂ«m, teste dhe deploy, kjo ndihet. Dhe nĂ«se nuk ke Godâs mode nĂ« AWS, do tĂ« marrĂ«sh edhe njĂ« faturĂ« astronomike.
Prandaj, duhet të zgjidhni imazhin më të përshtatshëm, me versionin e saktë dhe minimumin e software-it. Për shembull, merrni: FROM ruby:2.5.5-stretch
P: Oh, kuptoj. Si dhe ku të shoh imazhet e disponueshme? Si ta kuptoj qëllimin e nevojshëm?
IA: Zakonisht imazhet merret nga , mos e ngatërroni me pornhub :). Për imazhet zakonisht ekzistojnë disa ndërtimi:
Alpine: imazhet janë ndërtuar mbi një imazh minimaliste të Linux, gjë që është vetëm 5 Mb. Mungesa e tij: është ndërtuar me një implementim të tij të libc, paketat standarde nuk funksionojnë. Do të duhet shumë kohë për të kërkuar dhe instaluar paketën e nevojshme.
Scratch: njĂ« imazh bazĂ«, nuk pĂ«rdoret pĂ«r ndĂ«rtimin e imazheve tĂ« tjera. Ai Ă«shtĂ« ndĂ«rtuar ekskluzivisht pĂ«r ekzekutimin e tĂ« dhĂ«nave tĂ« pĂ«rgatitura. ĂshtĂ« ideale pĂ«r tĂ« drejtuar aplikacione binare qĂ« pĂ«rfshijnĂ« gjithçka tĂ« nevojshme, pĂ«r shembull aplikacione go.
Për bazën e ndonjë sistemi operativ, si Ubuntu ose Debian. Këtu, mendoj se nuk ka nevojë për shpjegim.
IA: Tani duhet të instalojmë të gjitha paketat shtesë dhe të pastrojmë cache-t. Dhe menjëherë mund të heqim apt-get upgrade. Nëse jo, me çdo ndërtim, pavarësisht nga teli i fiksuar i imazhit bazë, do të kemi imazhe të ndryshme. Azhurnimi i paketave në imazh është detyra e mbajtësit, dhe ajo shoqërohet me ndryshimin e telave.
P: Po, e kam provuar këtë të bëj, rezultati im ishte kështu:
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/*IA: Jo keq, por ka edhe nga ato që mund të përmirësojmë. Shiko, kjo komandë:
RUN rm -rf /usr/local/bundle/cache/*.gem
&& apt-get clean
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* ⊠nuk nukton të dhënat nga imazhi përfundimtar, por thjesht krijon një nivel shtesë pa këto të dhëna. E drejta është kështu:
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/* Por kjo nuk Ă«shtĂ« e gjitha. ĂfarĂ« ke aty, Ruby? AtĂ«herĂ« nuk ka nevojĂ« tĂ« kopjosh tĂ« gjithĂ« projektin nga fillimi. Mjafton tĂ« kopjosh Gemfile dhe Gemfile.lock.
Me këtë qasje, bundle install nuk do të ekzekutohet për çdo ndryshim në burime, por vetëm nëse është ndryshuar Gemfile ose Gemfile.lock.
Të njëjtat metoda funksionojnë edhe për gjuhë të tjera me menaxher të varësive, si npm, pip, composer dhe të tjera që bazohen në një skedë me listë varësish.
Dhe pĂ«r fund, e kujton, nĂ« fillim tĂ« flisja pĂ«r ideologjinĂ« e Docker «njĂ« kontejner â njĂ« proces»? Kjo do tĂ« thotĂ« qĂ« supervisor nuk Ă«shtĂ« i nevojshĂ«m. Po ashtu, nuk duhet tĂ« instalosh systemd, pĂ«r tĂ« njĂ«jtat arsye. NĂ« thelb, Docker vetĂ« Ă«shtĂ« supervisor. Dhe kur pĂ«rpiqesh tĂ« ekzekutosh disa procese brenda tij, Ă«shtĂ« si tĂ« ekzektosh disa aplikacione brenda njĂ« procesi supervisor.
Gjatë ndërtimit, do të bësh një imazh të vetëm, dhe pastaj do të nisësh numrin e nevojshëm të kontejnerëve, në mënyrë që në çdo njëri të funksiononte një proces.
Por për këtë më vonë.
P: Duket se e kuptova. Shikoni, çfarë ndodh:
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 do ta kalojmĂ« nisjen e demonĂ«ve gjatĂ« nisjes sĂ« kontejnerit?
AI: Po, krejtësisht. Për më tepër, mund të përdorësh si CMD ashtu edhe ENTRYPOINT. Ndërsa të kuptosh ndryshimin, kjo është detyra jote shtëpiake. Ka një artikull të mirë për këtë në Habr. .
Pra, le të vazhdojmë. Shkarko një skedë për instalimin e node, por nuk ka asnjë garantim se do të ketë atë që të nevojitet. Duhet të shtosh validimin. Për shembull, kështu:
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/* Me kontrollën e shumës së kontrollit, do të jesh në gjendje të verifikosh nëse ke shkarkuar skedarin e saktë.
P: Por nëse skedari ndryshon, atëherë ndërtimi nuk do të kalojë.
AI: Po, dhe siç duket, ky është një avantazh. Do ta kuptosh që skedari ka ndryshuar dhe do të mund të shohësh se çfarë është ndërruar. Ndoshta, kanë shtuar një skript që fshin gjithçka që arrin, ose krijon një backdoor.
P: Faleminderit. Kështu, Dockerfile përfundimtar do të duket kështu:
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, faleminderit për ndihmën. Më duhet të ik, duhet të bëj edhe 10 komitë sot.
Igor Ivanovich, duke ndaluar shikimin e kolegut të nxituar, bën një gllënjkë kafeje të fortë. Pas disa sekondash mendime për SLA 99.9% dhe kod pa defekte, ai bën një pyetje.
AI: Ku i ruani log-et?
P: Sigurisht, në production.log. Po, si do ta kemi qasje në to pa ssh?
AI: Nëse i lini në skedarë, zgjidhja për ju është menduar. Komanda docker exec lejon të ekzekutoni çdo komandë brenda kontejnerit. Për shembull, mund të bëni cat për log-et. Dhe duke përdorur çelësin -it dhe duke nisur bash (nëse është instaluar në kontejner), do të keni qasje interaktive në kontejner.
Por nuk duhet tĂ« ruani log-et nĂ« skedarĂ«. TĂ« paktĂ«n kjo çon nĂ« rritjen e pakontrolluar tĂ« madhĂ«sisĂ« sĂ« kontejnerit, pĂ«r shkak se askush nuk i rrotullon log-et. TĂ« gjitha log-et duhet tĂ« dĂ«rgohen nĂ« stdout. Aty mund tâi shihni me komandĂ«n docker logs.
P: Igor Ivanovich, ndoshta do t'i transferojmë log-et në një direktor të montuar, në nodën fizike, si të dhënat e përdoruesve?
AI: Mirë që nuk e pate harruar të dalësh me të dhënat që ngarkohen në diskun e nodës. Me log-et mund të bësh po ashtu, vetëm mos harro të konfigurosh rotimin.
Mirë, mund të ikësh.
P: Igor Ivanovich, do you have any recommendations on what to read?
AI: To start, read , hardly anyone knows Docker better than them.
And if you want to gain practical experience, check out the . After all, theory without practice is dead.
Burimi: habr.com
