Docker: nevēlamie padomi

Manas rakstā komentāros Docker: kaitīgas rekomendācijas bija daudzas lūgums paskaidrot, kāpēc aprakstītais Dockerfile ir tik briesmīgs.

Iepriekšējās sērijas īss saturs: divi izstrādātāji stingrā termiņā sastāda Dockerfile. Procesa gaitā pie viņiem ienāk Ops Igors Ivanovičs. Gala Dockerfile ir tik slikts, ka I.I. tiek uz robežas ar infarktu.

Docker: nevēlamie padomi

Tagad sapratīsim, kas nav kārtībā ar šo Dockerfile.

Tātad, ir pagājusi nedēļa.

Izstrādātājs Pēteris sastopas ēdnīcā pie kafijas tases ar Ops Igoru Ivanoviču.

P: Igors Ivanovič, vai jūs esat ļoti aizņemts? Vēlētos noskaidrot, kur mēs ko sajaucām.

I.I.: Tas ir labi, nav bieži sastopami izstrādātāji, kuri interesējas par ekspluatāciju.
Sāksim ar dažām vienošanām:

  1. Docker ideoloģija: viens konteiners — viens process.
  2. Jo mazāks konteiners, jo labāk.
  3. Jo vairāk ņem no keša, jo labāk.

P: Kāpēc vienā konteinerā jābūt vienam procesam?

I.I.: Docker, uzsākot konteineru, uzrauga procesu ar pid 1 stāvokli. Ja process mirst, Docker mēģina restartēt konteineru. Pieņemsim, ka jūsu konteinerā darbojas vairāki lietojumi vai galvenais lietojums nav uzsākts ar pid 1. Ja process mirst, Docker par to neuzzinās.

Ja jautājumu nav, rādiet savu Dockerfile.

Un Pēteris parādīja:

FROM ubuntu:latest

# Pārsūtām avota kodu
COPY .\/ \/app
WORKDIR \/app

# Atjaunojam pakotņu sarakstu
RUN apt-get update 

# Atjaunojam pakotnes
RUN apt-get upgrade

# Instalējam nepieciešamās pakotnes
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full ssh supervisor

# Instalējam bundler
RUN gem install bundler

# Instalējam nodejs, kas tiek izmantots statikas veidošanai
RUN curl -sL https:\/\/deb.nodesource.com\/setup_9.x | sudo bash -
RUN apt-get install -y nodejs

# Instalējam atkarības
RUN bundle install --without development test --path vendor\/bundle

# Notīram kešus
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
# Uzsākam skriptu, pie konteineru startēšanas, kas uzsāks visu pārējo.
CMD ["\/app\/init.sh"]

I.I.: Ak, sāksim risināt pa kārtai. Sāksim ar pirmo rindu:

FROM ubuntu:latest

Jūs ņemat tagu latest. Izmantošana tagam latest var novest pie neparedzamām sekām. Iedomājieties, ka attēla uzturētājs veido jaunu attēla versiju ar citu programmatūras sarakstu, šis attēls saņem tagu latest. Un jūsu konteiners labākajā gadījumā pārstāj būvēt, bet sliktākajā gadījumā jūs saņemat kļūdas, kādas iepriekš nebija.

Jūs ņemat attēlu ar pilnvērtīgu OS, kurā ir daudz nevajadzīga programmatūra, kas palielina konteineru lielumu. Un jo vairāk programmatūras, jo vairāk potenciālo drošības caurumu un ievainojamību.

Turklāt, jo lielāks attēls, jo vairāk vietas tas aizņem vietējā sistēmā un reģistrā (jūs taču kaut kur glabājat attēlus)?

J: Jā, protams, mums ir reģistrs, jūs taču to iestatījāt.

I: Tātad, par ko es runāju?.. Ah jā, par attēliem… Tādējādi palielinās tīkla slodze. Atsevišķam attēlam tas nav pamanāms, taču, kad notiek nepārtraukta izveide, testēšana un izvietošana, tas ir jūtams. Un, ja jums nav Dieva režīma AWS, jums vēl būs jāmaksā par to.

Tāpēc ir jāizvēlas visatbilstošākais attēls ar precīzu versiju un minimālo programmatūru. Piemēram, ņem: FROM ruby:2.5.5-stretch

J: O, saprotu. Kā un kur var apskatīt esošos attēlus? Kā saprast, kurš man ir nepieciešams?

I: Parasti attēli tiek ņemti no Docker Hub, nesajauc ar Pornhub :). Parasti attēlam ir vairākas versijas:
Alpine: attēli, kas veidoti uz minimalistiska Linux attēla, apmēram 5 MB. Tās trūkums: tas ir veidots ar savu libc realizāciju, standarta pakotnes tajā nedarbojas. Nepieciešamā pakotnes meklēšanai un instalēšanai aizņems daudz laika.
Scratch: pamata attēls, ko neizmanto citu attēlu veidošanai. Tas paredzēts tikai bināro, iepriekš sagatavotu datu palaišanai. Ideāli piemērots bināro lietojumprogrammu palaišanai, kuras ietver visu nepieciešamo, piemēram, Go lietojumprogrammas.
Uz kādas OS, piemēram, Ubuntu vai Debian. Nu, šeit domāju, nav jāizskaidro.

I: Tagad mums ir jāinstalē visi papildu pakotnes un nekavējoties jāiztīra keši. Un uzreiz var izmest apt-get upgrade. Citādi, ņemot vērā fiksētu pamata attēla tagu, katru reizi būs jāiegūst dažādi attēli. Pakotņu atjaunināšana attēlā ir uzturētāja uzdevums, kas ir saistīts ar tagu maiņu.

J: Jā, es mēģināju to izdarīt, man izdevās tā:

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/*

I: Ne slikti, bet šeit arī ir, pie kā strādāt. Skat, šī komanda:

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

… nenod dzēš datus no gala attēla, bet tikai izveido papildu slāni bez šiem datiem. Pareizi ir šādi:

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/* 

Bet tas vēl nav viss. Kas jums tur ir, Ruby? Tad nav nepieciešams sākumā kopēt visu projektu. Pietiek ar Gemfile un Gemfile.lock kopēšanu.

Ar šo pieeju bundle install netiks izpildīts pie katras avota izmaiņas, bet tikai tad, ja ir mainījies Gemfile vai Gemfile.lock.

Tās pašas metodes darbojas arī citās valodās ar atkarību pārvaldniekiem, piemēram, npm, pip, composer un citiem, kas balstās uz atkarību saraksta failu.

Un visbeidzot, vai tu atceries, ka sākumā es runāju par Docker ideoloģiju „viens konteiners — viens process”? Tas nozīmē, ka supervizors nav nepieciešams. Tāpat nevajadzētu uzstādīt systemd, to pašu iemeslu dēļ. Praktiski Docker pats ir supervizors. Un, kad tu mēģini tajā palaist vairākus procesus, tas ir kā supervizorā palaist vairākas lietotnes.
Sagatavošanas procesā tu izveidosi vienotu attēlu, un pēc tam palaidīs nepieciešamo skaitu konteineru, lai katrā darbotos viens process.

Par to vēlāk.

J: Izskatās, ka sapratu. Skaties, kas sanāk:

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”]

Bet mēs varam pārdefinēt dēmonu palaišanu, kad konteineru palaidīsim?

AI: Jā, viss pareizi. Starp citu, var izmantot gan CMD, gan ENTRYPOINT. Bet saprast, kāda ir atšķirība, ir tas, ko tu zini mājasdarba uzdevumu. Par šo tēmu Habrā ir labi raksti. raksts.

Tātad, turpināsim. Tu lejupielādē instalācijas failu node, bet nav nekādas garantijas, ka tajā būs tas, kas tev nepieciešams. Jāpapildina ar validāciju. Piemēram, tā:

IZPILDĪT 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/* 

Pateicoties kontroles summai, tu vari pārbaudīt, vai esi lejupielādējis pareizo failu.

P: Bet, ja fails mainīsies, tad būvēšana neizdosies.

AI: Jā, un, kā dīvaini, tas ir arī pluss. Tu uzzināsi, ka fails ir mainījies, un varēsi paskatīties, kas tur ir mainīts. Kas zina, varbūt ir pievienots skripts, kas dzēš visu, ko vien sasniedz, vai arī izveido aizmugures durvis.

P: Paldies. Izskatās, ka gala Dockerfile būs šāds:

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: Igors Ivanovičs, paldies par palīdzību. Man jau jādodas, jāizdara vēl 10 commiti šodien.

Igors Ivanovičs, apstādinot steigāto kolēģi ar skatienu, izdara malku stiprā kafijā. Pārdomājis dažas sekundes par SLA 99.9% un kļūdu brīvo kodu, viņš uzdod jautājumu.

AI: Kur jūs uzglabājat logus?

P: Protams, production.log. Starp citu, kā mēs bez ssh piekļūsim tiem?

AI: Ja jūs tos atstājat failos, risinājums jau ir izdomāts. Komanda docker exec ļauj izpildīt jebkuru komandu konteinerā. Piemēram, jūs varat izmantot cat logiem. Un, ja izmantosit atslēgu -it un palaist bash (ja tas ir uzstādīts konteinerā), jūs iegūsiet interaktīvu piekļuvi konteineram.

Bet logus nav vērts uzglabāt failos. Vismaz tas noved pie nekontrolētas konteineru izaugsmes, jo logus neviens nerotē. Visiem logiem jābūt stdout. Tur tos jau var apskatīt, izmantojot komandu docker logs.

P: Igors Ivanovičs, bet varbūt iznest logus uz pievienoto direktoriju, uz fizisko mezglu, kā lietotāju datus?

AI: Labi, ka tu neaizmiri iznest datus, kas uzglabāti mezgla diskā. Ar logiem arī tā var, tikai nepārsteidzies ar rotāciju.
Visi, vari iet.

P: Igors Ivanovičs, lūdzu, ieteiktu, ko izlasīt?

II: Sāc ar izstrādātāju ieteikumiem par Docker, droši vien neviens nezina Docker labāk par viņiem.

Ja vēlies veikt praksi, doties uz intensīvo apmācību. Galu galā teorija bez prakses ir mirusi.

Avots: habr.com

Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem 🔥 Iegādājieties uzticamu tīmekļa hostingu ar DDoS aizsardzību, VPS VDS serveriem | ProHoster