Взлом
Уважаемые гости! При посещении нашего сайта просим вас ознакомиться с разделами форума, прежде чем оставлять ваши объявления и т.п., а также при обращении за помощью просим быть внимательными: на сайте есть как проверенные специалисты, так и непроверенные. Если вы обратились к специалисту, который проверку НЕ проходил, рекомендуем воспользоваться услугой гарант-сервиса. Спасибо, что посетили форум хакеров.

Как собрать Docker образ который можно запускать в проде

BoHDaN★

Новый
Пользователь
Регистрация
7 Авг 2025
Сообщения
19
Реакции
0
Баллы
1
Возраст
31
Если ты пишешь Dockerfile, скорее всего, он работает. Но вопрос не в том, работает ли. Вопрос во втором: будет ли он работать через неделю, на втором сервере, в CI/CD, на чужом железе — и будет ли это безопасно. Или все сломается, потому что ты не зафиксировал зависимости, положился на последний, и забыл о том, что ENTRYPOINT — это тоже код.
В этой статье я роскажу как собрать нормальный Docker-образ, который предсказуем, устойчив и готов к продакшену.
Знімок екрана 2025-08-21 145909.png

1. Первая ошибка: ты начинаешь с плохой базы

Многие берут базовый образ, не задумываясь. Например, python:3.12. Это "толстый" образ с кучей ненужных пакетов. Он может весить 1+ ГБ. Там куча системных библиотек, что увеличивает потенциальную поверхность для атак и делает билды медленнее.

Плохой Dockerfile:

FROM python:3.12

WORKDIR /app

COPY. .

RUN pip install -r requirements.txt

CMD ["python", "main.py"]

Что здесь не так:

Образ велик.

Все слои кэша сбиваются при любом изменении.

Ты клонируешь весь проект внутрь, включая мусор.

Как лучше:

Брать python:3.12-slim или python:3.12-alpine, но только если понимаешь, как с ним работать и зачем ты его выбираешь.

Использовать многоступенчатую сборку: сначала билд, потом перенос нужного в "чистую" фазу.

Указывать чёткую структуру слоев: сначала зависимости, потом код.

2. Не используй latest

latest - это ловушка. Сегодня образ один, завтра он обновится, и все сломается. Причем сломается неожиданно – у тебя в проде или в CI.

Пример:

FROM node:latest

В понедельник это Node 18. В среду уже 20. И твой build падает, потому что какой-то пакет несовместим.

Лучше указать конкретную версию:

FROM node:18.16.1

Или даже с sha256:

FROM node@sha256:<digest>

Это не просто паранойя. Это способ зафиксировать окружение. Больше контроля – меньше сюрпризов.

3. Пример хорошего Dockerfile для Python‑приложения

FROM python:3.12.1-slim as builder

WORKDIR /install

RUN apt-get update && apt-get install -y build-essential

COPY requirements.txt .

RUN pip install --upgrade pip && \

pip wheel --no-deps --wheel-dir /wheels -r requirements.txt

FROM python:3.12.1-slim

ENV PYTHONDONTWRITEBYTECODE=1 \

PYTHONUNBUFFERED=1

WORKDIR /app

COPY --from=Builder /wheels /wheels

COPY requirements.txt .

RUN pip install --no-deps --no-index --find-links=/wheels -r requirements.txt

COPY. .

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

Этот Dockerfile делает две вещи: сначала собирает в зависимости, потом создает чистый образ с приложением. Так получается меньше мусора и быстрее сборка.

Первая часть – сборка зависимостей:

Берем легкий образ Python 3.12.1

Ставим build-essential – он нужен для компиляции некоторых пакетов

Копируем файл requirements.txt

Собираем зависимости в wheel-файлы (это как zip-архивы для Python-пакетов)

Фишка в том, что build-essential останется только в этой временной части и не попадет в итоговый образ.

Вторая часть – финальный образ:

Снова берём чистый Python 3.12.1 без лишнего

Настраиваем две важные переменные:

PYTHONDONTWRITEBYTECODE — чтобы не создавались .pyc-файлы

PYTHONUNBUFFERED — чтобы логи выводились сразу

Копируем wheel-файлы из первой части

Ставим зависимости из этих файлов (уже без интернета и компиляции)

Копируем само приложение

Запускаем uvicorn на порту 8000

Почему так лучше:

Итоговый образ меньше весит

Не нужно компилировать пакеты при каждом запуске

Сборка идет быстрее счёт кеширования wheel-файлов

Нет лишних пакетов типа build-essential в финальном образе

Если нужно добавить что-нибудь в образ (например, curl для healthcheck), делай это перед последним COPY. Но помни – каждый RUN добавляет слой к образу.

4. .dockerignore - must-have

Без .dockerignore ты случайно кладешь в образ лишнее:

.git

pycache

.env

.vscode/

node_modules/

и т.д. и т.п.

Это увеличивает размер, сбивает кэш и вообще плохо.

Пример .dockerignore:

.git

__pycache__/

*.pyc

.env

.vscode/

node_modules/

*.log

Сделай это один раз – и забудешь о проблемах.

5. Volume: будь осторожен

Проблема: когда ты монтируешь volume, он затирает всё внутри контейнера.

docker run -v $(pwd):/app myapp

В результате:

Все, что ты собрал – перезаписано.

Права доступа могут сломать работу.

Что делать:

Используй именованные volume:

docker volume create mydata

docker run -v mydata:/data myapp

Пропиши правильные права заранее.

6. CMD и ENTRYPOINT

Нюанс: CMD подменяется, ENTRYPOINT – остается.

Пример:

CMD ["python", "app.py"]

Ты запустил:

docker run myapp bash

А получил: python app.py bash

Правильно да:

ENTRYPOINT ["python", "app.py"]

CMD ["--debug"]

Теперь все работает предсказуемо.

7. USER: не запускай все от root

По умолчанию Docker запускается от root. Это небезопасно. Особенно если есть volume или доступ к сокету.

Добавь:

RUN useradd -m myuser

USER myuser

Теперь все работает от безопасного пользователя. И если кто-нибудь сломает контейнер, он не получит root.

8. Healthcheck

Docker считает, что контейнер жил, если он просто не умер. Но твой сервис может зависнуть или вернут 500.

Добавить healthcheck:

HEALTHCHECK --interval=30s --timeout=10s --retries=3 \

CMD curl -f http://localhost:8000/health || exit 1

Теперь Docker будет знать, когда сервис реально жил.

9. Кэш Docker

Слои в Docker кэшируются. Если ты пишешь слои неправильно, кэш не работает.

Плохо:

COPY. .

RUN pip install -r requirements.txt

Лучше:

COPY requirements.txt .

RUN pip install -r requirements.txt

COPY. .

Теперь, когда ты меняешь только код, зависимости не ставятся заново.

10. Docker в CI

Частые ошибки:

Пуш latest без тега.

Кладут частные ключи в образ.

Не используют .dockerignore.

Как надо:

Указывать метки явно: myapp:1.2.3

Не храните секреты в образе. использовать secrets или переменные окружения.

Убедится, что .dockerignore есть и рабочий.

11. Уменьшение размера вида

Каждый MB важен, особенно в CI/CD. Что можно сделать:

Убирать временные пакеты после использования.

RUN apt-get install -y gcc && pip install some-lib && apt-get remove -y gcc

Использовать --no-cache и чистить /tmp.

Применят slim, а не full-образы.

12. Alpine - не серебряная пуля

Да, вон маленький. Но:

Использует musl, а не glibc.

Проблемы с совместимостью C-библиотек.

Долгий билд Python-пакетов.

Используй Alpine только если ты понимаешь, зачем он тебе нужен. В остальных случаях – slim.

Итоги:

Сборка Docker-образа — это не только про "работает ли у меня". Это про устойчивость, безопасность и предсказуемость. Маленькие ошибки приводят к большим проблемам.
 
Яндекс.Метрика