Heroku Buildpack
在 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 将
- 安装最新的 crystal 版本。
- 通过 shards 安装项目依赖项。
- 以发布模式编译主要源文件。
- 使用
--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 它。欢迎贡献!