Эта статья для случаев, когда стандартной автонастройки недостаточно и вы хотите полностью контролировать сборку и запуск контейнера.
Когда нужен кастомный Dockerfile
Используйте свой Dockerfile, если вам нужно:
установить системные пакеты (apt, apk) или нестандартные зависимости;
делать многоэтапную сборку (build stage + runtime stage);
явно контролировать команду запуска (CMD/ENTRYPOINT);
запускать веб-приложение вместе с ботом на конкретном порту;
использовать собственную структуру проекта, которую автоопределение не покрывает.
Если ваш проект простой (например, Python-бот с requirements.txt), чаще всего достаточно стандартного сценария деплоя без кастомного Dockerfile.
Базовые требования Bothost
Чтобы контейнер корректно работал с доменом/webhook на платформе:
приложение должно слушать 0.0.0.0, а не 127.0.0.1;
порт должен браться из переменной окружения PORT;
в настройках бота внутренний порт должен совпадать с портом, который реально слушает приложение;
после изменения порта/домена нужен повторный деплой.
Для веб-сервисов (FastAPI, Express и т.д.) это критично: иначе получите 502/504 даже при успешной сборке.
Минимальный шаблон для Python (бот + веб endpoint)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Приложение должно читать PORT из env и слушать 0.0.0.0
CMD ["python", "main.py"]
Минимальный шаблон для Node.js
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
# Приложение должно читать PORT из env и слушать 0.0.0.0
CMD ["node", "index.js"]
Минимальный шаблон для Go (multi-stage)
FROM golang:1.22-alpine AS builder
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /usr/local/bin/bot .
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
WORKDIR /app
# Бинарник кладём в /usr/local/bin/, а не в /app —
# иначе он будет скрыт bind mount'ом при деплое.
# Данные (БД и т.д.) храним в /app/data как обычно.
COPY --from=builder /usr/local/bin/bot /usr/local/bin/bot
RUN mkdir -p /app/data && chmod 777 /app/data
CMD ["/usr/local/bin/bot"]
Важно для Go и других компилируемых языков: на Bothost каталог /app
при запуске контейнера монтируется с исходниками из Git. Бинарник, скомпилированный
в образе и положенный в /app, будет скрыт этим mount'ом и не найдётся при старте.
Всегда кладите бинарники в /usr/local/bin/ или другой путь вне /app.
Нужные файлы не копируются в образ (COPY неполный).
Сборка успешна, но процесс сразу падает при старте (смотрите runtime-логи, а не только build-логи).
Cannot find module '/app/dist/...' при успешной сборке — часто из‑за WORKDIR /app и артефактов сборки (dist/, build/), которые не попадают в примонтированный с Git каталог /app. Решение: перенести WORKDIR в путь вне /app (например /usr/src/app), данные оставить в /app/data. Подробно: Справочник ошибок при деплое.
Чеклист перед деплоем
Dockerfile лежит в корне репозитория.
Команда запуска стартует долгоживущий процесс (а не одноразовый скрипт).
Для веб-приложения есть обработчик health (или понятный endpoint для проверки).