LoginSignup
20
19

More than 3 years have passed since last update.

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

Last updated at Posted at 2017-12-04

この記事は、 Heroku Advent Calendar 2017 4日目の記事です
(dev center の記事を私訳します。 2017/11/23 最終更新の記事)
(Last updated 02 May 2019 の記事に追従 (2019/05/30))


Heroku Container Registry では、Docker ベースのアプリケーションを Heroku にデプロイすることができます
Common RuntimePrivate Space もサポートされています

もし、Heroku 上で Docker image をビルドする場合、Review app を利用することもできます
building Docker images with heroku.yml を確認してください

まずはじめに

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

そして、release 操作を行います

$ heroku container:release 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>

既存の 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>

tag にプロセスタイプを指定することで、CLI を使用して image をリリースできます(release the image using the CLI)
もし、tag にプロセスタイプを指定したくない場合は、image_id を使った API 経由のリリースが可能です(release via the API)

複数の 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

image のリリース

CLI

container registry への push が成功したあと、新しい release を作ることができます

$ heroku container:release web

もし、複数の image がある場合は、リストとして渡します

$ heroku container:release web worker

caution
多数のプロセスタイプをもつ app の場合で、ひとつのプロセスタイプのみを release した場合、
(e.g., heroku container:relase web)
すべてのプロセスタイプがリスタートされます

API

$ curl -n -X PATCH https://api.heroku.com/apps/$APP_ID_OR_NAME/formation \
  -d '{
  "updates": [
    {
      "type": "web",
      "docker_image": "$WEB_DOCKER_IMAGE_ID"
    },
    {
      "type": "worker",
      "docker_image": "$WORKER_DOCKER_IMAGE_ID"
    },
  ]
}' \
  -H "Content-Type: application/json" \
  -H "Accept: application/vnd.heroku+json; version=3.docker-releases"

Docker image ID を取得する

$ docker build -t my_image .
...
Successfully built acf835bc07f5
Successfully tagged my_image:latest

docker inspect my_image --format={{.Id}}
acf835bc07f5

ワンオフdyno

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

$ heroku run bash --type=worker
Running bash on ⬢ multidockerfile... up, worker.5180

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

CI/CD を利用する

caution
現時点では、コンテナビルドのテストに Heroku CI は使えません

もしサードパーティの 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 をビルドしプッシュするためのドキュメントを用意しています:

Release フェイズ

Release フェイズ を使用するためには、Docker image の名前を release とします

$ heroku container:push release

heroku container:release によって Docker image をリリースする場合、プロセスタイプの指定が必要です

$ heroku container:release web release
Releasing images web,release to your-app-name... done
Running release command...
Migrating database.

release フェイズ実行中の、ストリーミングログを見たい場合、Docker image 内に curl が必要です
Docker image 内に curl がない場合、release フェイズのログはアプリケーションログ内で利用可能です
Heroku-16 もしくは Heroku-18 スタックをベースイメージとして使用している場合、curl はイメージ内に含まれています

Dockerfile コマンドとランタイム

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

  • web プロセスはHerokuによって設定される$PORTにおいてHTTPトラフィックをリッスンしなければならなりません. Dockerfile 内の EXPOSE は優先されませんが、ローカルでのテスト時に使用することができます. また、HTTPリクエストのみがサポートされます
  • dyno 同士のネットワークリンクはサポートされません
  • ファイルシステムはエフェメラルです
  • 実行時のディレクトリは/です.WORKDIRによって他のディレクトリを指定できます
  • 環境変数設定のための ENV がサポートされています
    • センシティブなクレデンシャルが、偶発的にソースコードに紛れることがなくすために、ENV は実行時変数(例: GEM_PATH)の使用や、クレデンシャル用に heroku config を使用することが推奨されます
  • ENTRYPOINT はオプションです. もし設定されない場合/bin/sh -c が使用されます
    • config varsがプロセスで使用可能になるために、CMD は shell によって常に実行されます
    • シングルバイナリの実行や、shell 無しでの image 実行には ENTRYPOINT を利用してください

ローカルでの image のテストにはroot以外のユーザでの実行を強く推奨します
Heroku 上では、container は 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以外のユーザでの実行を強く推奨します
Heroku 上では、container は 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 をスタックする

Heroku-16Heroku-18 の Docker image が利用可能です
しかしながら、いかなる base image も使用することができます
Heroku スタックイメージを使用する必要はありません
もし Heroku スタックイメージを使用することを選択するならば Heroku-18 (406 MB) をお勧めします

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

FROM heroku/heroku:18

latest image を取得する

すでにアプリケーションで Heroku-18 を使用していて、latest version に更新したい場合は、下記を実行します

$ docker pull heroku/heroku:18

そして、再度アプリケーションの deply を実行してください

デプロイ方法の変更

Container Registry へアプリケーションをデプロイしたならば、スタックは container にセットされます
これは、アプリケーションが、カスタム container を使用し、 Heroku-curated スタックをもはや使用しないということです
container に設定されると、git経由でアプリケーションをプッシュすることはできません
container registry 経由でアプリケーションをデプロイする必要が無く、代わりにgitを使用したい場合は、heroku stack:set heroku-18を実行してください

既知の制限とイシュー

  • Review apps はサポートされません. Docker を Review apps とともに利用する場合、Docker image を Heroku 上でビルドするために heroku.yml manifest とともにアプリケーションを定義してください
  • Docker image は(slugと違い)サイズ制限の対象ではありませんが,dyno の起動時間制限の対象です. レイヤ数/image サイズが大きくなると、dyno の起動時間も長くなります
  • 40以上のレイヤを持つ image は Common Runtime では起動に失敗するでしょう
  • Pipeline promotion はサポートされません
  • このコマンドリストはサポートされません
20
19
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
19