在 Heroku 上部署 Docker 容器 (以 One-API 为例)

在 Heroku 上部署 Docker 容器 (以 One-API 为例)

所谓诚其意者 毋自欺也

近期,我发现之前使用 Vercel 搭建的 RSSHub 服务版本过时,尝试更新部署新版本时却在 Vercel 上持续遇到故障。在寻找替代方案的过程中,我了解到可以通过 GitHub 学生包等途径获取 Heroku 的使用额度(例如当时发现的 $312 赠金),并且 Heroku 平台原生支持运行 Docker 容器,这为部署各种应用提供了极大的灵活性。

Heroku 部署方式概览

Heroku 主要提供三种部署应用的方式:

  1. Heroku Git: 通过 Heroku 提供的 Git 远程仓库部署代码,Heroku 使用 Buildpacks 自动构建和运行应用。
  2. GitHub: 直接连接 GitHub 仓库,实现自动或手动部署。
  3. Container Registry: 将构建好的 Docker 镜像推送到 Heroku 的容器注册表进行部署。

本文将重点介绍第三种方法:使用 Heroku Container Registry 部署预先构建好的 Docker 镜像

Heroku部署选项

下面,我将以部署 One-API(一个 API 管理和分发项目)为例,详细说明在 Heroku 上部署 Docker 容器的具体步骤。

环境与准备

  • 操作系统: 示例使用 Ubuntu 22.04,但步骤适用于其他支持 Docker 和 Heroku CLI 的系统。
  • 必要工具:
    • Docker (已安装并运行)
    • Heroku CLI (Heroku 命令行工具)
  • Heroku 账号: 你需要一个 Heroku 注册账号。
  • 待部署的 Docker 镜像:
    • 你需要一个已经构建好的、可以在本地成功运行的 Docker 镜像。本文以本地已有的 calciumion/new-api:latest 镜像为例。
    • 关键要求: 该 Docker 镜像启动的应用 必须 监听由 Heroku 运行时动态注入的 $PORT 环境变量所指定的端口号。大多数 Web 框架能自动识别或可以配置为使用此环境变量。同时,建议在 Dockerfile 中使用 EXPOSE $PORT 或具体的端口号(如果你的应用固定监听某个端口,但监听 $PORT 是最推荐的做法)。

我的本地 Ubuntu 环境,可以看到 calciumion/new-api 镜像已存在:

Ubuntu环境

部署步骤

1. 安装 Heroku CLI

Heroku CLI 是与 Heroku 平台交互的主要工具。

  • 对于 Debian/Ubuntu 系统,可以使用官方脚本安装:

    1
    curl [https://cli-assets.heroku.com/install-ubuntu.sh](https://cli-assets.heroku.com/install-ubuntu.sh) | sh
  • 对于 macOS, Windows 或其他 Linux 发行版,请参考 Heroku 官方文档 进行安装。

安装完成后,可以通过 heroku --version 验证安装。

2. 登录 Heroku

在终端执行登录命令,它会打开浏览器引导你完成登录授权过程:

1
heroku login

3. 创建 Heroku 应用

在部署之前,你需要在 Heroku 上创建一个应用。应用名称 (<your-app-name>) 在 Heroku 全平台上必须是唯一的。

1
2
# 将 <your-app-name> 替换为你想要的应用名称,例如 newapi0819
heroku create newapi0819

成功后,Heroku 会返回应用的访问 URL 和 Git 仓库 URL。

4. 设置应用堆栈为 Container (关键步骤)

默认情况下,Heroku 应用使用 Buildpack 堆栈来构建源代码。因为我们要部署的是预构建的 Docker 镜像,所以需要将应用的堆栈(Stack)明确设置为 container

1
2
# 将 newapi0819 替换为你的应用名称
heroku stack:set container -a newapi0819

5. 登录 Heroku Container Registry

你需要登录到 Heroku 自己的 Docker 镜像注册表,才能推送镜像:

1
heroku container:login

6. 标记 (Tag) 本地 Docker 镜像

将你本地准备好的 Docker 镜像,按照 Heroku Container Registry 的格式进行标记。格式为:registry.heroku.com/<app-name>/<process-type>

  • <app-name>: 你在第 3 步创建的应用名称 (例如 newapi0819)。
  • <process-type>: 定义这个容器扮演的角色。对于处理 Web 请求的应用,通常使用 web。其他类型如 worker 用于后台任务。

假设你的本地镜像是 calciumion/new-api:latest,应用名为 newapi0819,进程类型为 web

1
docker tag calciumion/new-api:latest [registry.heroku.com/newapi0819/web](https://registry.heroku.com/newapi0819/web)

7. 推送 Docker 镜像到 Heroku

将标记好的镜像推送到 Heroku Container Registry:

1
docker push [registry.heroku.com/newapi0819/web](https://registry.heroku.com/newapi0819/web)

推送过程可能需要一些时间,具体取决于镜像大小和网络速度。

8. 发布 (Release) 镜像到应用

推送完成后,你需要执行 release 命令,告诉 Heroku 使用这个新推送的镜像来运行你的应用。

1
2
# 发布 web 进程类型的容器
heroku container:release web -a newapi0819

Heroku 会拉取镜像并在新的 Dyno(Heroku 的容器实例)中启动它。

9. 验证部署

部署完成后,可以通过以下方式验证:

  • 查看实时日志:

    1
    heroku logs --tail -a newapi0819

    观察是否有错误信息,确认应用是否成功启动并监听在 $PORT 上。

  • 打开应用 URL:

    1
    heroku open -a newapi0819

    或者直接在浏览器中访问 https://newapi0819.herokuapp.com (将 newapi0819 替换为你的应用名)。

注意事项

  1. 环境变量: 如果你的 Docker 应用依赖环境变量(例如数据库连接字符串、API 密钥等),你需要在 Heroku 应用的设置 (Settings) -> “Config Vars” 部分进行配置。Heroku 会将这些 Config Vars 作为环境变量注入到运行的容器中。不要 将敏感信息硬编码在 Docker 镜像里。
  2. 短暂文件系统与数据持久化: Heroku 的 Dyno 文件系统是 短暂的 (Ephemeral)。这意味着每次 Dyno 重启(至少每天发生一次,或在部署、配置更改、平台维护、崩溃后),所有写入容器本地文件系统的更改都会丢失。如果你的应用需要持久化存储数据(如数据库内容、用户上传的文件等),必须 使用 Heroku Add-ons(例如 Heroku Postgres, Heroku Redis)或外部的云数据库/云存储服务(如 AWS RDS, AWS S3)。
  3. 监听 $PORT: 再次强调,部署到 Heroku 的 Web 应用 必须 监听 $PORT 环境变量指定的端口。Heroku 的路由层会将外部的 80/443 端口请求路由到你的容器内部监听的这个动态端口上。
  4. Heroku 赠金/额度: 如果你通过 GitHub 学生包或其他途径获得了 Heroku 额度,请注意其使用规则。例如,文中提到的 $13/月使用上限和 24 个月有效期。Heroku 的定价和优惠政策可能会变化,请参考 Heroku 官方文档获取最新信息。免费套餐通常也有一定的限制(如 Dyno 休眠机制)。

通过以上步骤,你应该能够成功地将你的 Docker 容器化应用部署到 Heroku 平台上。

  • Title: 在 Heroku 上部署 Docker 容器 (以 One-API 为例)
  • Author:
  • Created at : 2024-07-21 13:29:03
  • Updated at : 2025-04-29 19:17:00
  • Link: https://xblog.aptzone.cc/2024/07/21/在Heroku上部署Docker容器/
  • License: All Rights Reserved © 凡
Comments