HTML Diff
0 added 0 removed
Original 2026-01-01
Modified 2026-02-19
1 <p>Привет, я Дмитрий Желудков, архитектор по эксплуатации, и сегодня я покажу, как собрать приложение в docker на вот этих вот 4 левых пальцах (а как же иначе, у нас же серьёзное исследование).</p>
1 <p>Привет, я Дмитрий Желудков, архитектор по эксплуатации, и сегодня я покажу, как собрать приложение в docker на вот этих вот 4 левых пальцах (а как же иначе, у нас же серьёзное исследование).</p>
2 <p>На незаданный вопрос я смело отвечу, что иногда требуется взять своё простое, но гордое приложение, и запустить его внутри контейнера, чтобы:</p>
2 <p>На незаданный вопрос я смело отвечу, что иногда требуется взять своё простое, но гордое приложение, и запустить его внутри контейнера, чтобы:</p>
3 <ul><li>запускалось одинаково везде (даже на машине тёти Зины);</li>
3 <ul><li>запускалось одинаково везде (даже на машине тёти Зины);</li>
4 <li>можно было задеплоить хоть в облако, хоть на ведро;</li>
4 <li>можно было задеплоить хоть в облако, хоть на ведро;</li>
5 <li>не думать про зависимости, версии, среды и вот это всё.</li>
5 <li>не думать про зависимости, версии, среды и вот это всё.</li>
6 </ul><p>Как вы могли заметить, мы подошли к одному из постулатов эксплуатации: "В первую очередь, контейнер - это артефакт поставки приложения, а уже потом изоляция", и сделали важный шаг к большим оркестраторам k8s.</p>
6 </ul><p>Как вы могли заметить, мы подошли к одному из постулатов эксплуатации: "В первую очередь, контейнер - это артефакт поставки приложения, а уже потом изоляция", и сделали важный шаг к большим оркестраторам k8s.</p>
7 <p>Поехали к делу.</p>
7 <p>Поехали к делу.</p>
8 <p>Простой пример: у нас есть приложение на Python, которое мы запускаем как python app.py. Ничего экзотического. Берём Python как самый популярный язык программирования в мире по версии TIOBE на июль 2025 года. На этом серьёзность исследования заканчиваем и дальше можно не ждать авторитетных источников).</p>
8 <p>Простой пример: у нас есть приложение на Python, которое мы запускаем как python app.py. Ничего экзотического. Берём Python как самый популярный язык программирования в мире по версии TIOBE на июль 2025 года. На этом серьёзность исследования заканчиваем и дальше можно не ждать авторитетных источников).</p>
9 <p><strong>Шаг 1. Готовим проект</strong></p>
9 <p><strong>Шаг 1. Готовим проект</strong></p>
10 <p>Вот структура проекта:</p>
10 <p>Вот структура проекта:</p>
11 <p>myapp/</p>
11 <p>myapp/</p>
12 <p>├── app.py</p>
12 <p>├── app.py</p>
13 <p>├── requirements.txt</p>
13 <p>├── requirements.txt</p>
14 <p>app.py может быть хоть "Hello, world!", или же веб-приложение, не суть. Главное - он запускается и работает. Если же не запускается и не работает, то, боюсь, ваше приложение недостаточно гордое и придётся его доработать.</p>
14 <p>app.py может быть хоть "Hello, world!", или же веб-приложение, не суть. Главное - он запускается и работает. Если же не запускается и не работает, то, боюсь, ваше приложение недостаточно гордое и придётся его доработать.</p>
15 <p>В requirements.txt перечислены зависимости, например:</p>
15 <p>В requirements.txt перечислены зависимости, например:</p>
16 <p>flask</p>
16 <p>flask</p>
17 <p>requests</p>
17 <p>requests</p>
18 <p>В общем, полноценный проект, с большой буквы П.</p>
18 <p>В общем, полноценный проект, с большой буквы П.</p>
19 <p><strong>Шаг 2. Пишем Dockerfile</strong></p>
19 <p><strong>Шаг 2. Пишем Dockerfile</strong></p>
20 <p>Теперь создаём файл Dockerfile в корне проекта:</p>
20 <p>Теперь создаём файл Dockerfile в корне проекта:</p>
21 <p>FROM python:3.13-slim</p>
21 <p>FROM python:3.13-slim</p>
22 <p>WORKDIR /app</p>
22 <p>WORKDIR /app</p>
23 <p>COPY requirements.txt .</p>
23 <p>COPY requirements.txt .</p>
24 <p>RUN pip install --no-cache-dir -r requirements.txt</p>
24 <p>RUN pip install --no-cache-dir -r requirements.txt</p>
25 <p>COPY . .</p>
25 <p>COPY . .</p>
26 <p>CMD ["python", "<a>app.py</a>"]</p>
26 <p>CMD ["python", "<a>app.py</a>"]</p>
27 <p>Что тут происходит:</p>
27 <p>Что тут происходит:</p>
28 <ul><li>берём официальный образ Python, но облегчённый (slim);</li>
28 <ul><li>берём официальный образ Python, но облегчённый (slim);</li>
29 <li>переходим в директорию /app внутри контейнера;</li>
29 <li>переходим в директорию /app внутри контейнера;</li>
30 <li>копируем зависимости и ставим их через pip;</li>
30 <li>копируем зависимости и ставим их через pip;</li>
31 <li>копируем весь проект внутрь контейнера;</li>
31 <li>копируем весь проект внутрь контейнера;</li>
32 <li>запускаем app.py, когда контейнер стартует.</li>
32 <li>запускаем app.py, когда контейнер стартует.</li>
33 </ul><p>Dockerfile - это такой файл‑рецепт. Прям как инструкция к сборке мебели из ИКЕА, только для приложения. Ты пишешь в нём, из чего собирать образ (например, взять Ubuntu, поставить туда Python, или сразу взять Python, поставить зависимости), что скопировать внутрь, какие команды выполнить и как запускать это всё добро.</p>
33 </ul><p>Dockerfile - это такой файл‑рецепт. Прям как инструкция к сборке мебели из ИКЕА, только для приложения. Ты пишешь в нём, из чего собирать образ (например, взять Ubuntu, поставить туда Python, или сразу взять Python, поставить зависимости), что скопировать внутрь, какие команды выполнить и как запускать это всё добро.</p>
34 <p>От этого куча плюсов: и версионирование вариантов сборок, и автоматизация сборки и доставки на стенды (вот это наше любимое CI/CD), и не надо объяснять новичку, как собирать проект "делай docker build".</p>
34 <p>От этого куча плюсов: и версионирование вариантов сборок, и автоматизация сборки и доставки на стенды (вот это наше любимое CI/CD), и не надо объяснять новичку, как собирать проект "делай docker build".</p>
35 <p>Мы, собственно, уже написали файл-инструкцию о том, как упаковать наше гордое приложение в контейнер (включая зависимости), и как его запускать.</p>
35 <p>Мы, собственно, уже написали файл-инструкцию о том, как упаковать наше гордое приложение в контейнер (включая зависимости), и как его запускать.</p>
36 <p>За скобками остаются такие вещи, как FROM scratch, почему python, а не alpine, и почему указана версия, а не latest, да и что такое latest, но, думаю, имея пытливый ум, вы найдёте ответы на эти вопросы.</p>
36 <p>За скобками остаются такие вещи, как FROM scratch, почему python, а не alpine, и почему указана версия, а не latest, да и что такое latest, но, думаю, имея пытливый ум, вы найдёте ответы на эти вопросы.</p>
37 <p><strong>Шаг 3. Собираем образ</strong></p>
37 <p><strong>Шаг 3. Собираем образ</strong></p>
38 <p>В терминале, находясь в директории с Dockerfile, выполняем:</p>
38 <p>В терминале, находясь в директории с Dockerfile, выполняем:</p>
39 <p>docker build -t myapp .</p>
39 <p>docker build -t myapp .</p>
40 <p>Это соберёт образ с тегом myapp. Docker пройдётся по Dockerfile и на каждый шаг сделает слой.</p>
40 <p>Это соберёт образ с тегом myapp. Docker пройдётся по Dockerfile и на каждый шаг сделает слой.</p>
41 <p>Так, стойте, какие слои, мы что, готовим пирог?</p>
41 <p>Так, стойте, какие слои, мы что, готовим пирог?</p>
42 <p>Да, слои в Docker - это как слоёный пирог, только вместо теста и начинки у нас команды из Dockerfile.</p>
42 <p>Да, слои в Docker - это как слоёный пирог, только вместо теста и начинки у нас команды из Dockerfile.</p>
43 <p>Каждая инструкция (FROM, COPY, RUN, CMD) - это один слой. И Docker собирает твой образ слой за слоем. Как только ты что-то написал в Dockerfile, он создаёт новый слой на основе предыдущего.</p>
43 <p>Каждая инструкция (FROM, COPY, RUN, CMD) - это один слой. И Docker собирает твой образ слой за слоем. Как только ты что-то написал в Dockerfile, он создаёт новый слой на основе предыдущего.</p>
44 <p>Зачем это всё?</p>
44 <p>Зачем это всё?</p>
45 <p>Docker кеширует слои. Если ты не менял код, а просто перезапускаешь сборку, он не будет заново ставить Python или зависимости - он возьмёт готовые слои из кэша. Быстрее, дешевле, удобнее.</p>
45 <p>Docker кеширует слои. Если ты не менял код, а просто перезапускаешь сборку, он не будет заново ставить Python или зависимости - он возьмёт готовые слои из кэша. Быстрее, дешевле, удобнее.</p>
46 <p>Ну и да: образы легче обновлять. Поменял только одну строчку? Пересобрался только один слой, остальное осталось как есть. Конечно, если у вас код подъезжает последними слоями, а не в первую очередь.</p>
46 <p>Ну и да: образы легче обновлять. Поменял только одну строчку? Пересобрался только один слой, остальное осталось как есть. Конечно, если у вас код подъезжает последними слоями, а не в первую очередь.</p>
47 <p>Так что слои - это и про оптимизацию, и про повторное использование, и вообще про порядок в контейнерной жизни.</p>
47 <p>Так что слои - это и про оптимизацию, и про повторное использование, и вообще про порядок в контейнерной жизни.</p>
48 <p>Тут ещё можем рассказать о другие инструменты сборки, но это уже не про пальцы.</p>
48 <p>Тут ещё можем рассказать о другие инструменты сборки, но это уже не про пальцы.</p>
49 <p><strong>Шаг 4. Запускаем контейнер</strong></p>
49 <p><strong>Шаг 4. Запускаем контейнер</strong></p>
50 <p>Теперь можно запустить наше приложение в контейнере:</p>
50 <p>Теперь можно запустить наше приложение в контейнере:</p>
51 <p>docker run --rm myapp</p>
51 <p>docker run --rm myapp</p>
52 <p>Если всё ок, увидим вывод от app.py. Можно порт пробросить, если приложение вебовое:</p>
52 <p>Если всё ок, увидим вывод от app.py. Можно порт пробросить, если приложение вебовое:</p>
53 <p>docker run -p 8000:8000 myapp</p>
53 <p>docker run -p 8000:8000 myapp</p>
54 <p>Опять же, под капотом и за кулисами есть всякое интересное: cgroup, namespace - но мы же сегодня про "4 простых шага для чайников".</p>
54 <p>Опять же, под капотом и за кулисами есть всякое интересное: cgroup, namespace - но мы же сегодня про "4 простых шага для чайников".</p>
55 <p>Можно ещё ключ -d добавить, чтобы он в фон провалился. Или в compose обернуть, если у вас несколько сервисов и ещё база данных, и прочее сетевое взаимодействие. Ну или про структуру хранения файлов в Git-репозитории рассказать, и про CI, и много-много чего другого.</p>
55 <p>Можно ещё ключ -d добавить, чтобы он в фон провалился. Или в compose обернуть, если у вас несколько сервисов и ещё база данных, и прочее сетевое взаимодействие. Ну или про структуру хранения файлов в Git-репозитории рассказать, и про CI, и много-много чего другого.</p>
56 <p>Но базово, вот так просто и без фанатизма, мы запихнули приложение в контейнер.</p>
56 <p>Но базово, вот так просто и без фанатизма, мы запихнули приложение в контейнер.</p>
57 <p>Теперь можно в бой? На самом деле нет, ибо нюансов много, да и глубина кроличьей норы поражает. Но именно эта задумана как отправная точка в мир контейнеров для самых маленьких, с которой можно начинать знакомство.</p>
57 <p>Теперь можно в бой? На самом деле нет, ибо нюансов много, да и глубина кроличьей норы поражает. Но именно эта задумана как отправная точка в мир контейнеров для самых маленьких, с которой можно начинать знакомство.</p>
58 <p>Главное - не бойтесь Dockerfile. Он страшен только снаружи. А внутри - просто шаги, как в рецепте.</p>
58 <p>Главное - не бойтесь Dockerfile. Он страшен только снаружи. А внутри - просто шаги, как в рецепте.</p>
59 <p><strong>Больше интересного и полезного про работу в Docker - на курсе Слёрма<a>"Docker для админов и разработчиков".</a></strong>Если вы хотите освоить Docker с нуля и уверенно разворачивать, управлять и масштабировать приложения в реальных условиях, вам сюда.</p>
59 <p><strong>Больше интересного и полезного про работу в Docker - на курсе Слёрма<a>"Docker для админов и разработчиков".</a></strong>Если вы хотите освоить Docker с нуля и уверенно разворачивать, управлять и масштабировать приложения в реальных условиях, вам сюда.</p>
60 <p>Приятного контейнеринга!</p>
60 <p>Приятного контейнеринга!</p>