Эта статья для случаев, когда стандартной автонастройки недостаточно и вы хотите полностью контролировать сборку и запуск контейнера.
Когда нужен кастомный 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 /app/bot .
FROM alpine:3.20
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/bot .
CMD ["./bot"]
Типовые ошибки
Приложение слушает localhost вместо 0.0.0.0.
Порт захардкожен в коде, а не берётся из PORT.
CMD запускает не тот файл/бинарник.
Нужные файлы не копируются в образ (COPY неполный).
Сборка успешна, но процесс сразу падает при старте (смотрите runtime-логи, а не только build-логи).
Чеклист перед деплоем
Dockerfile лежит в корне репозитория.
Команда запуска стартует долгоживущий процесс (а не одноразовый скрипт).
Для веб-приложения есть обработчик health (или понятный endpoint для проверки).