Help us understand the problem. What is going on with this article?

Heroku で Docker を使う場合の諸注意

More than 1 year has passed since last update.

本日、かしゆかの誕生日です、どうぞみなさまお祝いください。

さて、本日の内容です。

Container Registry が GA になったよ!!

2017/9/5 の changelog で Container Registry GA - Deploy Docker images to Herokuと公開されたとおり、これまでβサービスとして提供されていた Docker 向けコンテナサービスが、本番向けにリリースされました。

これまで buildpack の制約や、docker でせっかく準備した開発サイクルのために、Herokuの利用を躊躇されていたみなさまには、朗報です。はやいところ、Heroku Pipelines 上で Heroku CI つかって、Docker のCI/CD まわしたいですね!! Heroku は世界を支配しますよ!!
(もしかすると、https://devcenter.heroku.com/articles/heroku-yml-build-manifest これ使うと、Pipelines も Review Apps もいけるかもしれないんですが、いまテスト中です。ややこい)

とは言え、Docker完全サポートではありません。Dockerで動きさえすればHeroku上でも動く、というわけでは残念ながらありません。Docker を Heroku上で動かすためには、いくつかの注意事項がありますので、そちらをご紹介します。

前提条件

Docker を Heroku上で動かすためには、最低限の条件が3点あります。

  1. Heroku アカウントを持っていること
  2. Heroku CLI コマンドを導入して、利用可能にしていること
  3. docker コマンドを導入して、利用可能なこと

現時点では、Dockerイメージを Heroku 上にデプロイするためには CLIが必須です。また、ローカルでdockerコマンドを実行して制御するため、Docker コマンドが必須です。Docker 使おうってんだから、みんな入ってるはずですけど。

デプロイの流れとコマンド

実際に、ローカルに準備した Dockerfile をHeroku上へデプロイする場合の流れは、次のとおりになります。すべて、コマンドで実行した場合です。一部、GUIでも実行可能な部分については、その旨を追記しています。

  1. heroku login で、Heroku アカウントへログインさせます。
  2. heroku container:login で、Heroku 上の Container Registry へログインします。
  3. heroku create で、Docker を動かすための Herokuアプリを作成します(GUIでも可)。
  4. heroku addons:create で、必要なアドオンを追加します(GUIでも可、アドオン不要なら実行不要)。
  5. heroku container:push <process-type> で、ローカルの Dockerfile もろもろをデプロイします。
  6. docker のイメージが作成され、Heroku 上で動作するように配置されます。
  7. heroku open で、デプロイされたアプリへ、ブラウザでアクセスします(GUIでも可)。

設定・デプロイ上の注意事項

とまぁ、コマンドがちょっとちがうものの、HerokuへのDockerデプロイは、それほど困難はありません。ただ、Heroku固有の制約があります。それらについて説明します。

  1. PORT 環境変数で Listen する Webアプリケーションであること
  2. Network link は未サポート
  3. Default working directory = '/'。変更するときは WORKDIR を指定する。
  4. CMDが必須。ENTRYPOINTはオプション。
  5. VOLUMEEXPOSESTOPSIGNALSHELLHEALTHCHECKは未サポート

Heroku は Webアプリケーションを動かすためのプラットフォームです。また、環境変数 PORT で指定されたポートで LISTENしていないと、「こりゃ不適合アプリだな」としてアプリをクラッシュさせて停止します。厳密には、PORT 変数で LISTENさえしていれば、Web応答をするかどうかに関係なく実行はできるようです(2017/12/18現在)

したがって、ポート番号を強制するようなEXPOSEも利用できませんし、そもそも外部のファイルデバイスを利用するという仕組みのないHerokuでは、VOLUME も利用できないということになります。

ENTRYPOINT はオプション指定ですが、何も指定していなければ自動的に /bin/sh -c が指定されます。

複数のイメージを push するには

ディレクトリごとにDockerfileを準備して、個別にも、いっぺんにでも、まとめてHerokuアプリへpushできます。例えば、次のようなディレクトリ構成だとします。

directory
web/
 +- Dockerfile.web

worker-dyno/
 +- Dockerfile.worker

worker-test/
 +- Dockerfile.test

heroku container:push--recursive を付与して実行します。

push
heroku container:push --recursive

この場合、web worker-dyno worker-test にある全ての Dockerfile のイメージが作成され、一つずつが Dyno として Heroku アプリ上に作られます。この場合では、3つの Dynoが作られるということですね。

ディレクトリ名はなんでもいいんですが、Dockerfile のあとは重要な識別子になります。これが Dyno のプロセスタイプになります。Heroku は Web Dyno が必要で、それが Webアプリとして実行される Dyno になります。その他のプロセスタイプの場合は、Worker Dynoとして定義され、バックエンドで実行させることができるようになります。

今回のケースだと、web 「Web Dyno」 一つと worker test という2つの「Worker Dyno」がデプロイされるということになります。このプロセスタイプを、Dockerfile のあとに「.」をつけて付与する必要があります。ただの「Dockerfile」では認識されませんので、お気をつけください。

また、push時にデプロイするプロセスタイプを指定できます。例えば、webtest だけデプロイしたい、ということであれば。

push
heroku container:push web test --recursive

と指定することになります。この場合でも --recursive は必要ですのでお忘れなく。

※ Herokuチームにはさんざんレビューいただいて、ホント感謝です。

参考

Container Registry & Runtime (Docker Deploys)

sho7650
妻x1+娘x4 オンプレインフラメインのインフラエンジニアが、ソフトウェア中心のPaaS/SaaS業界へ転身し、一度はやめたアプリケーションに手を出し始めている昨今、みなさまいかがお過ごしでしょうか。 外資系はいいぞ(
http://oshiire.to
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away