如何通过Docker将一个传统的Rails应用部署到Heroku上

343 阅读2分钟

最近,我们致力于将一个传统的Rails应用程序部署到Heroku。Heroku支持的最低Ruby版本是2.7.6。运行旧版本的应用程序必须在部署前进行升级。值得庆幸的是,这个问题可以通过将应用部署为一个容器来解决。这篇文章解释了如何将一个应用程序容器化并部署到Heroku。

Dockerize应用程序

首先,我们需要为应用程序创建一个简单的Docker文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
FROM ruby:2.4.2

RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs

RUN mkdir /myapp
WORKDIR /myapp

COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock

RUN bundle install

COPY . /myapp

EXPOSE 3000
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

不同的Ruby应用会有不同的Dockerfile。这个例子是为运行Ruby 2.4.2的简单的Rails 4应用程序建立的,但它可以作为一个起点,为不同的使用情况进行修改。

有了这个Dockerfile,该应用就可以在本地运行:

1
docker build -t myapp . && docker run -it myapp

在运行该应用时,可能会出现错误。这在对传统应用进行容器化时很常见,通常有一些需要修复或升级的依赖项。

添加Heroku.yaml

一旦应用程序在本地运行,我们需要添加一个 heroku.yaml文件:

1
2
3
4
5
6
7
build:
  docker:
    web: Dockerfile
  config:
    RAILS_ENV: production
run:
  web: bundle exec rails server -b 0.0.0.0 -p $PORT

这告诉Heroku使用Dockerfile构建一个镜像,然后指定一个运行容器的过程。

请注意,网络进程运行在一个由下列文件指定的端口上 $PORT.这是必须的,因为Heroku在每次部署时都会动态地分配一个端口,网络进程必须听从这个端口。

构建应用程序和部署

在这一点上,我们可以通过用户界面或CLI建立一个新的Heroku应用。默认情况下,Heroku应用程序不运行容器构建。我们必须通过Heroku CLI改变堆栈:

1
heroku stack:set container

代码库和Heroku应用现在已经准备好了,我们可以推送到Heroku,开始构建和部署。

切换到DB上并复制环境变量

应用程序已经成功部署,并在Heroku上运行,但我们缺少重要的组件,如数据库。这里有两个选择:

  1. 将附加组件从传统的Heroku应用程序迁移到新的应用程序上
  2. 从传统应用中复制配置变量到新应用,重新使用传统应用的附加组件

选项一比较干净,可以让我们完全停用旧的应用程序。选项二更快。

我们建议从选项二开始,以验证新应用程序是否正常工作。然后逐步将附加组件迁移过去。