Хабрахабр

Docker: вредные советы

Это правило я запомнил сразу и на всю жизнь. Когда я учился водить машину, на первом же занятии инструктор выехал на перекресток задним ходом, а потом сказал, что делать так нельзя — вообще никогда.

Читаешь детям «Вредные советы» Григория Остера, и видишь, как легко и непринужденно до них доходит, что так делать нельзя.

Но мне не попадалось инструкций, как писать неправильные Dockerfile. О том, как правильно писать Dockerfile, написана куча статей. И, может быть, в проектах, которые я получаю на поддержку, таких докерфайлов станет меньше. Восполняю этот пробел.

Если вы узнали себя, сорри. Все герои, ситуации и Dockerfile вымышленные.

Создаем Dockerfile, зловещий и ужасный

Столько статей по нему, глаза разбегаются. Петр (Senior java/rubby/php developer): Коллега Василий, вы уже залили в Docker новый модуль?
Василий (junior): Нет, не успел, никак не разберусь с этим Docker.

Давай помогу, в процессе разберемся. Петр: У нас дедлайн год назад вышел. Рассказывай, что там у тебя не получается.

А что много лишнего, потом еще пригодится. Василий: Не могу выбрать базовый образ, чтобы минимальный, но было все, что нужно.
Петр: Бери образ ubuntu, в нем есть все, что нужно. И не забудь поставить тэг latest, чтобы версия всегда была самая последняя.

И в Dockerfile появляется первая строка:

FROM ubuntu:latest

Петр: Что там дальше, на чем мы писали наш модуль?
Василий: Так ruby жe, там веб сервер и пара служебных демонов должно запускаться.
Петр: Ага, что нам надо: ruby, bundler, nodejs, imagemagick ну и что там еще … И заодно, сделай upgrade, чтобы точно получить новые пакеты.
Василий: А пользователя не будем создавать, чтобы не из под root?
Петр: Да ну его, потом еще морочиться с правами.
Василий: Мне нужно время, минут 15, чтобы это все в одну команду слепить, я читал, что…
(Петр грубо прерывает дотошного и шибко умного джуна.)
Петр: Пиши отдельными командами, так и читать проще будет.

Dockerfile растет:

FROM ubuntu:latest
RUN apt-get update
RUN apt-get upgrade
RUN apt-get -y install libpq-dev imagemagick gsfonts ruby-full
RUN gem install bundler
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/*

Тут в кабинет врывается Игорь Иванович, DevOps (но больше Ops, чем Dev), с криками:

ИИ: Петя, твои разработчики опять разломали прод БД, когда же это закончится….

После небольшой перепалки Игорь Иванович остывает и начинает выяснять, чем коллеги тут занимаются.

И вообще, это никуда не годится.
Петр: Идите, пожалуйста, по своим делам, мы тут как-нибудь разберемся. ИИ: Чем заняты?
Василий: Петр помогает мне составить Dockerfile для нового модуля.
ИИ: Дайте глянуть… Да что вы тут понаписали, вы же репозиторий чистите отдельной командой, это же дополнительный слой… Да как же вы ставите зависимости, если не скопировали Gemfile!

Игорь Иванович тоскливо вздыхает и уходит разбираться, кто-таки сломал БД.

И давай сразу поставим ssh и supervisor, а то как мы демонов запускать будем. Петр: Да, но про код-то он правильно сказал, надо его в имидж запихнуть.

Если Gemfile не меняется, слой возьмется из кэша.
Петр: Что вы все с этими слоями, копируй сразу все. Василий: Я тогда сначала скопирую Gemfile и Gemfile.lock, потом все поставлю, и потом уже копирую весь проект. Первой же строкой. Сразу копируй.

Dockerfile теперь выглядит так:

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
RUN gem install bundler
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/*

У тебя есть конфиги для supervisor?
Василий: Нее, нету. Петр: Так, что дальше. Давай сейчас набросаем init скрипт, который будет все запускать. Но я быстро сделаю.
Петр: Потом сделаешь. Потом так же запускай supervisor. Так-с, значит, запускаешь ssh, с nohup, чтобы мы могли подключиться к контейнеру и посмотреть, что пошло не так. И вообще, как? Ну и потом просто запустишь passenger.
В: Но я читал, что должен быть один процесс, так Docker будет знать, что что-то пошло не так, и сможет перезапустить контейнер.
П: Не забивай голову ерундой. Пусть о стабильности Игорь Иванович думает, не зря же он зарплату получает. Как ты это все запустишь в одном процессе? И вообще, пусть скажет спасибо, что мы написали за него Dockefile. Наше дело код писать.

Спустя 10 минут и два видеоролика про котиков.

Еще комментариев понадобавлял.
П: Показывай! В: Я все сделал.

Свежая версия Dockerfile:

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/* # Запускаем скрипт, при старте контейнера, который запустит все остальное.
CMD [“/app/init.sh”]

И комментарии на русском, удобно и читаемо, все бы так работали. П: Отлично, мне нравится. Пошли пить кофе... Я тебя всему научил, дальше сможешь сам.

Dockerfile, конечно же, мог быть еще хуже, нет предела совершенству. Ну, вот мы и получили идеально ужасный Dockerfile, от вида которого Игорь Иванович захочет уволиться и у него еще неделю будут болеть глаза. Но для начала и так сойдет.

Закончить хотелось бы цитатой Григория Остера:

Если вы еще не твердо
В жизни выбрали дорогу,
И не знаете, с чего бы
Трудовой свой путь начать,
Бейте лампочки в подъездах —
Люди скажут вам «Спасибо».
Вы поможете народу
Электричество беречь.

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»