· Heroku golang Go

HerokuでGoアプリケーションを動かしたい

  • このエントリーをはてなブックマークに追加

はじめに

Goで作ったWebアプリケーションをHerokuにデプロイする手順を書いておこうと思います。最初はDockerを使わずにデプロイし、あとでDocker化してみようと思います。

セットアップ

Herokuのコマンドラインツールのインストール

Herokuのコマンドラインツールをインストールしましょう

こちらから各環境のコマンドラインツールをインストールできます。

そしてツールをインストールしたら、

% heroku login

でログインしておきます。

Heroku側にnew appを作成

HerokuにデプロイするためにHerokuに新規アプリを作成しましょう

% heroku apps:create heroku-with-go --buildpack heroku/go

--buildpackはHeroku上でビルドするのに必要ですのでGo用のbuildpackを設定しておきます。オープンソースですので、こちらで見ることが出来ます。

新規アプリが作成されたかブラウザで確認してみます。

% heroku open --app heroku-with-go

Goアプリケーション作成してからHerokuデプロイまで

Goアプリケーションを準備するのですが、Getting Started on Heroku with Goには、Githubからサンプルをクローンしてきて、デプロイしてみようみたな感じですが、ここではこのサンプルは使わず、1から自分で作ってみようと思います。

プロジェクト(ディレクトリ)作成

$GOPATH にWebアプリケーションプロジェクトを作成しましょう。 今回はheroku-with-goディレクトリを作成しました。

$ mkdir $GOPATH/src/github.com/kwmt/heroku-with-go

heroku-with-go にWebアプリを書いて行きましょう。

main.go作成

とりあえず、簡単のためにURLのPathを表示するだけのアプリを書いてみます。(環境変数PORTを取得できるようにする必要があります)

package main

import (
	"fmt"
	"log"
	"net/http"
	"os"
)

func main() {
	port := os.Getenv("PORT")
	if port == "" {
		log.Fatal("$PORT must be set")
	}

	http.HandleFunc("/", handler)
	http.ListenAndServe(":"+port, nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %q", r.URL.Path[1:])
}

Procfile作成

Herokuで動かすには、Procfileというファイルが必要ですので、それも作成しましょう。(Procfileについては、こちらに詳細があります)

Procfileには、Heroku上で自分のアプリケーションを動かすためのコマンドを記述しますので、たとえば次のように記述します。

web: heroku-with-go

heroku-with-goというのは、最初に作成したディレクトリです。つまり、ここでは$GOPATH/src/github.com/kwmt/heroku-with-goheroku-with-goの部分です。 下記でBuildpackというのを設定するのですが、そのなかで自動的にGoプログラムをgo buildして go install$GOPATH/binにインストールされる仕組みになっていますので、herokuプロジェクト名を書いて置くといいでしょう。ソースはこのあたりを参照すると良いかもしれません。

vendor.json作成

vendor/vendor.jsonファイルを作成しましょう。これは依存ライブラリを使っていなくても必須のようです。簡単でいいので作成しておきます。

{
	"rootPath": "github.com/kwmt/heroku-with-go"
}

簡単といってもrootPathだけは必要のようです。{}だけだと

-----> Go app detected
-----> Checking vendor/vendor.json file.
 !!    The 'rootPath' field is not specified in 'vendor/vendor.json'.
 !!    'rootPath' must be set to the root package name used by your repository.
 !!    Recent versions of govendor add this field automatically, please upgrade
 !!    and re-run 'govendor in

と怒られてしまいます。

また、vendor/vendor.jsonがないときにherokuにpushすると、次のようにdeployに失敗してしまいます。

% git push heroku master
Counting objects: 15, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (15/15), 1.64 KiB | 0 bytes/s, done.
Total 15 (delta 2), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote: 
remote: -----> Failed to detect app matching https://github.com/heroku/heroku-buildpack-go.git buildpack
remote:        More info: https://devcenter.heroku.com/articles/buildpacks#detection-failure
remote: 
remote:  !     Push failed
remote: Verifying deploy...
remote: 
remote: !	Push rejected to heroku-with-go.
remote: 
To https://git.heroku.com/heroku-with-go.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/heroku-with-go.git'

Herokuにデプロイ

ここまでで最低限の準備ができましたので、Herokuにデプロイしてみます。下記のようにherokuのgitレポジトリにpushするだけです。

% git push heroku master

heroku は新規アプリ作ったとき(heroku createしたとき)に自動的に作成されています。git remoteコマンドで確認できます。

% git remote -v
heroku	https://git.heroku.com/heroku-with-go.git (fetch)
heroku	https://git.heroku.com/heroku-with-go.git (push)

ちゃんとデプロイされたかブラウザで確認してみます。

% heroku open world

とすると

と期待どうりになっていることがわかるかと思います。

Dockerを使いたい

前提として

上記ディレクトリをコピーして名前heroku-with-dockerと少し変更して作業を進めています

cp -r $GOPATH/src/github.com/kwmt/heroku-with-go $GOPATH/src/github.com/kwmt/heroku-with-docker

heroku-container-toolsプラグインをインストールしておきます。(このプラグインはdeprecatedなので本当は使いたくないのですが。。)

% heroku plugins:install heroku-container-tools 

app.json

下記のようなapp.jsonファイルを作成します。

{
  "name": "Heroku with Docker",
  "description": "Sample",
  "image": "heroku/go:1.6",
  "mount_dir": "src/github.com/kwmt/heroku-with-docker",
  "website": "http://github.com/kwmt/heroku-with-docker",
  "repository": "http://github.com/kwmt/heroku-with-docker"
}

これはheroku-container-toolsプラグインの

% heroku container:init

というコマンドを使って、次のようなDockerfiledocker-compose.ymlファイルを自動生成するためのものです。

FROM heroku/go:1.6
web:
  build: .
  command: 'bash -c ''heroku-with-docker'''
  working_dir: /app/user/src/github.com/kwmt/heroku-with-docker
  environment:
    PORT: 8080
  ports:
    - '8080:8080'
shell:
  build: .
  command: bash
  working_dir: /app/user/src/github.com/kwmt/heroku-with-docker
  environment:
    PORT: 8080
  ports:
    - '8080:8080'
  volumes:
    - '.:/app/user/src/github.com/kwmt/heroku-with-docker'

ぶっちゃけこれらのファイルの書き方が分かってしまえば、app.jsonは不要です。といいますか、heroku-container-toolsはdeprecatedになっているので、今後heroku container:initする手段がなくなります。。。

そもそもheroku container:initheroku-container-toolsプラグインのコマンドなんですが、このプラグインはdeprecatedになってたり。 addonはここにあるものしかかけないし・・・

デプロイ

% heroku container:release

以上でデプロイできて、動いた。わーい!

とはいかなくて、Godeps/Godeps.jsonファイルを作らないと動きません。

% cat Godeps/Godeps.json
{
    "ImportPath": "github.com/kwmt/heroku-with-docker",
    "GoVersion": "go1.6",
    "Deps": []
}

Dockerイメージheroku/goがGodepsに依存してしまってて。。

とはいえ、Godeps.jsonファイルを作れば下図のようにデプロイ出来ました。

まとめ(Heroku+Dockerが微妙なとこ)

サンプルソース

参考

  • このエントリーをはてなブックマークに追加
  • LinkedIn
  • Tumblr
  • Reddit
  • Google+
  • Pinterest
  • Pocket