Развертывание FastAPI в Heroku с помощью реестра контейнеров Docker

Проблема

Я развертываю образ Docker с использованием FastAPI в Heroku, используя метод развертывания Docker Container Registry. Когда я развертываю контейнер, я получаю следующие журналы при запуске:

2024-06-03T20:57:32.222808+00:00 app[api]: Release v29 created by user [email protected]
2024-06-03T20:57:32.222808+00:00 app[api]: Deployed web (228f5e77d4e2) by user [email protected]
2024-06-03T20:57:45.637479+00:00 heroku[web.1]: Starting process with command `/bin/sh -c \"./start.sh\ \$\{PORT\}\"`
2024-06-03T20:57:46.235100+00:00 heroku[web.1]: Process exited with status 127
2024-06-03T20:57:46.185240+00:00 app[web.1]: /bin/sh: 1: ./start.sh 53182: not found
2024-06-03T20:57:46.255899+00:00 heroku[web.1]: State changed from starting to crashed

В пользовательском интерфейсе Heroku я вижу команду для запуска процесса heroku logs --app <app-name> --tailweb, и это правильно, поскольку эта команда работает локально. Я даже запустил контейнер и запустил web /bin/sh -c \"./start.sh\ \$\{PORT\}\", чтобы убедиться, что он будет работать, и он работает (это означает, что я могу подключиться к любой и всем конечным точкам API и получить ожидаемые результаты).

Детали

Докерфайл

FROM node:21 as ui-build

ENV PORT $PORT

WORKDIR /opt/ui

COPY ui .
RUN npm ci && npm run build

FROM python:3.11 as final-build

WORKDIR /opt/app
COPY --from=ui-build /opt/ui/build ./ui/build
COPY server server

RUN cd server && pip install -r requirements.txt

# Apparently Heroku doesn't respect the EXPOSE directive.
EXPOSE $PORT

WORKDIR /opt/app/server
COPY ./start.sh .

# Not sure why these commands are not working but the start.sh script seems to be going in the right direction.
# ENTRYPOINT [ "uvicorn", "api.app:app" ]
# CMD [ "--host", "0.0.0.0", "--port", $PORT ]
CMD "./start.sh ${PORT}"

Я использую действие gonuit/heroku-docker-deploy Github Action для создания и отправки образа Docker в реестр контейнеров Heroku. Вот как я использую это действие в своем рабочем процессе.

name: Build and Push Image

on:
  push:
    branches:
      - main

jobs:
  build-image:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Build and Push to Heroku
        uses: gonuit/[email protected]
        with:
          email: [email protected]
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: <app-name>

Ссылки

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

Эта последняя ссылка является официальной документацией Heroku по развертыванию с реестром контейнеров Docker, которую, насколько мне известно, я реализовал идентично.

Решение

Идеальным решением для меня было бы развертывание моего приложения с помощью Docker и Github Actions. Если мне нужно добавить файл Procfile или Heroku.yml в приложение, меня это устраивает, просто кажется, что это не нужно для метода развертывания, который я использую.

Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Развертывание модели машинного обучения с помощью Flask - Angular в Kubernetes
Kubernetes - это портативная, расширяемая платформа с открытым исходным кодом для управления контейнерными рабочими нагрузками и сервисами, которая...
Как создать PHP Image с нуля
Как создать PHP Image с нуля
Сегодня мы создадим PHP Image from Scratch для того, чтобы легко развернуть базовые PHP-приложения. Пожалуйста, имейте в виду, что это разработка для...
0
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Возможно, попробуйте изменить CMD на:

CMD ["/path/to/start.sh", "--port ${PORT}"]

Спасибо или предложение, но я получаю не ту же ошибку, а по сути ту же ошибку. ``` 2024-06-05T14:26:25.259174+00:00 Heroku[web.1]: Запуск процесса с помощью команды /bin/sh -c \[\ \"/opt/app/server/start.sh\",\ \ \37593\ \] 2024-06-05T14:26:25.883545+00:00 app[web.1]: /bin /sh: 1: [: /opt/app/server/start.sh,: неожиданный оператор 2024-06-05T14:26:25.951508+00:00 Heroku[web.1]: Процесс завершен со статусом 2 ``` Это предложение, в то время как лучшая практика Docker — это, по сути, то же самое, что и в исходном посте.

HopAlongPolly 05.06.2024 16:35
Ответ принят как подходящий

Мой ответ по сути представляет собой переработку этого ответа. https://stackoverflow.com/a/67747986/1464160

Правильный способ определения директивы CMD:

CMD [ "sh", "-c", "uvicorn api.app:app --host=0.0.0.0 --port=${PORT:-8000}" ]

Конечно, путь api.app:app и номер порта по умолчанию можно изменить на все, что вы хотите. Кажется, важной частью является наличие "sh", "-c" в начале директивы CMD.

Другие вопросы по теме