M1 MacでHerokuにデプロイする手順


TL;DR

M1 MacでHeorkuにデプロイするときは、Rosettaかますんやで。
Dockerイメージを使用するときはマルチプラットフォームイメージをビルドするプラグインを使用してな!
※2021/5/22時点の情報です。

はじめに

M1のMacを使用しているのですが、Herokuデプロイ時に詰まりに詰まり苦労したので、同じようなことで挫折しないためにも備忘として記載していきます。

まず簡単な前提ですが、以下の内容でタイトルの通りHerokuにデプロイしていきます。

  1. とりあえず、M1のことを考えずにドキュメント通りにデプロイしてみる(エラーの確認)
  2. Deploy to Heroku From a MacBook M1: Heroku CLI or GitHubActionsを参考に1で確認したエラーを解決していく!
  3. Dockerもこちらの記事を参考にしていきますよ

※2021/5/22時点の情報です。

とりあえずデプロイ(エラーの確認)

繰り返しになりますが、ここではContainer Registry & Runtime (Docker Deploys)を参考に進めていきます!(Herokuアカウント登録している前提で)

まず、Getting startedということで、

$ heroku container:login

Herokuコンテナにログインしていきましょう。

ここでは何も起こらず、おそらく以下のように成功すると思います。

Login Succeeded

次にサンプルコードをクローンしていきます!

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

クローンができていれば、以下のような感じで表示されるはずです。

Cloning into 'alpinehelloworld'...
remote: Enumerating objects: 59, done.
remote: Total 59 (delta 0), reused 0 (delta 0), pack-reused 59
Receiving objects: 100% (59/59), 7.65 KiB | 1.91 MiB/s, done.
Resolving deltas: 100% (17/17), done.

(心配な場合はlsコマンドで確認してみてください〜)

そして、クローンしたディレクトリ(alpinehelloworld)に移動していきましょう!

$ cd alpinehelloworld

移動できましたら、Herokuアプリを作っていきます!

$ heroku create

アプリが作成できましたら、以下のように表示されます。

Creating app... done, ⬢ ※アプリ名
https://※アプリ名.herokuapp.com/ | https://git.heroku.com/※アプリ名.git

※はHeroku側で作られたアプリ名となっており、それぞれcreateしたときに違う名前がつけられています。

続いて、アプリのイメージをコンテナレジストリにビルドして、プッシュしていきます!

$ heroku container:push web

以下のような表示がされれば成功していると思われます。

Your image has been successfully pushed. You can now release it with the 'container:release' command.

次はコンテナのイメージからアプリをリリースしていきます!

$ heroku container:release web

リリースできた場合、以下のように表示されます!

Releasing images web to アプリ名... done

あれ?M1 Macでも余裕でデプロイできるんちゃう?
では、デプロイしたアプリをみていきましょう!

$ heroku open

Application error
An error occurred in the application and your page could not be served. If you are the application owner, check your logs for details. You can do this from the Heroku CLI with the command
heroku logs --tail

はい、ここでエラーきました。本来なら、Hello Worldが表示されるはずです。

ちなみに heroku logs --tailで内容確認しても僕には何もわかりませんでした。

とはいえ諦めずアプリをHerokuを動かせるようにするため色々調べていきましょう!

エラーを解決していく!

とりあえず、「Heroku M1 Deploy」で検索してみます!

そうすると、以下の記事にたどり着くと思います!

英語ですが、頑張って読んでいきましょう!

どうやらこの記事は、Rosettaを使用してHerokuのCLI操作する方法とGithubActionsのパイプラインの作成を説明してくれてるっぽいですね!

・ using Heroku Command Line Interface (with Rosetta)
・ creating a GitHubActions pipeline

今回は前者の「Rosettaを使用してHerokuのCLI操作する方法」が関係してくるっぽいので、こちらのみを参考にさせていただきましょう!

さていきなり重要な情報ですが、まだM1はHeroku CLIに対応していないらしいです。おそらくそのため先程のエラーが出たのだと思われます。

Heroku CLI with Rosetta
The Heroku CLI is not yet natively running on the Apple M1 chip, therefore the only option at the moment is to install and run it with Rosetta (Rosetta is the translation process that allows applications designed for Intel processors to run apps on Apple silicon).

ただ、Rosettaを使用すれば、Heroku CLIを実行できるようですね!

ということで、Rosettaを有効にしていきましょう!

Finder > アプリケーション > ユーティリティ > ターミナル

でターミナルを見つけて、右クリックをします。
その後「情報を見る」を開き、Rosettaを有効にします。
(ターミナル複製して片方だけRosettaを有効にするのも良いですね)

Rosettaは手動でもインストールできるらしいので、そうしたい場合は以下のコマンドからインストールするらしいですね。(ディレクトリはalpinehelloworld)

$ /usr/sbin/softwareupdate --install-rosetta

ここで、brewを再度インストールするっぽいですね!

記事にはこんな感じで書かれてます。

If you have installed Homebrew earlier (before enabling Rosetta) you have already downloaded M1 compatible packages in your Mac. Try

$ which brew
/opt/homebrew/bin/brew

とりあえず、which brewを叩いて、「/opt/homebrew/bin/brew」という結果が返ってくるか確認してみましょう。

上記を確認しましたら、Rosettaを有効にしたターミナルでHomebrewを再インストールしていきます!

$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
==> Checking for `sudo` access (which may request your password).
sudo: /var/db/sudo/ts is owned by uid 501, should be 0

パスワードを入力し、
再度パスワードを求められるので、パスワードを入力し、

==> This script will install:
/opt/homebrew/bin/brew
/opt/homebrew/share/doc/homebrew
/opt/homebrew/share/man/man1/brew.1
/opt/homebrew/share/zsh/site-functions/_brew
/opt/homebrew/etc/bash_completion.d/brew
/opt/homebrew
==> The following new directories will be created:
/opt/homebrew/Caskroom

Press RETURN to continue or any other key to abort

とりあえずEnterを押します。

また、パスワードを求められたので、パスワード入力します。
何度もパスワード求められるかもしれませんが、めげずにパスワードを入力します。(sudoのアクセスチェックです。)

==> Installation successful!

これが表示されたら、インストール成功です!

そしたらこの記事によるとエイリアスを作成すると色々楽になって良いとのことなので、それに従いエイリアスを作っていきます。

$ alias rbrew='/usr/local/bin/brew'

rbrewとbrewの確認をしていきましょうか。

Rosettaを有効にしたbrew

$ which rbrew
rbrew: aliased to /usr/local/bin/brew

ネイティブ(Intelじゃない方)なbrew

$ which brew

/opt/homebrew/bin/brew

上記確認しましたら、Herokuをインストールしていきます。
(おそらく再インストールって感じですかね)

$ rbrew tap heroku/brew && rbrew install heroku

Herokuを既にインストールしている人は以下のようなエラーが出るはずです

Error: heroku 7.53.1 is already installed
To upgrade to 7.54.0, run:
  brew upgrade heroku/brew/heroku

アップグレードする場合は、

$ brew upgrade heroku/brew/heroku

を打てとのことなので、とりあえず打っときますか

そうすると、またエラーが、、、

Cannot install under Rosetta 2 in ARM default prefix (/opt/homebrew)!
To rerun under ARM use:
    arch -arm64 brew install ...
To install under x86_64, install Homebrew into /usr/local.

インストールするんだったら、「arch -arm64 brew install」を頭につけろよって言われてます。
(「To instal under ~」は一旦ここでは無視)

とのことなのでつけましょう。

$ arch -arm64 brew install heroku/brew/heroku

またエラーです、、、

heroku 7.53.1 is already installed
To upgrade to 7.54.0, run:
  brew upgrade heroku/brew/heroku

既にインストールするから、アップグレードにしてくれや!とのことです。
だったら先にそれ言ってや〜って感じですが、気を取り直して

$ arch -arm64 brew upgrade heroku/brew/heroku

これでいけるはずです。
僕は既にこの工程を終了しているので、以下のように出力されますが、他の人もダウンロード完了していると思います

Already downloaded

とりあえずHerokuコマンド打ってみますか!

$ heroku --version 
heroku/7.54.0 darwin-x64 node-v12.21.0

行けてるっぽいですね!
一応リフレッシュとかもしときますか

$ heroku autocomplete --refresh-cache
Building the autocomplete cache... done

これで先程のエラー原因となっていた、M1がHeroku CLIに対応していないということを解決できました!

今度こそデプロイ!

ということで、今度こそデプロイしていきましょう!
今回はDockerコンテナイメージをHerokuにプッシュしていくので、そちらを対象に進めていきます!

参考にする記事は、こちらです。

先程の記事を投稿した人の記事となっております。(ほんとにありがたいですね)

こちらの記事によりますと、Dockerコンテナのビルドとデプロイはめちゃ簡単らしいですね。以下は記事から参照した前提条件です。

・ Login into Heroku (heroku login) and Heroku Docker Registry (heroku:container login)
・ Place the Dockerfile in the root folder

一つ目がHeroku(Heroku Docker Registry)にログインしてください(heroku login or heroku:container login)。

二つ目が、ルートフォルダーにDockerfileを置いてください!(これは各自で確認お願いします)とのこと。

ということで、ログイン。

$ heroku container:login
Login Succeeded

env変数が必要な場合は以下のコマンドを打つらしいです。

$ heroku config:set PARAM="value"
Setting PARAM and restarting ⬢ アプリ名... done, v4
PARAM: value

Dockerイメージをビルドしてプッシュしましょう!

$ heroku container:push web

(アプリを指定する必要がある場合は、上記コマンド後ろに -a アプリ名をつける)

成功すると以下のように出力されます。

Your image has been successfully pushed. You can now release it with the 'container:release' command.

そして、リリースしていきましょう!

$ heroku container:release web
Releasing images web to アプリ名... done

リリースできましたね!
それでは早速アプリケーションを確認していきましょう!としたいのですが、今のままでは実は先程のエラー画面が出てきます!

次はM1かつHerokuだからというよりかは、Dockerの設定になってきますね。

ということで、こちらも解決していきましょう!

参考記事を確認していくと、どちらか二つの方法で試せ!と説明されているのでとりあえずそちらを試していきますか。

Option A: buildx
Buildx is a Docker plugin that allows, amongst other features, to build multi-platform images.
We are developing on the Mac ARM architecture but we want to create a x86 compatible image. The solution is NOT to use the heroku:container push command but rather building the image locally with Docker buildx.

Option B: set DOCKER_DEFAULT_PLATFORM
The DOCKER_DEFAULT_PLATFORM environment variable permits to set the default platform for the commands that take the --platform flag.

オプションAは、どうやらDockerのBuildxというマルチプラットフォームイメージをビルドするプラグインを利用するみたいですね。

オプションBは「DOCKER_DEFAULT_PLATFORM = linux / amd64」という環境変数を設定していくらしいです。

今回は特に理由はないですが、オプションAを試していきます!

記事の手順に沿って、

$ docker buildx build --platform linux/amd64 -t アプリ名 .

次は多分タグ付けしているだけだとは思いますが、手順通りに実行します。

$ docker tag アプリ名 registry.heroku.com/アプリ名/web

そして手順通りにマルチプラットフォームイメージでビルドされたアプリをプッシュします。

$ docker push registry.heroku.com/アプリ名/web

プッシュされたイメージをリリースしていきます。

$ heroku container:release web -a アプリ名

はい、ここでリリースされればおそらくもう大丈夫です!

ではアプリケーションを見ていきましょう!

$ heroku open 

ついに出てきました、Hello World!

成功です!

ということでM1 MacでHerokuデプロイする手順でした!
途中あえて詰まりそうなところでエラーを出すような手順を試していましたが、その辺はすみませんご容赦ください。

記事を先にわかりやすくまとめてくださった方々には感謝しかないです。ありがとうございました。
また長くなりましたが、最後まで読んでいただきありがとうございました。

参考(再掲)

Container Registry & Runtime (Docker Deploys)

Deploy to Heroku From a MacBook M1: Heroku CLI or GitHubActions

From Apple Silicon to Heroku Docker Registry Without Swearing