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

能否通过heroku.yml在Heroku上部署含ElasticSearch的容器化MVP应用?

问题描述

我有一个用于测试的MVP应用想要部署在Heroku平台上,该应用依赖的ElasticSearch已在docker-compose文件中定义。Heroku平台上最小规格的ElasticSearch插件每月需67美元,超出了我为这个MVP设定的预算。我正尝试将ElasticSearch与Web应用以容器化方式一同部署,但我查阅到的多进程部署指南均使用Dockerfile而非docker-compose,因此想咨询是否可以通过heroku.yml配置实现该需求?

以下是我的docker-compose.yml文件:

version: '3.6'
services:
  web:
    image: denoland/deno:latest
    container_name: my_app
    build: .
    ports:
      - 3001:3001
    environment:
     - DENO_ENV=local
     - ES_HOST=elasticsearch
     - DENO_PORT=3001
     - ELASTIC_URL=http://elasticsearch:9200
    volumes: 
      - .:/usr/src/app
    command: deno run --allow-net --allow-read --allow-env src/main.ts
    links: 
      - elasticsearch
    depends_on:
      - elasticsearch
    networks:
      - es-net
  elasticsearch:
    container_name: es-container
    image: docker.elastic.co/elasticsearch/elasticsearch:8.5.2
    volumes:
      - esdata:/usr/share/elasticsearch/data
    environment:
      - xpack.security.enabled=false
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - discovery.type=single-node
    logging:
      driver: none
    ports:
      - 9300:9300
      - 9200:9200
    networks:
      - es-net
volumes:
  esdata:
networks:
  es-net:
    driver: bridge
解决方案

可以通过heroku.yml配置实现将Web应用和ElasticSearch一同部署到Heroku,以下是具体步骤和注意事项:

1. 创建并配置heroku.yml

Heroku支持通过heroku.yml定义多进程部署,替代docker-compose的功能。创建heroku.yml文件,内容如下:

build:
  docker:
    web: Dockerfile
    elasticsearch: Dockerfile.es
run:
  web: deno run --allow-net --allow-read --allow-env src/main.ts
  elasticsearch: /usr/share/elasticsearch/bin/elasticsearch
release:
  image: web
  command:
    - echo "Release command (if needed)"

2. 为ElasticSearch创建单独的Dockerfile

由于Heroku需要为每个进程指定Dockerfile,你需要创建Dockerfile.es来构建ElasticSearch镜像:

FROM docker.elastic.co/elasticsearch/elasticsearch:8.5.2

# 设置环境变量
ENV xpack.security.enabled=false
ENV bootstrap.memory_lock=true
ENV ES_JAVA_OPTS=-Xms512m -Xmx512m
ENV discovery.type=single-node

# 暴露端口(Heroku内部网络会自动处理端口映射)
EXPOSE 9200 9300

# 启动命令
CMD ["/usr/share/elasticsearch/bin/elasticsearch"]

3. 调整Web应用的Dockerfile

确保你的Web应用根目录有Dockerfile,并调整环境变量适配Heroku的内部网络:

FROM denoland/deno:latest

WORKDIR /usr/src/app

# 复制应用代码
COPY . .

# 设置环境变量,ES_HOST在Heroku内部可直接用进程名elasticsearch
ENV DENO_ENV=production
ENV ES_HOST=elasticsearch
ENV DENO_PORT=${PORT}  # Heroku会自动分配端口,必须使用${PORT}变量
ENV ELASTIC_URL=http://elasticsearch:9200

# 启动命令
CMD ["deno", "run", "--allow-net", "--allow-read", "--allow-env", "src/main.ts"]

4. 启用Heroku容器栈

在终端执行以下命令,告诉Heroku使用容器部署:

heroku stack:set container

5. 部署应用

提交所有配置文件到Git,然后部署:

git add heroku.yml Dockerfile Dockerfile.es
git commit -m "Add multi-container deployment config"
git push heroku main

关键注意事项

  • 资源限制:Heroku免费/基础dyno资源有限,ElasticSearch需要一定内存,基础dyno(512MB)可能不足以稳定运行,建议至少使用标准dyno(1GB内存),同时需监控内存占用情况。
  • 数据持久化:Heroku的dyno是临时的,重启后本地存储会完全丢失。若需保留ES数据,需搭配外部存储服务(如AWS S3快照、Heroku附加存储),否则每次重启ES都会清空数据。
  • 端口配置:Web应用必须监听Heroku分配的${PORT}环境变量指定的端口,不能硬编码3001;ElasticSearch的端口在Heroku内部网络可直接使用9200/9300,无需映射到外部。
  • 网络连通性:Heroku内部dyno进程可直接通过进程名(如elasticsearch)互相访问,因此Web应用的ES_HOST设置为elasticsearch即可正常连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 10:20:31