本日、かしゆかの誕生日です、どうぞみなさまお祝いください。
さて、本日の内容です。
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点あります。
- Heroku アカウントを持っていること
- Heroku CLI コマンドを導入して、利用可能にしていること
- docker コマンドを導入して、利用可能なこと
現時点では、Dockerイメージを Heroku 上にデプロイするためには CLIが必須です。また、ローカルでdockerコマンドを実行して制御するため、Docker コマンドが必須です。Docker 使おうってんだから、みんな入ってるはずですけど。
デプロイの流れとコマンド
実際に、ローカルに準備した Dockerfile をHeroku上へデプロイする場合の流れは、次のとおりになります。すべて、コマンドで実行した場合です。一部、GUIでも実行可能な部分については、その旨を追記しています。
-
heroku loginで、Heroku アカウントへログインさせます。 -
heroku container:loginで、Heroku 上の Container Registry へログインします。 -
heroku createで、Docker を動かすための Herokuアプリを作成します(GUIでも可)。 -
heroku addons:createで、必要なアドオンを追加します(GUIでも可、アドオン不要なら実行不要)。 -
heroku container:push <process-type>で、ローカルの Dockerfile もろもろをデプロイします。 - docker のイメージが作成され、Heroku 上で動作するように配置されます。
-
heroku openで、デプロイされたアプリへ、ブラウザでアクセスします(GUIでも可)。
設定・デプロイ上の注意事項
とまぁ、コマンドがちょっとちがうものの、HerokuへのDockerデプロイは、それほど困難はありません。ただ、Heroku固有の制約があります。それらについて説明します。
-
PORT環境変数で Listen する Webアプリケーションであること - Network link は未サポート
- Default working directory = '/'。変更するときは
WORKDIRを指定する。 -
CMDが必須。ENTRYPOINTはオプション。 -
VOLUME、EXPOSE、STOPSIGNAL、SHELL、HEALTHCHECKは未サポート
Heroku は Webアプリケーションを動かすためのプラットフォームです。また、環境変数 PORT で指定されたポートで LISTENしていないと、「こりゃ不適合アプリだな」としてアプリをクラッシュさせて停止します。厳密には、PORT 変数で LISTENさえしていれば、Web応答をするかどうかに関係なく実行はできるようです(2017/12/18現在)
したがって、ポート番号を強制するようなEXPOSEも利用できませんし、そもそも外部のファイルデバイスを利用するという仕組みのないHerokuでは、VOLUME も利用できないということになります。
ENTRYPOINT はオプション指定ですが、何も指定していなければ自動的に /bin/sh -c が指定されます。
複数のイメージを push するには
ディレクトリごとにDockerfileを準備して、個別にも、いっぺんにでも、まとめてHerokuアプリへpushできます。例えば、次のようなディレクトリ構成だとします。
web/
+- Dockerfile.web
worker-dyno/
+- Dockerfile.worker
worker-test/
+- Dockerfile.test
heroku container:push に --recursive を付与して実行します。
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時にデプロイするプロセスタイプを指定できます。例えば、web と test だけデプロイしたい、ということであれば。
heroku container:push web test --recursive
と指定することになります。この場合でも --recursive は必要ですのでお忘れなく。
※ Herokuチームにはさんざんレビューいただいて、ホント感謝です。