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>