Container Registry および Runtime (Docker デプロイ)
この記事の英語版に更新があります。ご覧の翻訳には含まれていない変更点があるかもしれません。
Last updated 29 October 2020
Table of Contents
Heroku Container Registry を使用すると、Docker イメージを Heroku にデプロイできます。 Common Runtime と Private Space の両方がサポートされています。
Heroku で Docker イメージをビルドさせる場合は、レビューアプリを活用するだけでなく、heroku.yml で Docker イメージのビルドを確認します。
はじめに
作業用 Docker インストールがあることを確認し (docker ps
など)、Heroku にログインしていることを確認します (heroku login
)。
Container Registr にログインします。
$ heroku container:login
Alpine ベースの python 例を複製することによりサンプルコードを取得します。
$ git clone https://github.com/heroku/alpinehelloworld.git
アプリのディレクトリに移動して、Heroku アプリを作成します。
$ heroku create
Creating salty-fortress-4191... done, stack is heroku-18
https://salty-fortress-4191.herokuapp.com/ | https://git.heroku.com/salty-fortress-4191.git
イメージをビルドし、Container Registry にプッシュします。
$ heroku container:push web
続いてイメージをアプリにリリースします。
$ heroku container:release web
次に、アプリをブラウザで開きます。
$ heroku open
レジストリへのログイン
Heroku は、registry.heroku.com
でコンテナレジストリを実行します。
Heroku CLI を使用している場合、次のように指定してログインできます。
$ heroku container:login
または直接 Docker CLI を使用します。
$ docker login --username=_ --password=$(heroku auth:token) registry.heroku.com
イメージのビルドとプッシュ
イメージのビルドとプッシュ
イメージをビルドして Container Registry にプッシュするには、ディレクトリに Dockerfile が含まれていることを確認し、次のように実行します。$ heroku container:push <process-type>
既存のイメージのプッシュ
Docker Hub からプルしたものなどのイメージを Heroku にプッシュするには、次の命名テンプレートに従って、そのイメージにタグを付けプッシュします。$ docker tag <image> registry.heroku.com/<app>/<process-type>
$ docker push registry.heroku.com/<app>/<process-type>
タグでプロセスタイプを指定することにより、CLI を使用してイメージをリリースできます。 タグでプロセスタイプを指定しない場合は、image_id
を使用する API を介してリリースする必要があります。
複数のイメージのプッシュ
複数のイメージをプッシュするには、Dockerfile.<process-type>
を使用して 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 つのイメージすべてをビルドしてプッシュします。 特定のイメージだけをプッシュする場合は、プロセスタイプを指定できます。
$ heroku container:push web worker --recursive
=== Building web
=== Building worker
=== Pushing web
=== Pushing worker
イメージのリリース
CLI
Container Registry に正常にイメージをプッシュした後、次のコマンドを使用して新しいリリースを作成できます。$ heroku container:release web
複数のイメージがある場合は、それらを一覧表示します。
$ heroku container:release web worker
複数のプロセスタイプを持つアプリでは、1 つのプロセスタイプ (heroku container:release 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 イメージ ID の取得
$ docker build -t my_image .
...
Successfully built acf835bc07f5
Successfully tagged my_image:latest
$ docker inspect my_image --format={{.Id}}
acf835bc07f5
One-off dyno
アプリが複数の Docker イメージから構成されている場合、One-off dyno を作成するときにプロセスタイプを対象にすることができます
$ heroku run bash --type=worker
Running bash on ⬢ multidockerfile... up, worker.5180
$
タイプが指定されていない場合、web
イメージが使用されます。
CI/CD プラットフォームの使用
現在、Heroku CI を使用してコンテナビルドをテストすることはできません。
サードパーティ製の CI/CD プラットフォームを使用している場合は、レジストリにイメージをプッシュできます。最初に次の情報で認証します。
- レジストリ URL:
registry.heroku.com
- ユーザー名:
your Heroku email address
- メール:
your Heroku email address
- パスワード:
your Heroku API key
多くの CI/CD プロバイダーは、イメージをビルドして Docker レジストリにプッシュする方法に関するドキュメントを用意しています。
Release Phase
Release Phase を使用するには、release
という名前の Docker イメージをプッシュします。
$ heroku container:push release
Docker イメージをリリースすると、heroku container:release
を実行することにより、Release Phase プロセスタイプを指定する必要があります。
$ heroku container:release web release
Releasing images web,release to your-app-name... done
Running release command...
Migrating database.
Release Phase が実行するときにストリーミングログを確認する場合は、Docker イメージに curl
が必要です。 Docker イメージに curl
が含まれていない場合、アプリケーションログで Release Phase ログを使用できます。 Heroku-16 または Heroku-18 をベースイメージとして使用している場合、curl
が含まれます。
Dockerfile コマンドとランタイム
Docker イメージは、dyno において、slugs が行う方法と同じように同じ制約のもと実行します。
- Web プロセスは、Heroku により設定された
$PORT
上で HTTP トラフィックをリスンする必要があります。Dockerfile
内の EXPOSE
は考慮されませんが、ローカルテストに使用できます。 HTTP リクエストだけがサポートされています。 - dyno のネットワークリンクはサポートされていません。
- ファイルシステムは一時的です。
- 作業用ディレクトリは
/
です。 WORKDIR
を使用して、別のディレクトリを設定できます。 - 環境変数を設定するための
ENV
がサポートされています。- ランタイム変数 (
GEM_PATH
など) に ENV
を、資格情報に heroku config
を使用することをお勧めします。そうすれば、機密性のある資格情報が誤ってソースコード制御にチェックインされることがなくなります。
- ランタイム変数 (
-
ENTRYPOINT
はオプションです。 設定されていない場合、/bin/sh -c
が使用されます。-
CMD
は常にシェルにより実行されるので、環境設定はプロセスで使用可能になります。単一のバイナリを実行したり、シェルなしでイメージを使用するには、ENTRYPOINT
を使用してください。
-
コンテナは、Heroku のルート権限で実行されていないので、非ルートユーザーとしてローカルでイメージをテストすることを強くお勧めします。
未サポートの Dockerfile コマンド
-
VOLUME
- ボリュームマウンティングはサポートされていません。 dyno のファイルシステムは一時的です。 -
EXPOSE
- EXPOSE
はローカルテストに使用できますが、Heroku のコンテナランタイムではサポートされていません。 代わりに、Web プロセス/コードで $PORT 環境変数を取得する必要があります。 -
STOPSIGNAL
- dyno マネージャーは、SIGTERM 信号とそれに続く SIGKILL 信号を送信することにより、プロセスがグレースフルシャットダウンを行うように要求します。 STOPSIGNAL
は考慮されません。 -
SHELL
- Docker イメージのデフォルトのシェルは /bin/sh
であり、必要に応じて ENTRYPOINT
で上書きできます。 -
HEALTHCHECK
- HEALTHCHECK
は現在サポートされていませんが、Heroku Dyno マネージャーが自動的に、実行中のコンテナのヘルスを確認します。
ローカルでのイメージのテスト
ローカルでイメージをテストするときに、多数のベストプラクティスがあります。 これらのベストプラクティスは、この Dockerfile 例に実装されています。
非ルートユーザーとしてのイメージの実行
コンテナは、Heroku のルート権限で実行されていないので、非ルートユーザーとしてローカルでイメージをテストすることを強くお勧めします。CMD
の直前に、次のコマンドを Dockerfile に追加できます。
Alpine を使用している場合:
RUN adduser -D myuser
USER myuser
Ubuntu を使用している場合:
RUN useradd -m myuser
USER myuser
コンテナが非ルートユーザーとして実行していることを確認するには、実行中のコンテナにアタッチしてから、whoami
コマンドを実行します。
$ docker exec <container-id> bash
$ whoami
myuser
Heroku にデプロイすると、非ルートユーザーとしてもコンテナを実行します (ただし、Dockerfile で指定された USER
は使用しません)。
$ heroku run bash
$ whoami
U7729
環境変数からのポートの取得
テストのために、たとえば次のように、Dockerfile
またはコードが $PORT 環境変数から読み取ることをお勧めします。
CMD gunicorn --bind 0.0.0.0:$PORT wsgi
Docker コンテナをローカルで実行している場合、-e フラグを使用して環境変数を設定できます。
$ docker run -p 5000:5000 -e PORT=5000 <image-name>
複数の環境変数の設定
ローカルで Heroku を使用する場合、.env ファイルで環境設定を設定できます。 heroku local
が実行されると、.env が読み取られ、各 name/value のペアが環境で設定されます。 Docker を使用するときに、この同じ .env ファイルを使用できます。
$ docker run -p 5000:5000 --env-file .env <image-name>
.env ファイルを .dockerignore ファイルに追加することをお勧めします。
マルチコンテナアプリケーションに対する Docker Compose の利用
マルチコンテナアプリケーションを作成した場合、Docker Compose を使用して、ローカルの開発環境を定義できます。 ローカル開発に Docker Compose を使用する方法について説明します。
追加情報
- ローカルでの Docker イメージの実行に関する詳細は、Docker の公式ドキュメントに記述されています。
- ローカル開発に Docker Compose を使用する方法について説明します。
- Docker イメージのビルドパフォーマンスおよびサイズを最適化する方法のヒントについては、Dockerfile を書き込むためのベストプラクティスのガイドを参照してください。
スタックイメージ
Heroku-16 および Heroku-18 スタックは、便宜上、Docker イメージとして使用できます。ただし、目的のベースイメージを自由に使用できます。Heroku スタックイメージを使用する必要はありません。ビルドおよび起動時間を最短にするには、アプリの言語についていずれかの公式の Docker イメージなど、より小さい汎用性の低いベースイメージを使用することをお勧めします。Heroku イメージを使用することにした場合、Heroku-18 (486 MB) をお勧めします。
Dockerfile
でベースイメージとして Heroku-18 を使用するには、次のように指定します。
FROM heroku/heroku:18
最新のイメージの取得
ベースイメージに Heroku-18 を使用してアプリをすでにデプロイしており、最新バージョン (通常セキュリティ更新を含む) を取得する場合、単に次のように実行します。
$ docker pull heroku/heroku:18
そしてアプリケーションを再デプロイします。
デプロイ方法の変更
Container Registry を介してアプリケーションをデプロイすると、スタックは container
に設定されます。 これは、アプリケーションが Heroku-curated スタックを使用しなくなったが、代わりに自身のカスタムコンテナを使用していることを意味します。 container
に設定した後、Git を介したアプリのプッシュは無効になります。 Container Registry を介してアプリをデプロイする必要がなくなり、代わりに Git を使用する場合は、heroku stack:set heroku-18
を実行します。
既知の問題と制限事項
- レビューアプリはサポートされてません。 レビューアプリで Docker を使用するために、Heroku に Docker イメージをビルドできるようにする heroku.yml マニフェストでアプリを定義できます。
- パイプラインのプロモートはサポートされていません。
- Docker イメージは、サイズの制限に従いませんが (slugs) と異なる)、dyno 起動時間の制限に従います。 レイヤ数/イメージサイズが大きくなると、dyno 起動時間が長くなります。Docker イメージサイズを減らす推奨の方法については、Dockerfile の書き込みのベストプラクティスガイドを参照してください。
- 40 を超えるレイヤを持つイメージは、Common Runtime で開始できない場合があります
- ここに一覧表示したコマンドはサポートされていません。