Эта статья для случаев, когда стандартной автонастройки недостаточно и вы хотите полностью контролировать сборку и запуск контейнера.
Когда нужен кастомный Dockerfile
Используйте свой Dockerfile, если вам нужно:
установить системные пакеты (apt, apk) или нестандартные зависимости;
делать многоэтапную сборку (build stage + runtime stage);
явно контролировать команду запуска (CMD/ENTRYPOINT);
запускать веб-приложение вместе с ботом на конкретном порту;
использовать собственную структуру проекта, которую автоопределение не покрывает.
Если ваш проект простой (например, Python-бот с requirements.txt), чаще всего достаточно стандартного сценария деплоя без кастомного Dockerfile.
Как включить свой Dockerfile
Положите файл Dockerfile в корень репозитория.
В форме создания или редактирования бота откройте блок «Дополнительные настройки».
Включите галочку «Использовать собственный Dockerfile».
После этого система будет собирать образ по вашему 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 для проверки).