Облачная платформаEvolution

Требования к Docker-образу в Container Apps


При создании файла образа нужно учитывать среду выполнения и требования для успешного деплоя образа в Container Apps.

Требования для деплоя образа

Чтобы деплой завершился успешно, образ должен удовлетворять обязательным требованиям. Также, желательно, чтобы образ соответствовал и рекомендованным требованиям. Если рекомендованные требования не будут соблюдены, приложение будет развернуто, но его работа может быть нестабильна.

Обязательные требования

  • Язык программирования — любой.

  • Доступный формат образа — Docker Image Manifest V 2.

  • Docker-образ должен имплементировать любой тип веб-сервера и определять номер порта, на котором контейнер будет принимать запросы.

  • Docker-образ должен быть собран под плафторму linux/amd64.

    Пока не поддерживается запуск Docker-oбразов, собранных под другие платформы. При использовании Apple Mac с процессором серии М образ по умолчанию собирается под платформу arm64.

    При работе на Mac добавляйте в команду скачивания и сборки образа параметр --platform linux/amd64.

    docker buildx build \
    --platform linux/amd64,linux/arm64 \
    --tag <registry_name>.cr.cloud.ru/<repository>:<tag> \
    --push .

    где:

    • <registry_name> — название реестра;

    • <repository> — название репозитория;

    • <tag> — название тега.

  • В Docker-образе не должны использоваться настройки для подключения томов (volumes) к контейнеру.

    Образ на основе Dockerfile, который содержит инструкцию VOLUME, не может использоваться для развертывания контейнера.

  • Образ должен быть загружен в Artifact Registry в том же проекте, что и Container Apps.

  • Если вы планируете делать образ доступным другим пользователям, он должен быть загружен в публичный репозиторий.

  • Если образ создается для использования в Container Services, то приложение должно слушать 0.0.0.0:$PORT. При этом переменная окружения PORT не может быть переопределена.

    import os
    import uvicorn
    if __name__ == "__main__":
    port = int(os.getenv("PORT", "8080"))
    uvicorn.run("app:app", host="0.0.0.0", port=port)
  • Если образ создается для использования в Container Jobs, процесс должен завершаться с exit code 0 при успехе.

  • Нужно учитывать, что задание, которое развернется из образа в Container Jobs, укладывается в таймаут 3 600 секунд и учитывает лимит — не более 5 параллельных запусков.

  • Если контейнер запускается от имени root-пользователя, то при создании контейнера в Container Apps необходимо включить привилегированный режим, иначе контейнер не запустится.

  • Если контейнер запускается не от имени root-пользователя, то в Dockerfile укажите команду создания пользователя с идентификатором 1000 и назначьте ему права на пользовательскую директорию:

    RUN addgroup -g 1000 appuser \
    && adduser -u 1000 -G appuser -s /bin/sh -D appuser
    RUN chown -R 1000 /mydirectory

    где /mydirectory — название директории в вашем приложении.

    По умолчанию контейнеры в Container Apps запускаются от имени пользователя с идентификатором (UID) 1000, если не включен привилегированный режим.

  • Docker-образ не должен находиться в карантине из-за наличия уязвимостей в реестре Artifact Registry, иначе его будет невозможно использовать для развертывания контейнера.

Рекомендованные требования

  • В образе есть HTTP-эндпоинт для health-проверок (/health, /ready, /ping), который помогает отслеживать состояния приложения в контейнере. При успешной health-пробе возвращается ответ «200 OK».

  • В вашем образе есть обработка сигнала SIGTERM. Это поможет корректно завершить все задачи перед завершением задания или остановкой контейнера.

    import signal, sys
    def handle_sigterm(signum, frame):
    # дождаться завершения активных запросов, закрыть пулы соединений с БД
    graceful_stop()
    sys.exit(0)
    signal.signal(signal.SIGTERM, handle_sigterm)
  • Используйте быстрый «холодный» старт (желательно — 1–3 секунды), чтобы минимизировать задержку при первом обращении.

  • При настройке логирования, записывайте их в стандартные потоки вывода — stdout, stderr, желательно в формате JSON и без буферизации. Это упростит парсинг и поиск в сервисе логирования, а также не будет задержки в появлении логов.

  • Не храните данные внутри контейнеров, используйте внешние хранилища.

  • Используйте минималистичный базовый образ без лишних утилит для более быстрого «холодного» старта.

  • Используйте явные, иммутабельные теги для разных версий образов, чтобы точно понимать в чем отличия.

Требования для размещения образа в «Маркетплейсе»

Если вы планируете загружать образ на витрину «Маркетплейса», то он должен удовлетворять дополнительным требованиям:

  • В образе пропишите OCI-метки: title, description, vendor, version, source, licenses.

    LABEL org.opencontainers.image.title="My Awesome App"
    LABEL org.opencontainers.image.description="Описание приложения для витрины маркетплейса"
    LABEL org.opencontainers.image.vendor="Имя разработчика / компании"
    LABEL org.opencontainers.image.version="1.0.0"
    LABEL org.opencontainers.image.licenses="Apache-2.0"
    LABEL org.opencontainers.image.url="https://docs.myapp.com"
    LABEL org.opencontainers.image.source="https://gitverse.ru/user/repo"
    LABEL org.opencontainers.image.revision="<git-sha>"
    LABEL org.opencontainers.image.created="2026-07-28T15:00:00Z"
  • Подготовьте манифест приложения и опишите в нем:

    • Переменные окружения — укажите всю конфигурацию приложения.

    • Минимально необходимые ресурсы — CPU и RAM.

    • Требуется ли подключения к другим сервисам — например «нужен S3-бакет» или «нужна БД PostgreSQL».

    • Тип рабочей нагрузки — Container Services или Container Jobs

Пример Docker-файла

Пример Docker-файла, который удовлетворяет всем обязательным требованиям:

dockerfile
# ---------- build stage ----------
FROM --platform=linux/amd64 python:3.12-slim AS builder
WORKDIR /build
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/build/deps -r requirements.txt
# ---------- runtime stage ----------
FROM --platform=linux/amd64 python:3.12-slim
# метаданные для витрины маркетплейса
LABEL org.opencontainers.image.title="My Awesome App" \
org.opencontainers.image.description="ETL-задание для синхронизации данных" \
org.opencontainers.image.vendor="ACME Ltd." \
org.opencontainers.image.version="1.0.0" \
org.opencontainers.image.licenses="Apache-2.0" \
org.opencontainers.image.source="https://gitverse.ru/acme/my-awesome-app"
# логи без буферизации, сразу в stdout
ENV PYTHONUNBUFFERED=1 \
PYTHONDONTWRITEBYTECODE=1 \
PYTHONPATH=/app/deps
# пользователь с UID 1000 — требование среды выполнения
RUN groupadd -g 1000 appuser \
&& useradd -u 1000 -g appuser -m -s /bin/sh appuser
WORKDIR /app
COPY --from=builder /build/deps /app/deps
COPY --chown=1000:1000 ./src /app
RUN chown -R 1000:1000 /app
USER appuser
# декларативно; фактический порт платформа передает в $PORT
EXPOSE 8080
# exec-форма, чтобы SIGTERM дошел до процесса
CMD ["python", "main.py"]