Докер: жаман кеңес емес

Менің мақалама түсініктемелерде Докер: жаман кеңес онда сипатталған Dockerfile неге соншалықты қорқынышты екенін түсіндіруге көптеген сұраулар болды.

Алдыңғы бөлімнің қысқаша мазмұны: Екі әзірлеуші ​​қысқа мерзімде Dockerfile жасайды. Сөйтіп жүргенде оларға Оп Игорь Иванович келеді. Алынған Dockerfile соншалықты нашар, AI инфаркт алдында тұр.

Докер: жаман кеңес емес

Енді осы Docker файлында не дұрыс емес екенін анықтайық.

Сонымен, бір апта өтті.

Дев Петя асханада бір шыны кофе үстінде опп Игорь Ивановичті кездестіреді.

П: Игорь Иванович, сіз өте боссыз ба? Мен қай жерде бүлдіргенімізді білгім келеді.

AI: Бұл жақсы, сіз эксплуатацияға қызығушылық танытатын әзірлеушілерді жиі кездестіре бермейсіз.
Алдымен, бірнеше нәрсеге келісіп алайық:

  1. Докер идеологиясы: бір контейнер – бір процесс.
  2. Контейнер неғұрлым аз болса, соғұрлым жақсы.
  3. Кэштен неғұрлым көп алсаңыз, соғұрлым жақсы.

P: Неліктен бір контейнерде бір процесс болуы керек?

AI: Docker, контейнерді іске қосқан кезде, процестің күйін pid 1 арқылы бақылайды. Процесс бітсе, Docker контейнерді қайта іске қосуға тырысады. Контейнерде жұмыс істейтін бірнеше қолданбаңыз бар делік немесе негізгі қолданба pid 1-мен жұмыс істемейді делік. Процесс тоқтап қалса, Docker бұл туралы білмейді.

Қосымша сұрақтарыңыз болмаса, бізге Docker файлыңызды көрсетіңіз.

Ал Петя көрсетті:

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

А.И.: Ой, ретімен алайық. Бірінші жолдан бастайық:

FROM ubuntu:latest

Сіз белгіні алыңыз latest. Тегті пайдалану latest болжауға болмайтын салдарға әкеледі. Елестетіп көріңізші, кескінді сақтаушы бағдарламалық жасақтаманың басқа тізімі бар кескіннің жаңа нұсқасын жасайды, бұл кескін соңғы тегті алады. Сіздің контейнеріңіз, ең жақсы жағдайда, құрылысты тоқтатады, ал ең нашар жағдайда, сіз бұрын болмаған қателерді ұстайсыз.

Сіз контейнердің көлемін арттыратын көптеген қажетсіз бағдарламалық жасақтамасы бар толыққанды ОЖ-мен суретке түсіресіз. Және бағдарламалық жасақтама неғұрлым көп болса, соғұрлым көп тесіктер мен осалдықтар.

Сонымен қатар, кескін неғұрлым үлкен болса, ол хостта және тізілімде көбірек орын алады (суреттерді бір жерде сақтайсыз ба)?

P: Иә, әрине, бізде реестр бар, оны өзіңіз орнатасыз.

А.И.: Ендеше, мен нені айтып отырмын?.. Иә, томдар... Желіге жүктеме де артып барады. Бір кескін үшін бұл байқалмайды, бірақ үздіксіз құрастыру, сынақтар және орналастыру кезінде ол байқалады. Егер сізде AWS-те Құдайдың режимі болмаса, сіз ғарыштық шот аласыз.

Сондықтан нақты нұсқасы мен минималды бағдарламалық жасақтамасы бар ең қолайлы кескінді таңдау керек. Мысалы, алыңыз: FROM ruby:2.5.5-stretch

P: О, түсіндім. Қол жетімді суреттерді қалай және қай жерден көруге болады? Маған қайсысы керек екенін қайдан білемін?

AI: Әдетте суреттер мына жерден алынады dockerhub, pornhub-пен шатастырмаңыз :). Кескін үшін әдетте бірнеше жинақтар бар:
Альпі: кескіндер минималистік Linux кескінінде жинақталған, бар болғаны 5 МБ. Оның кемшілігі: ол өзінің libc іске асыруымен құрастырылған, стандартты пакеттер онда жұмыс істемейді. Қажетті пакетті табу және орнату көп уақытты алады.
Сызу: негізгі кескін, басқа кескіндерді құру үшін пайдаланылмайды. Ол тек екілік, дайындалған деректерді іске қосуға арналған. GO қолданбалары сияқты қажеттінің барлығын қамтитын екілік қолданбаларды іске қосу үшін өте қолайлы.
Ubuntu немесе Debian сияқты кез келген ОЖ негізінде. Жақсы, түсіндірудің қажеті жоқ деп ойлаймын.

AI: Енді біз барлық қосымшаларды орнатуымыз керек. пакеттер мен кэштерді тазалаңыз. Ал сіз оны бірден лақтырып тастай аласыз upgrade жаңарту. Әйтпесе, әрбір құрастыру кезінде негізгі кескіннің бекітілген тегіне қарамастан, әртүрлі кескіндер алынады. Кескіндегі бумаларды жаңарту қызмет көрсетушінің міндеті болып табылады және тегті өзгертумен бірге жүреді.

P: Иә, мен мұны істеуге тырыстым, ол былай болды:

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

А.И.: Жаман емес, бірақ жұмыс істейтін нәрсе де бар. Міне, мына пәрмен:

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

... соңғы кескіннен деректерді жоймайды, тек бұл деректерсіз қосымша қабат жасайды. Мынадай дұрыс:

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

Бірақ бұл бәрі емес. Онда не бар, Руби? Содан кейін барлық жобаны басында көшіріп алудың қажеті жоқ. Gemfile және Gemfile.lock файлдарын көшіру жеткілікті.

Бұл тәсілмен пакетті орнату әрбір бастапқы өзгеріс үшін орындалмайды, бірақ Gemfile немесе Gemfile.lock өзгерген жағдайда ғана.

Дәл осындай әдістер тәуелділіктер тізімі бар файлға негізделген npm, pip, composer және басқалары сияқты тәуелділік менеджерімен басқа тілдер үшін жұмыс істейді.

Соңында, мен Docker идеологиясы туралы «бір контейнер – бір процесс» туралы айтқанымды есіңізде ме? Бұл супервайзер қажет емес дегенді білдіреді. Сондай-ақ, бірдей себептермен systemd орнатуға болмайды. Негізінде, Докердің өзі супервайзер. Онда бірнеше процестерді іске қосуға тырысқанда, бұл бір супервайзер процесінде бірнеше қолданбаларды іске қосу сияқты.
Құрылыс кезінде сіз бір кескін жасайсыз, содан кейін әрқайсысында бір процесс орындалатындай контейнерлердің қажетті санын іске қосасыз.

Бірақ бұл туралы кейінірек.

P: Мен түсіндім деп ойлаймын. Не болып жатқанын қараңыз:

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

Контейнерді іске қосқан кезде демондарды іске қосуды жоққа шығара аламыз ба?

А.И.: Иә, дұрыс. Айтпақшы, сіз CMD және ENTRYPOINT екеуін де пайдалана аласыз. Ал айырмашылығы неде екенін анықтау - үй тапсырмасы. Хабреде бұл тақырыпта жақсы нәрсе бар мақала.

Олай болса, әрі қарай жүрейік. Сіз түйінді орнату үшін файлды жүктейсіз, бірақ ол сізге қажет нәрсені қамтитынына кепілдік жоқ. Біз тексеруді қосуымыз керек. Мысалы, келесідей:

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

Бақылау сомасын пайдаланып, дұрыс файлды жүктеп алғаныңызды тексеруге болады.

P: Бірақ файл өзгерсе, құрастыру сәтсіз болады.

А.И.: Иә, бір қызығы, бұл да плюс. Сіз файлдың өзгергенін білесіз және сол жерде не өзгергенін көре аласыз. Сіз ешқашан білмейсіз, олар қол жеткізе алатын барлық нәрсені жоятын немесе бэкдор жасайтын сценарийді қосты.

P: рахмет. Соңғы Dockerfile келесідей болады:

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

П: Игорь Иванович, көмегіңіз үшін рахмет. Менің жүгіретін уақытым келді, бүгін тағы 10 міндеттеме жасауым керек.

Игорь Иванович асығыс әріптесін көзімен тоқтатып, қою кофеден бір жұттады. 99.9% SLA және қатесіз код туралы бірнеше секунд ойланғаннан кейін ол сұрақ қояды.

AI: Сіз журналдарды қайда сақтайсыз?

P: Әрине, production.log сайтында. Айтпақшы, иә, бірақ біз оларға sshсіз қалай қол жеткізе аламыз?

AI: Егер сіз оларды файлдарда қалдырсаңыз, сіз үшін шешім ойлап табылған. Docker exec пәрмені контейнердегі кез келген пәрменді орындауға мүмкіндік береді. Мысалы, сіз бөренелер үшін мысық жасай аласыз. Және кілтті пайдалану -бұл және іске қосу bash (контейнерде орнатылған болса) сізге контейнерге интерактивті қол жеткізуге мүмкіндік береді.

Бірақ журналдарды файлдарда сақтамау керек. Кем дегенде, бұл контейнердің бақылаусыз өсуіне әкеледі және ешкім журналдарды айналдырмайды. Барлық журналдар stdout-қа жіберілуі керек. Онда оларды пәрмен арқылы көруге болады докер журналдары.

P: Игорь Иванович, мүмкін мен журналдарды бекітілген каталогқа, физикалық түйінге, пайдаланушы деректері ретінде қоюға болады ма?

AI: Түйін дискісіне жүктелген деректерді жоюды ұмытпағаныңыз жақсы. Сіз мұны журналдармен де жасай аласыз, тек айналуды орнатуды ұмытпаңыз.
Болды, жүгіруге болады.

П: Игорь Иванович, маған не оқуға кеңес бере аласыз ба?

А.И.: Алдымен оқы Docker әзірлеушілерінің ұсыныстары, Доккерді олардан артық ешкім білмейді.

Ал тәжірибеден өткіңіз келсе, барыңыз қарқынды. Өйткені практикасыз теория өлі.

Ақпарат көзі: www.habr.com

пікір қалдыру