Heroku
GitLab
docker
GitLab-CI

HerokuのContainer RegistryベースのデプロイをGitLab-CI上で行う

TL;DR

GitLab.comのプロジェクトで次の準備を一通り行うと、masterブランチへプッシュするたびにherokuへデプロイしてくれるようになります。

  1. HEROKU_TOKENに自身のherokuアカウントのAPIキーを登録する 1
  2. HEROKU_APPにデプロイ先となるherokuアプリケーションの名前を登録する 2
  3. .gitlab-ci.ymlに次のタスクをコピペする
.gitlab-ci.yml
push-heroku:
  only:
    - master
  image: docker:stable
  services:
    - docker:dind
  script:
    - echo $HEROKU_TOKEN | docker login --username=_ --password-stdin registry.heroku.com
    - docker build -t registry.heroku.com/$HEROKU_APP/web .
    - docker push registry.heroku.com/$HEROKU_APP/web

本文

何故やりたくなったのか

すごくコンパクトな自分用Webサービスの動作環境として、最近herokuを主に使っています。
普段プロジェクト管理はGitLab.comを使っているのですが、せっかくなので"Heroku Git"へではなく"Container Registry"にデプロイしてみることにしました。

HerokuのContainer Registryの仕組み

仕組みといっても、Heroku Gitと表面的には大きな違いがあるわけではありません。
Heroku Gitはプッシュすると、向こう側でBuildpackベースでアプリが動くようになるのに対して、Container Registryは手元でビルドしたDockerイメージをプッシュして、そのコンテナをそのまま動かすようにできています。

Webアプリ用のポートを環境変数から受け取って待ち受けたり、HTTP/HTTPSをX-Forwarded-Protoで判別するあたりは変わらないです。

基本的には、Heroku-CLIを標準的な取扱方法としており、heroku container:push webを実行すると
1. docker build in local
2. docker push to heroku container registory
3. docker run in heroku
4. をやっていくような感じっぽいです。

さて、ここでのDockerイメージのプッシュ対象となるContainer Registryはregistry.heroku.comです。
そして、各アプリの動かすときのイメージ名はregistry.heroku.com/<app>/<process-type>と定められてます。
サイトにはRegistryへのdocker-loginの方法にheroku container:loginだけでなく通常のdocker loginも併記されており、Heroku-CLIは別に必要ないことがわかります。

GitLab-CIでDocker pushを実現する

というわけで、GitLab-CIの仕組みでContainerRegistryへプッシュするまでを作りました。

Herokuの準備

Herokuの側から事前に確認しておくべき点は、次の2個です。

  • 自分のアカウントのAPI Key
  • デプロイする先のアプリケーション名

.gitlab-ci.ymlの中身(タスク設定)

gitlab-runnerはservicesの概念により、プロジェクトコード用のタスクの裏にDocker in Docker(dind)を動かしてdocker buildを実行してビルドができます。

  image: docker:stable
  services:
    - docker:dind

dockerコマンド用にdocker:stableイメージを、dockerビルド環境用にdocker:dindサービスを指定します。

docker loginにはCIなどでパスワードなどを公開しないようにする、--password-stdinオプションがあります。
これを利用すると、docker loginの前にパスワードをechoすることができるようになり、パスワードを出さずに済むようになります。

  script:
    - echo $HEROKU_TOKEN | docker login --username=_ --password-stdin registry.heroku.com

API Keyをパスワードに使うことで、usernameを_にすることが可能です。

  script:
    (略)
    - docker build -t registry.heroku.com/$HEROKU_APP/web .
    - docker push registry.heroku.com/$HEROKU_APP/web

あとは、GitLab Registry向けにbuild+pushするのと同じようにタスク設定することで、Heroku上にDockerコンテナ型のアプリをデプロイすることができるようになります。
便利ですね。

参考リンク


  1. CI/CD設定の、Secret Variablesの利用を推奨します 

  2. .gitlab-ci.ymlへのベタ書きは推奨しません