DockerでHerokuでmrubyが動いたぞ!!1
dockerを使ってHerokuにアプリを簡単にデプロイできる感じの仕組みができた(という説明であってるのかよくわからないけど)そうなので、試してみた。
動かしているのは、単になんか変な文字列を表示するだけのアプリ。
以下に、手順を示す。
動かすまでの手順
herokuコマンドなどの準備
herokuクライアントを入れる。
$ brew install heroku ==> Downloading https://s3.amazonaws.com/assets.heroku.com/heroku-client/heroku-client-3.32.0.tgz 🍺 /usr/local/Cellar/heroku-toolbelt/3.32.0: 818 files, 7.4M, built in 7 seconds
boot2dockerでdockerが動いていることを確認(boot2dockerについてはどこか適当なとこを見てください)。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
dockerプラグインを入れる。
$ heroku plugins:install heroku-docker Installing plugin heroku-docker... done updating...done. Updated to 3.36.0
helpを見てみるね。
$ heroku help docker Usage: heroku docker Use Docker to build and deploy Heroku apps Additional commands, type "heroku help COMMAND" for more details: docker:clean # clean up docker images docker:exec # run command in development Docker container docker:init # create Dockerfile for app docker:release # create and release slug to app docker:start # start Docker app container
ディレクトリを作る。
$ mkdir mruby-app-on-heroku-using-docker $ cd mruby-app-on-heroku-using-docker $ git init
実行環境の準備
まずはDockerfile
を作成。言語が判定できたらそれ用のファイルが作られるが、今回の場合は空ディレクトリなので、ミニマルなものが作られる。
$ heroku docker:init Wrote Dockerfile (minimal) $ cat Dockerfile FROM heroku/cedar:14 RUN useradd -d /app -m app USER app WORKDIR /app ENV HOME /app ENV PORT 3000 RUN mkdir -p /app/heroku RUN mkdir -p /app/src RUN mkdir -p /app/.profile.d WORKDIR /app/src ONBUILD COPY . /app/src ONBUILD EXPOSE 3000
これを、あとで書くコードを動かすために、以下のように変更します(# install mruby
のとこを足しただけ)。dockerまだよくわかってない(ONBUILD
とか)ので、おかしいかも。
FROM heroku/cedar:14 RUN useradd -d /app -m app # install mruby WORKDIR /app ENV DEBIAN_FRONTEND noninteractive RUN apt-get -y update RUN apt-get -y install git RUN git clone https://github.com/mruby/mruby.git COPY ./build_config.rb /app/mruby/build_config.rb RUN cd mruby && ./minirake USER app WORKDIR /app ENV HOME /app ENV PORT 3000 RUN mkdir -p /app/heroku RUN mkdir -p /app/src RUN mkdir -p /app/.profile.d WORKDIR /app/src ONBUILD COPY . /app/src ONBUILD EXPOSE 3000
Procfile
も作ります。
web: /app/mruby/bin/mruby /app/src/server.rb $PORT
コード
コードを書きます。
queue = %w[生 麦 生 米 生 卵] server = SimpleHttpServer.new( server_ip: "0.0.0.0", port: ARGV[0] || 3000, document_root: "./", ) server.location "/" do |r| content = "" while rand > 0.1 do char = queue.shift content << char queue.push(char) end server.response_body = "#{content}\n" server.create_response end server.run
mruby用の設定ファイル(build_config.rb
)を最小限で作っておく(dockerコンテナ上にコピーする)。
MRuby::Build.new do |conf| toolchain :gcc conf.gembox "default" conf.gem github: "iij/mruby-pack" conf.gem github: "iij/mruby-io" conf.gem github: "iij/mruby-socket" conf.gem github: "mattn/mruby-http" conf.gem github: "matsumoto-r/mruby-simplehttpserver" end
動かす && デプロイ
準備が終わったら、以下のコマンドでdockerを起動(最初はもっといろいろ出るけど、最終的には以下の通りの表示)。
$ heroku docker:start building image... Sending build context to Docker daemon 36.35 kB Sending build context to Docker daemon Step 0 : FROM heroku-docker-56ce9cd475f9adbdf3bf82829f2b391b # Executing 2 build triggers Trigger 0, COPY . /app/src Step 0 : COPY . /app/src Trigger 1, EXPOSE 3000 Step 0 : EXPOSE 3000 ---> Running in 352b1fd7659c ---> 2733aaefdd11 Removing intermediate container cd1c25741202 Removing intermediate container 352b1fd7659c Successfully built 2733aaefdd11 starting container... web process will be available at http://192.168.59.103:3000/
アクセスしてみる。
$ curl http://192.168.59.103:3000/ 生麦生米 $ curl http://192.168.59.103:3000/ 生卵生麦生米生卵生麦生米生卵生 $ curl http://192.168.59.103:3000/ 麦生米生
ちゃんと表示されましたね。
では、デプロイしてみよう。その前に、Heroku上でアプリを作る。
$ heroku create Enter your Heroku credentials. Email: kentarok@gmail.com Password (typing will be hidden): Creating pacific-refuge-5105... done, stack is cedar-14 https://pacific-refuge-5105.herokuapp.com/ | https://git.heroku.com/pacific-refuge-5105.git Git remote heroku added
んでもってリリース。
$ heroku docker:release creating local slug... building image... Sending build context to Docker daemon 36.35 kB Sending build context to Docker daemon Step 0 : FROM heroku-docker-56ce9cd475f9adbdf3bf82829f2b391b # Executing 2 build triggers Trigger 0, COPY . /app/src Step 0 : COPY . /app/src Trigger 1, EXPOSE 3000 Step 0 : EXPOSE 3000 ---> Running in b699aa35853c ---> 56fdb53d58fa Removing intermediate container 87ea104c42ea Removing intermediate container b699aa35853c Successfully built 56fdb53d58fa creating remote slug... uploading slug... releasing slug...
以下のURLにアクセスしてみる。
$ curl https://pacific-refuge-5105.herokuapp.com/ 卵生麦生米生卵生麦 $ curl https://pacific-refuge-5105.herokuapp.com/ 生米生 $ curl https://pacific-refuge-5105.herokuapp.com/ 卵生麦生米生卵生麦生米
ちゃんと表示されましたね。やった!
よくわからないこと
- ほんとは、
$ heroku docker:start
した時に表示されるhttp://192.168.59.103:3000/
にアクセスするとローカルで見えるはずなのだけど、どうもProcfile
の実行時に$PORT
がわたってないぽかった。Heroku上ではちゃんとしてる。 Dockerfile
でWORKDIR /app/src
としているのに、Heroku上では、Procfile
で相対パスだとファイル名が解決できてなくて、絶対パスにしたらいけた。
追記: deeeeeeeeeetさんが教えてくれたよ(↑のコード(server.rb
)もあわせて修正)。
@kentaro ローカルで$PORTが渡らないのはホスト側の環境変数を取ってしまってるからだと思います(Procfileをそのままdocker runに渡してるので).`WORKDIR /app/src`が効くのはDockerのコンテキストだけでHeroku上では無効です!
— Taichi Nakashima ☕️ (@deeeet) May 7, 2015
@kentaro 環境変数はProcfileではなくコードから読むように書く感じですね(cf. https://t.co/DSFRZiKfaZ)DockerのENVとかWORDIRはHeroku上では有効にならないので/appの構築にのみ使うとよいかと(パンツ履いてください!)
— Taichi Nakashima ☕️ (@deeeet) May 7, 2015
まとめ
- Dockerを使って、ローカル開発環境をいい感じにしつつ、Herokuにも簡単にアプリを公開できるようになった
- 公式のドキュメントではRubyとnodeの解説しかないけど、普通になんでも動く。
- mrubyでアプリを作って動かしてみた。
- ハマったところはちょっとあったけど、総じて簡単だった。便利。