You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

部署在Heroku的多Docker应用(Streamlit+FastAPI)连接错误求助

问题根源

  • Heroku容器部署中,多个dyno不在同一私有网络,无法通过本地Docker Compose的服务名(如api)进行内部通信
  • Heroku每个dyno仅允许绑定一个平台分配的PORT环境变量,硬编码端口会导致服务无法正常暴露

解决方案:合并前后端到单个容器(推荐)

将前后端及Nginx反向代理打包进一个容器,通过localhost实现内部通信,同时适配Heroku的端口规则。

步骤1:创建核心配置文件

  1. 根目录新建Dockerfile:
FROM python:3.9-slim

WORKDIR /app

# 安装Nginx和进程管理器
RUN apt-get update && apt-get install -y nginx supervisor && rm -rf /var/lib/apt/lists/*

# 复制并安装前后端依赖
COPY frontend/requirements.txt ./frontend/
COPY backend/requirements.txt ./backend/
RUN pip install --no-cache-dir -r frontend/requirements.txt
RUN pip install --no-cache-dir -r backend/requirements.txt

# 复制前后端代码
COPY frontend/ ./frontend/
COPY backend/ ./backend/

# 复制Nginx配置
COPY nginx.conf /etc/nginx/nginx.conf

# 复制Supervisord配置
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# 暴露Heroku分配的端口
EXPOSE ${PORT:-80}

# 启动进程管理器
CMD ["supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
  1. 根目录新建nginx.conf:
events {
    worker_connections 1024;
}

http {
    server {
        listen ${PORT:-80};

        # 根路径转发给Streamlit前端
        location / {
            proxy_pass http://localhost:8501;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }

        # /api路径转发给FastAPI后端
        location /api/ {
            proxy_pass http://localhost:8080/;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
        }
    }
}
  1. 根目录新建supervisord.conf:
[supervisord]
nodaemon=true

# 启动FastAPI后端
[program:backend]
command=uvicorn backend.api:app --host 0.0.0.0 --port 8080
directory=/app
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

# 启动Streamlit前端(无头模式适配容器环境)
[program:frontend]
command=streamlit run frontend/streamlit_app.py --server.port 8501 --server.address 0.0.0.0 --server.headless true
directory=/app
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

# 启动Nginx反向代理
[program:nginx]
command=nginx -g "daemon off;"
directory=/app
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

步骤2:修改前端请求地址

编辑frontend/streamlit_app.py,将原硬编码的host="http://api:8080/ask"替换为:

host = "http://localhost/api/ask"

步骤3:更新heroku.yml

替换为单服务配置:

build:
  docker:
    web: Dockerfile
run:
  web: supervisord -c /etc/supervisor/conf.d/supervisord.conf

步骤4:重新部署

git add .
git commit -m "Merge frontend/backend into single container with Nginx proxy"
git push heroku main
heroku open

替代方案:分拆为两个独立Heroku应用

若需保持前后端分离,可将后端单独部署为一个Heroku应用,然后:

  1. 在前端应用的Heroku环境变量中设置BACKEND_URL为后端应用的完整请求地址(如https://your-backend-app.herokuapp.com/ask)
  2. 修改streamlit_app.py从环境变量读取地址:
import os
host = os.getenv("BACKEND_URL", "http://api:8080/ask")

此方案需维护两个应用,且需在后端配置CORS解决跨域问题。

内容的提问来源于stack exchange,提问作者BioGeek

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 07:07:47