Heroku
docker
HerokuDay 4

Heroku Container Registry & Runtime とは(Heroku Dev Center の私家訳)

More than 1 year has passed since last update.

この記事は、 Heroku Advent Calendar 2017 4日目の記事です

(dev center の記事を私訳します。 2017/11/23 最終更新の記事)


Heroku Container Registry では、Docker ベースのアプリケーションを Heroku にデプロイすることができます

Common RuntimePrivate Space もサポートされています


まずはじめに

Docker がインストールされ、動作する環境を用意します(例: docker ps)。heroku へコマンドラインからログインしておきます(heroku login)

Container Registry へログインします:

$ heroku container:login

Alpine ベースの python サンプル image を入手します

$ git clone https://github.com/heroku/alpinehelloworld.git

アプリケーションのディレクトリに移動し、 heroku app を create します

$ heroku create

Creating salty-fortress-4191... done, stack is cedar-14
https://salty-fortress-4191.herokuapp.com/ | https://git.heroku.com/salty-fortress-4191.git

image をビルドし、 Container Registry へプッシュします

$ heroku container:push web

ブラウザからアプリケーションを開きます

$ heroku open


registry へのログイン

Heroku は Container Registry を、 registry.heroku.com 上で実行しています

HerokuCLI を利用している場合、次のようにしてログインすることが可能です:

$ heroku container:login

もしくは、Docker コマンドから直接ログインすることもできます:

$ docker login --username=_ --password=$(heroku auth:token) registry.heroku.com


image(s) のプッシュ


image のビルドとプッシュ

image をビルドし、registry.heroku.com へプッシュするには、アプリケーションのディレクトリに Dockerfile が存在することが必要です. 以下を実行します:

heroku container:push <process-type>


caution

プロセスタイプを指定するとしても、registry へのプッシュは、全てのプロセスをリスタートします

例えば、 もしあなたが web プロセスを指定したとしても、 worker プロセスもリスタートされます



既存の image をプッシュする

Heroku へ image をプッシュするために、 Docker Hub から pull されたものであっても、 tag 付けを行い、 naming template に従ってプッシュしてください:

$ docker tag <image> registry.heroku.com/<app>/<process-type>

$ docker push registry.heroku.com/<app>/<process-type>

image のプッシュが成功した後、アプリケーションを開いてください:

$ heroku open -a <app>


複数の image をプッシュする

複数 image をプッシュするために、Dockerfile を Dockerfile. のようにリネームしてください:

$ ls -R

./webapp:
Dockerfile.web
./worker:
Dockerfile.worker
./image-processor:
Dockerfile.image

それから、プロジェクトのルートディレクトリから、実行します:

$ heroku container:push --recursive

=== Building web
=== Building worker
=== Building image
=== Pushing web
=== Pushing worker
=== Pushing image

3つの image をビルドし、プッシュします

もし、特定の image のみをプッシュしたい場合は、プロセスタイプを指定することができます:

$ heroku container:push web worker --recursive

=== Building web
=== Building worker
=== Pushing web
=== Pushing worker


ワンオフdyno

もし、アプリケーションが複数の Docker image で構成される場合、ワンオフdyno を作るときに、プロセスタイプを指定することができます:

$ heroku run bash --type=worker

Running bash on ⬢ multidockerfile... up, worker.5180

もし、プロセスタイプが指定されていなかった場合、 web image が使用されます


CI/CD を利用する

もしサードパーティの CI/CD プラットフォームを使用しているならば、 registry へ image をプッシュすることができます

最初の認証は、下記の情報が必要です:


  • Registry URL: registry.heroku.com

  • Username: your Heroku email address

  • Email: your Heroku email address

  • Password: your Heroku API key

多くの CI/CD プロバイダが、Docker registry へ image をビルドしプッシュするためのドキュメントを用意しています:


Dockerfile コマンドとランタイム

アプリケーションのために Docker image を Container Registry へプッシュするとき、それら image は即座に Heroku app にリリースされます

Docker image はslugbuildpackでビルドすることと機能的に等価です

Docker image は dyno での実行において、slugが実行する方法と同じであり、また、同じ制約の下実行されます:



  • web プロセスはHerokuによって設定される$PORTにおいてHTTPトラフィックをリッスンしなければならなりません.Dockerfile 内の EXPOSE は優先されず、ローカルでのテスト時に使用することができます.HTTPリクエストのみがサポートされます

  • dyno同士のネットワークリンクはサポートされません

  • ファイルシステムはエフェメラルです

  • 実行時のディレクトリは/です.WORKDIRによって他のディレクトリを指定できます

  • 環境変数設定のための ENV はサポートされます



    • ENVは実行時変数(例: GEM_PATN)の使用や、クレデンシャルのための heroku config について使用することが推奨されます. そうすることで、センシティブなクレデンシャルが、偶然にソースコードに紛れないでしょう




  • ENTRYPOINT はオプションです. もし設定されない場合/bin/sh -c が使用されます


  • CMD は必須です. もしCMDが設定されていない場合、 registry はエラーを返します


ローカルでの image のテストにはroot以外のユーザでの実行を強く推奨します

container は Heroku 上では、root 権限では実行されないためです



サポートされない Dockerfile コマンド



  • VOLUME - ボリュームマウントはサポートされません. dyno のファイルシステムはエフェメラルです


  • EXPOSE - EXPOSE はローカルでのテスト時には使用することができます. しかし、 Heroku container runtime ではさぽーとされません. かわりに web プロセスなどで、環境変数の $PORT を取得するようにしてください


  • STOPSIGNAL - dyno マネージャは、プロセスが SIGLILL シグナルに準拠したSIGTERM signalを送られる事によるグレースフルシャットダウンを要求します.STOPSIGNAL は推奨されません


  • SHELL - Docker image のデフォルトのシェルは /bin/sh です. 必要であれば、ENTRYPOINT によって上書きすることができます


  • HEALTHCHECK - HEALTHCHEK は現在サポートされていませんが、 Heroku Dyno マネージャは実行中コンテナのherth check を自動的に行っています


ローカルで image をテストする

ローカルで image をテストするとき、いくつかのベストプラクティスがあります

この例の Dockerfile で実装されています


非root として実行する

ローカルでの image のテストにはroot以外のユーザでの実行を強く推奨します

container は Heroku 上では、root 権限では実行されないためです

Dockerfile のCMD行の直前に下記のコマンドを追加することができます:

Alpine 使用の場合:

RUN adduser -D myuser

USER myuser

Ubuntu 使用の場合:

RUN useradd -m myuser

USER myuser

自身の containar が非ルートユーザで実行されていることを確認し、実行中の container に attach し、 whoami コマンドを実行します:

$ docker exec <container-id> bash

$ whoami
myuser

Heroku へのデプロイ時、非ルートユーザで container も実行します

(Dockerfile に USER が指定されていたとしても使用しません)

$ heroku run bash

$ whoami
U7729


環境変数からのポート番号の取得

テスト目的で、Dockerfile やコード上で、環境変数から $PORT を読むようにすることを提案します

例えば:

CMD gunicorn --bind 0.0.0.0:$PORT wsgi

Docker container をローカルで実行するとき、-eフラグによって環境変数を設定することができます:

docker run -p 5000:5000 -e PORT=5000 <image-name>


複数の環境変数を設定する

もしheroku localで実行しているならば、config var を .env ファイルに設定することができます

heroku localが実行されているとき、 .env は読み込まれ、name/value ペアが環境変数に設定されます

同じ.envファイルを Docker を使用するときにも使用することができます:

docker run -p 5000:5000 --env-file .env <image-name>

.envファイルは、.dockerignoreファイルに追加することを提案します


マルチコンデナアプリケーション用のdocker-composeの活用

マルチコンテナアプリケーションを作ったならば、ローカル開発環境を定義するdocker-composeを使用することができます

ローカル開発のためのdocker-composeの使い方はこちら


参考情報


images をスタックする

Cedar-14Heroku-16 の Docker image が利用可能です

しかしながら、いかなる base image も使用することができます

Heroku スタックイメージを使用する必要はありません

もし Heroku スタックイメージを使用することを選択するならば Heroku-16 (465.3 MB) をお勧めします

Cedar-14 に比べより小さいからです

heroku-16 を base image として使用する場合、 Dockerfile に次のように記述してください:

FROM heroku/heroku:16


デプロイ方法の変更

Container Registry へアプリケーションをデプロイしたならば、スタックは container にセットされます

これは、アプリケーションが、カスタム container を使用し、 Heroku-curated スタックをもはや使用しないということです

container に設定されると、git経由でアプリケーションをプッシュすることはできません

container registry 経由でアプリケーションをデプロイする必要が無く、代わりにgitを使用したい場合は、heroku stack:set heroku-16を実行してください


既知の制限とイシュー


  • Heroku は、ホスト側でのdocker ビルドサービスを提供しません; image はローカルや, Docker Hub や、そのほかの Docker build serviceでビルドされなければいけません. これは, Heroku Github integration and review apps の枠組みから外れると機能しない事を意味します

  • Docker image は(slugと違い)サイズ制限の対象ではありませんが,dyno の起動時間制限の対象です. レイヤ数/image サイズが大きくなると、dyno の起動時間も長くなります

  • 40以上のレイヤを持つ image は Common Runtime では起動に失敗するでしょう

  • Pipeline promotion はサポートされません

  • Release phase はサポートされません


  • このコマンドリストはサポートされません