跳至内容
GitHub 仓库 论坛 RSS 新闻源

Heroku Buildpack

Brian J. Cardiff

在 2014 年底,第一个草案Heroku 为 crystal 创建的 buildpack。这真的很棒。能够在 Heroku 堆栈中运行 crystal 应用程序是一个非常棒的想法。

当我们继续开发语言、工具和标准库时,Crystal 周围的社区也随之壮大。许多人有兴趣尝试在 Heroku 上使用他们的 Crystal 驱动的 Web 应用程序。在 github 上为 buildpack 创建的网络图 非常大,尤其是对于一些简单的 bash 脚本来说!

然而,由于方法上的一些缺陷,buildpack 无法跟上 Crystal 最新版本的更新;但这现在已经解决了!太棒了!

虽然现在正在努力开发 Web 框架,但我们想分享使用 Crystal buildpack 在 Heroku 中部署 Web 应用程序的非常基本步骤,而无需任何额外的依赖项。

创建 Crystal 项目

假设您已经安装了 crystal

使用 crystal init app 来创建应用程序。

$ crystal init app heroku101
    create  heroku101/.gitignore
    create  heroku101/LICENSE
    create  heroku101/README.md
    create  heroku101/.travis.yml
    create  heroku101/shard.yml
    create  heroku101/src/heroku101.cr
    create  heroku101/src/heroku101/version.cr
    create  heroku101/spec/spec_helper.cr
    create  heroku101/spec/heroku101_spec.cr
Initialized empty Git repository in /Users/bcardiff/Work/Manas/crystal/heroku101/.git/

$ cd heroku101/

注意:在本文的剩余部分中,所有命令都是从 heroku101/ 目录执行的。

shard.yml 文件将项目的名称声明为 heroku101。这将被 buildpack 用于确定要编译的主要源文件:./src/heroku101.cr

$ cat shard.yml
name: heroku101
version: 0.1.0
...

要创建简单的 http 服务器,请编辑 src/heroku101.cr 文件并添加以下内容

# file: src/heroku101.cr
require "http/server"

bind = "0.0.0.0"
port = 8080

server = HTTP::Server.new(bind, port) do |context|
  context.response.content_type = "text/plain"
  context.response << "Hello world, got #{context.request.path}"
end

puts "Listening on http://#{bind}:#{port}"
server.listen

要构建和运行程序

$ crystal src/heroku101.cr
Listening on http://0.0.0.0:8080

在您的浏览器中打开 http://0.0.0.0:8080

要停止服务器,只需通过按 Ctrl+C 终止进程。

Herokufy 它

现在项目对 Heroku 一无所知。要开始使用,首先需要注册 Heroku 应用程序。最简单的方法是通过 Heroku 工具带

$ heroku create --buildpack https://github.com/crystal-lang/heroku-buildpack-crystal.git
Creating app... done, ⬢ sleepy-thicket-16179
Setting buildpack to https://github.com/crystal-lang/heroku-buildpack-crystal.git... done
https://sleepy-thicket-16179.herokuapp.com/ | https://git.heroku.com/sleepy-thicket-16179.git

上面的命令将生成一个随机的应用程序名称。查看 文档,以便从一开始就为您的应用程序命名。

在部署之前,我们需要做一个小小的更改。Heroku 随机分配一个端口号供应用程序使用。感谢 buildpack,这将在运行应用程序时以 --port 选项的形式告知。

因此,在 src/heroku101.cr 的开头添加一个 require "option_parser",并使用以下方法覆盖 port 变量的默认值

OptionParser.parse! do |opts|
  opts.on("-p PORT", "--port PORT", "define port to run server") do |opt|
    port = opt.to_i
  end
end

完整的 src/heroku101.cr 应该是

# file: src/heroku101.cr
require "http/server"
require "option_parser"

bind = "0.0.0.0"
port = 8080

OptionParser.parse! do |opts|
  opts.on("-p PORT", "--port PORT", "define port to run server") do |opt|
    port = opt.to_i
  end
end

server = HTTP::Server.new(bind, port) do |context|
  context.response.content_type = "text/plain"
  context.response << "Hello world, got #{context.request.path}"
end

puts "Listening on http://#{bind}:#{port}"
server.listen

要使用 --port 选项构建和运行

$ crystal src/heroku101.cr -- --port 9090
Listening on http://0.0.0.0:9090

或者在本地构建一个优化的版本,并通过以下方法执行它

$ crystal build src/heroku101.cr --release
$ ./heroku101
Listening on http://0.0.0.0:8080
^C
$ ./heroku101 --port 9090
Listening on http://0.0.0.0:9090
^C

部署!

当您准备使用您的应用程序投入生产时,只需使用 git push heroku master 以通常的方式部署它。

$ git push heroku master
Counting objects: 22, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (17/17), done.
Writing objects: 100% (22/22), 2.85 KiB | 0 bytes/s, done.
Total 22 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Fetching set buildpack https://github.com/crystal-lang/heroku-buildpack-crystal.git... done
remote: -----> Crystal app detected
remote: -----> Installing Crystal (0.17.3 due to latest release at https://github.com/crystal-lang/crystal)
remote: -----> Installing Dependencies
remote: -----> Compiling src/heroku101.cr (auto-detected from shard.yml)
remote:
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote:
remote: -----> Compressing...
remote:        Done: 289.4K
remote: -----> Launching...
remote:        Released v3
remote:        https://sleepy-thicket-16179.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy.... done.
To https://git.heroku.com/sleepy-thicket-16179.git
 * [new branch]      master -> master

buildpack 将

  1. 安装最新的 crystal 版本。
  2. 通过 shards 安装项目依赖项。
  3. 以发布模式编译主要源文件。
  4. 使用 --port 选项运行 Web 服务器进程。

指定 crystal 版本

如果要使用不同的 Crystal 版本,请创建一个 .crystal-version 文件,其中包含所需版本,遵循 crenv 的约定。

$ echo '0.17.1' > .crystal-version

提交 .crystal-version 中的更改并部署。

$ git push heroku master
Counting objects: 3, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 301 bytes | 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Fetching set buildpack https://github.com/crystal-lang/heroku-buildpack-crystal.git... done
remote: -----> Crystal app detected
remote: -----> Installing Crystal (0.17.1 due to .crystal-version file)
remote: -----> Installing Dependencies
remote: -----> Compiling src/heroku101.cr (auto-detected from shard.yml)
...

您现在将注意到 (0.17.1 due to .crystal-version file) 说明。

当您准备好升级到最新的 crystal 版本时,更新文件内容或直接将其删除并重新部署。

给我看看代码!

https://github.com/bcardiff/sample-crystal-heroku101 中查找所有使用的示例源代码。

要为 crystal buildpack 做出贡献,只需 fork 它。欢迎贡献!