ゼロからの slug の作成
最終更新日 2023年06月14日(水)
Table of Contents
この記事では、制御するマシン上で slug をゼロから作成した後、Heroku アプリでそれらの slug をアップロードおよび実行する方法について説明します。これを行うのが適切なのは、slug に含める必要があるものを完全に制御できる場合です。
ただし、ほとんどの用途では、Platform API の build
リソースを使用してソースコードを slug に変換することをお勧めします。ビルドリソースを使用すると、ゼロから slug を作成するよりも通常は簡単であり、標準の Heroku slug コンパイラと標準の Heroku buildpack を使用して slug が生成されます。標準ビルドパイプラインを使用して生成された slug の方が、Heroku と互換性があって正しく動作する可能性が高くなります。Platform API とビルドリソースを使用して slug を作成する方法についての詳細は、「Build and release using the API」(API を使用したビルドとリリース) を参照してください。
標準の buildpack と slug のコンパイルプロセスを使用しつつ複数のアプリで slug を再利用する場合は、「PlatformAPI を使用した slug のコピー」を参照してください。
slug とスタック
Heroku の slug は、特定のスタックに固有です。API を介して slug を作成するときに、必要に応じてスタックを指定できます。
slug を作成するときは、どの Heroku スタックに slug をデプロイすることを計画しているかに注意する必要があります。slug に含まれるすべてのバイナリが、ターゲットにしている Heroku スタックの基盤となる Linux バージョンと互換性があることを確認してください。
slug の作成
slug は、実行可能な Heroku アプリケーションを ./app
ディレクトリに格納して gzip 圧縮した tar ファイルです。slug では ./app
の外にもファイルを含めることができますが、それらのファイルは Heroku での解凍時に無視されます。slug サイズは slug サイズの制限を超えてはなりません。
この例では、Node.js、Ruby、または Go アプリのいずれかを含む slug をゼロから作成する方法を示します。すべての slug でコンテンツは ./app
ディレクトリに入れる必要があるため、まず次のディレクトリを作成および入力します。
$ mkdir app
$ cd app
次に、実際のアプリと、必要な依存関係を追加します。詳細は、選択したアプリとフレームワークによって異なります。
このガイドに従っている場合は、1 つの言語を選択し、その言語の手順のみを完了してください。
Node.js
x64 Linux 用の Node.js ランタイムを入手します。
$ curl http://nodejs.org/dist/v0.10.20/node-v0.10.20-linux-x64.tar.gz | tar xzv
次に、web.js
という名前のファイルにアプリのコードを追加します。
// Load the http module to create an http server
var http = require('http');
// Configure HTTP server to respond with Hello World to all requests
var server = http.createServer(function (request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.end("Hello World\n");
});
var port = process.env.PORT;
// Listen on assigned port
server.listen(port);
// Put a friendly message on the terminal
console.log("Server listening on port " + port);
Ruby
Ruby プロジェクトでは、事前コンパイルされた自己完結型ランタイムを提供していないため、Heroku Ruby チームによって buildpack 用に作成されたものを使用します。これは https://heroku-buildpack-ruby.s3.amazonaws.com/ruby-2.0.0.tgz
から入手できます。
Ruby ランタイムを入手します。
$ mkdir ruby-2.0.0
$ cd ruby-2.0.0
$ curl https://heroku-buildpack-ruby.s3.amazonaws.com/ruby-2.0.0.tgz | tar xzv
$ cd ..
ごく単純な Ruby アプリを server.rb
に追加します。
require 'webrick'
server = WEBrick::HTTPServer.new :Port => ENV["PORT"]
server.mount_proc '/' do |req, res|
res.body = "Hello, world!\n"
end
trap 'INT' do
server.shutdown
end
server.start
Go
Go slug の作成は驚くほど簡単です。理由は、go build
コマンドでは、追加の実行時依存関係をバンドルする必要がないスタンドアロンの実行可能ファイルが生成されるからです。注意事項の 1 つとして、Heroku が使用するものと同じアーキテクチャ (linux/amd64) で slug を作成しない場合、実行可能ファイルをクロスコンパイルする必要があります。クロスコンパイル用 Go ツールチェーンの設定は比較的簡単です。
web.go
でアプリを追加します。
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", hello)
fmt.Println("listening...")
err := http.ListenAndServe(":"+os.Getenv("PORT"), nil)
if err != nil {
panic(err)
}
}
func hello(res http.ResponseWriter, req *http.Request) {
fmt.Fprintln(res, "hello, world")
}
次に、Heroku で動作する実行可能ファイルをビルドします。
GOARCH=amd64 GOOS=linux go build web.go
slug アーカイブを作成する
app
の親ディレクトリに再び変更し、./app
を圧縮して (./
プレフィックスは重要) slug を作成します。
$ cd ..
$ tar czfv slug.tgz ./app
Heroku では現在、tar ファイルの互換性に制限があります。slug アーカイブを作成するときは、(bsdtar ではなく) GNU Tar を使用してください。tar のバージョンは tar --version
で確認できます。
GNU Tar を使用して作成した slug を Heroku で起動できない場合は、遠慮なくサポートチケットを開いて問題のデバッグの支援を受けてください。
プラットフォームへの公開
この slug を実行する Heroku アプリの作成から始めます。
$ heroku create example-app
Creating example-app... done
http://example-app-1234567890ab.herokuapp.com/ | git@heroku.com:example.git
プラットフォームへの slug の公開は 2 段階のプロセスです。まず、アプリに新しい slug を割り当てるよう Heroku にリクエストします。slug を割り当てるときは、process_types
パラメータを使用して、作成中の slug で使用できる実行可能コマンドのリストを指定します。slug の整合性を保証するために、checksum
パラメータで slug のチェックサムを指定することも推奨されます。
process_types
パラメータの内容は、Heroku にプッシュされるアプリに通常含まれる Procfile に含まれるものと同様です。dyno で slug が起動されるときに Procfile は解析されません。代わりにビルドシステムによって解析され、slug の作成時にその内容が渡されます。
process_types
パラメータは、先に作成した slug の種類によって異なります。
- Node.js:
{ "web": "node-v0.10.20-linux-x64/bin/node web.js" }
- Ruby:
{"web": "ruby-2.0.0/bin/ruby server.rb"}
- Go:
{"web":"./web"}
-n
フラグは、api.heroku.com
の資格情報を ~/.netrc
から 読み取るよう curl
に指示し、Authorization
ヘッダーを自動的に設定します。その他の認証オプションについては、Platform API スターターガイドを参照してください。
$ curl -X POST \
-H 'Content-Type: application/json' \
-H 'Accept: application/vnd.heroku+json; version=3' \
-d '{"process_types":{"web":"node-v0.10.20-linux-x64/bin/node web.js"}}' \
-n https://api.heroku.com/apps/example/slugs
{
"blob":{
"method": "put",
"url": "https://s3-external-1.amazonaws.com/herokuslugs/heroku.com/v1/d969e0b3-9892-4567-7642-1aa1d1108bc3?AWSAccessKeyId=..."
},
"commit":null,
"created_at":"2013-10-08T22:04:13Z",
"id":"d969e0b3-9892-3113-7653-1aa1d1108bc3",
"process_types":{
"web":"node-v0.10.20-linux-x64/bin/node web.js"
},
"updated_at":"2013-10-08T22:04:13Z"
}
slug 作成リクエストでは blob URL は渡されないことに注意してください。代わりに slug 作成応答で返され、その URL を使用してバイナリ slug アーティファクトを PUT
することができます。
2 番目の手順では、前の応答で得られた blob
URL を使用して slug.tgz
をアップロードし、プラットフォームで使用できるようにします。
$ curl -X PUT \
-H "Content-Type:" \
--data-binary @slug.tgz \
"https://s3-external-1.amazonaws.com/herokuslugs/heroku.com/v1/d969e0b3-9892-4567-7642-1aa1d1108bc3?AWSAccessKeyId=..."
slug のリリース
以上で、slug は Heroku にアップロードされましたが、まだアプリにリリースされていません。この slug の実行を実際に開始するには、その ID を /apps/:app/releases
エンドポイントに POST
します。
$ curl -X POST \
-H "Accept: application/vnd.heroku+json; version=3" \
-H "Content-Type: application/json" \
-d '{"slug":"d969e0b3-9892-3113-7653-1aa1d1108bc3"}' \
-n https://api.heroku.com/apps/example/releases
{
"created_at":"2013-10-08T16:09:54Z",
"description":"deploy",
"id":"a0ff4658-ec55-4ee2-96a9-8c67287a807e",
"slug":{
"id":"d969e0b3-9892-3113-7653-1aa1d1108bc3"
},
"updated_at":"2013-10-08T16:09:54Z",
"user":{
"email":"jane@doe.com",
"id":"2930066e-c315-4097-8e88-56126f3d4dc1"
},
"version":3
}
同じ slug を複数のアプリにリリースできます。これは、より高度なデプロイワークフローに使用できます。
これで、アプリのリリース履歴で新しいリリースを確認できるようになります。
$ heroku releases --app example
=== example Releases
v3 deploy jane@doe.com 2013/10/08 16:09:54 (~ 1m ago)
...
ブラウザでアプリを表示し、新しくリリースされた slug を使用して実行されていることを確認します。
$ heroku open --app example