プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Netlify のビルドイメージを更新 : Ubuntu 14.04 (Trusty) -> 20.04 (Focal)

先日、森ソフトのサイトをホストしている Netlify からメールが来ました。

ざっと要約すると、

いまホストしているサイトのビルドイメージが古くて、2021/9/19 に廃止するから、新しいビルドイメージに更新してね

ということでした。

Netlify でホストする時にビルドイメージなんて選択した記憶なかったんですが、デフォルトのビルドイメージが使われていて、それが Ubuntu 14.04 ベースだったようです。 Ubuntu 14.04 自体も、2019年にサポートが切れているので、まあそうなりますよね。

ということで、早速 Netlify 公式にビルドイメージの更新方法が載っていたのでその通りに試したところ、若干トラブルがあったので、解決方法をまとめておきます。

新しいビルドイメージでビルドできない

まずは、公式の手順通りにテストビルドを試してみます。

  1. Netlify にログインします。
  2. 対象サイトを選択します。
  3. 現在公開中の deploy を選択します(Publishedのバッジがついてます)。 f:id:junichim:20210730114323p:plain
  4. 『Lock publishing to this deploy』ボタンを押して、公開バージョンを、固定します。 f:id:junichim:20210730114422p:plain
  5. 『Deploy settings』ボタンを押します。
  6. 『Build image selection』を表示します。 f:id:junichim:20210730114740p:plain
  7. 『Edit Settings』を押すと、ビルドイメージ選択画面が表示されるので、今回は 20.04 を選択して、 Save します。 f:id:junichim:20210730114842p:plain
  8. 『Deploys』に戻り、『Trigger Deploy』を押します。この時、念のため『Clear cache and deploy site』を選択しました。
  9. ビルドが成功する... はずでしたが、失敗しました。

失敗した deploy のログを見ると、どうも ruby のインストールのところでこけているようです。 さて、困ったぞ。

ちなみに、失敗時のログは下記になりました。

10:29:18 AM: Build ready to start
10:29:20 AM: build-image version: 24d1ae1bfefc10e86e0c51980ba04d0882863fbd
10:29:20 AM: build-image tag: v4.0.6
10:29:20 AM: buildbot version: 32c566c80353626250182ad07e5aebc8ea63cd0e
10:29:20 AM: Building without cache
10:29:20 AM: Starting to prepare the repo for build
10:29:21 AM: No cached dependencies found. Cloning fresh repo
10:29:21 AM: git clone git@bitbucket.org:junichim/mywebsite
10:29:34 AM: Preparing Git Reference refs/heads/master
10:29:35 AM: Parsing package.json dependencies
10:29:36 AM: Different publish path detected, going to use the one specified in the Netlify configuration file: 'public' versus 'public/' in the Netlify UI
10:29:36 AM: Starting build script
10:29:36 AM: Installing dependencies
10:29:36 AM: Python version set to 2.7
10:29:37 AM: Downloading and installing node v6.17.1...
10:29:37 AM: Downloading https://nodejs.org/dist/v6.17.1/node-v6.17.1-linux-x64.tar.xz...
10:29:37 AM: Computing checksum with sha256sum
10:29:37 AM: Checksums matched!
10:29:39 AM: Now using node v6.17.1 (npm v3.10.10)
10:29:40 AM: Started restoring cached build plugins
10:29:40 AM: Finished restoring cached build plugins
10:29:40 AM: Attempting ruby version 2.3.6, read from environment
10:29:41 AM: Required ruby-2.3.6 is not installed - installing.
10:29:41 AM: Searching for binary rubies, this might take some time.
10:29:42 AM: Found remote file https://rvm_io.global.ssl.fastly.net/binaries/ubuntu/20.04/x86_64/ruby-2.3.6.tar.bz2
10:29:42 AM: Checking requirements for ubuntu.
10:29:43 AM: Missing required packages: libssl1.0-dev
10:29:43 AM: RVM autolibs is now configured with mode '2' =>
10:29:43 AM:   'Allow RVM to use package manager if found, fail if dependencies are missing. This is default.',
10:29:43 AM: please run `rvm autolibs enable` to let RVM do its job or run and read `rvm autolibs [help]`
10:29:43 AM: or visit https://rvm.io/rvm/autolibs for more information.
10:29:43 AM: Found undesired packages: libssl-dev
10:29:43 AM: RVM autolibs is now configured with mode '2' =>
10:29:43 AM:   'Allow RVM to use package manager if found, fail if dependencies are missing. This is default.',
10:29:43 AM: please run `rvm autolibs enable` to let RVM do its job or run and read `rvm autolibs [help]`
10:29:43 AM: or visit https://rvm.io/rvm/autolibs for more information.
10:29:43 AM: Requirements installation failed with status: 1.
10:29:43 AM: ruby-2.3.6 - #gemset created /opt/buildhome/.rvm/gems/ruby-2.3.6
10:29:43 AM: Required ruby-2.3.6 is not installed - installing.
10:29:43 AM: Searching for binary rubies, this might take some time.
10:29:43 AM: Found remote file https://rvm_io.global.ssl.fastly.net/binaries/ubuntu/20.04/x86_64/ruby-2.3.6.tar.bz2
10:29:43 AM: Checking requirements for ubuntu.
10:29:44 AM: Missing required packages: libssl1.0-dev
10:29:44 AM: RVM autolibs is now configured with mode '2' =>
10:29:44 AM:   'Allow RVM to use package manager if found, fail if dependencies are missing. This is default.',
10:29:44 AM: please run `rvm autolibs enable` to let RVM do its job or run and read `rvm autolibs [help]`
10:29:44 AM: or visit https://rvm.io/rvm/autolibs for more information.
10:29:44 AM: Found undesired packages: libssl-dev
10:29:44 AM: RVM autolibs is now configured with mode '2' =>
10:29:44 AM:   'Allow RVM to use package manager if found, fail if dependencies are missing. This is default.',
10:29:44 AM: please run `rvm autolibs enable` to let RVM do its job or run and read `rvm autolibs [help]`
10:29:44 AM: or visit https://rvm.io/rvm/autolibs for more information.
10:29:44 AM: Requirements installation failed with status: 1.
10:29:44 AM: ruby-2.3.6 - #importing gemsetfile /opt/buildhome/.rvm/gemsets/default.gems evaluated to empty gem list
10:29:44 AM: ruby-2.3.6 - #generating default wrappers.................
10:29:44 AM: Error running 'run_gem_wrappers regenerate',
10:29:44 AM: please read /opt/buildhome/.rvm/log/1627608584_ruby-2.3.6/gemset.wrappers.default.log
10:29:44 AM: Using /opt/buildhome/.rvm/gems/ruby-2.3.6
10:29:44 AM: Warning! Executable 'ruby' missing, something went wrong with this ruby installation!
10:29:44 AM: Warning! Executable 'gem' missing, something went wrong with this ruby installation!
10:29:44 AM: Warning! Executable 'irb' missing, something went wrong with this ruby installation!
10:29:44 AM: Using ruby version 2.3.6
10:29:44 AM: /opt/buildhome/.rvm/scripts/override_gem: line 19: gem: command not found
10:29:44 AM: Error installing bundler
10:29:44 AM: Build was terminated: Build script returned non-zero exit code: 1
10:29:44 AM: Creating deploy upload records
10:29:44 AM: Failing build: Failed to build site
10:29:44 AM: Failed during stage 'building site': Build script returned non-zero exit code: 1
10:29:44 AM: Finished processing build request in 24.47634162s

テストサイトを立ち上げる

何が原因か調べるために、Netlify の手順に新しくサイトを作って試す(リンク先の6番ですね)、というのがあるので、これをやってみます。

デフォルトで、新しくサイトを作成すると、あら不思議、問題なく deploy できました。ビルドイメージに何が使われているのか調べると、 16.04 (Xenial) になってました。 ビルドイメージの違いかな?と思ったので、この状態で 20.04 を選択し直して、再 deploy しても問題なく deploy に成功します。

はて、なぜでしょうか?

この時のログを見ると

10:53:20 AM: Build ready to start
10:53:22 AM: build-image version: 24d1ae1bfefc10e86e0c51980ba04d0882863fbd
10:53:22 AM: build-image tag: v4.0.6
10:53:22 AM: buildbot version: 32c566c80353626250182ad07e5aebc8ea63cd0e
10:53:22 AM: Building without cache
10:53:22 AM: Starting to prepare the repo for build
10:53:23 AM: No cached dependencies found. Cloning fresh repo
10:53:23 AM: git clone git@bitbucket.org:junichim/mywebsite
10:53:24 AM: Preparing Git Reference refs/heads/master
10:53:26 AM: Parsing package.json dependencies
10:53:27 AM: Starting build script
10:53:27 AM: Installing dependencies
10:53:27 AM: Python version set to 2.7
10:53:28 AM: v12.18.0 is already installed.
10:53:29 AM: Now using node v12.18.0 (npm v6.14.4)
10:53:29 AM: Started restoring cached build plugins
10:53:29 AM: Finished restoring cached build plugins
10:53:29 AM: Attempting ruby version 2.7.2, read from environment
10:53:31 AM: Using ruby version 2.7.2
10:53:31 AM: Using PHP version 7.4
10:53:31 AM: Started restoring cached go cache
10:53:31 AM: Finished restoring cached go cache
10:53:31 AM: go version go1.14.4 linux/amd64
10:53:31 AM: go version go1.14.4 linux/amd64
10:53:31 AM: Installing missing commands
10:53:31 AM: Verify run directory
10:53:32 AM: ​
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM:   Netlify Build                                                 
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM: ​
10:53:32 AM: ❯ Version
10:53:32 AM:   @netlify/build 17.2.0
10:53:32 AM: ​
10:53:32 AM: ❯ Flags
10:53:32 AM:   deployId: 61035b90d52294c3e5394973
10:53:32 AM: ​
10:53:32 AM: ❯ Current directory
10:53:32 AM:   /opt/build/repo
10:53:32 AM: ​
10:53:32 AM: ❯ Config file
10:53:32 AM:   No config file was defined: using default values.
10:53:32 AM: ​
10:53:32 AM: ❯ Context
10:53:32 AM:   production
10:53:32 AM: ​
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM:   1. Build command from Netlify app                             
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM: ​
10:53:32 AM: $ hugo
10:53:32 AM: Start building sites …
10:53:32 AM: WARN 2021/07/30 01:53:32 Page.Hugo is deprecated and will be removed in a future release. Use the global hugo function.
10:53:32 AM:                    | JA
10:53:32 AM: -------------------+-----
10:53:32 AM:   Pages            | 24
10:53:32 AM:   Paginator pages  |  2
10:53:32 AM:   Non-page files   |  0
10:53:32 AM:   Static files     | 86
10:53:32 AM:   Processed images |  0
10:53:32 AM:   Aliases          |  4
10:53:32 AM:   Sitemaps         |  1
10:53:32 AM:   Cleaned          |  0
10:53:32 AM: Total in 106 ms
10:53:32 AM: ​
10:53:32 AM: (build.command completed in 371ms)
10:53:32 AM: ​
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM:   2. Deploy site                                                
10:53:32 AM: ────────────────────────────────────────────────────────────────
10:53:32 AM: ​
10:53:32 AM: Starting to deploy site from 'public'
10:53:32 AM: Creating deploy tree 
10:53:32 AM: Creating deploy upload records
10:53:32 AM: 22 new files to upload
10:53:32 AM: 0 new functions to upload
10:53:33 AM: Site deploy was successfully initiated
10:53:33 AM: ​
10:53:33 AM: (Deploy site completed in 971ms)
10:53:33 AM: ​
10:53:33 AM: ────────────────────────────────────────────────────────────────
10:53:33 AM:   Netlify Build Complete                                        
10:53:33 AM: ────────────────────────────────────────────────────────────────
10:53:33 AM: ​
10:53:33 AM: (Netlify Build completed in 1.4s)
10:53:33 AM: Starting post processing
10:53:33 AM: Caching artifacts
10:53:33 AM: Started saving build plugins
10:53:33 AM: Finished saving build plugins
10:53:33 AM: Started saving pip cache
10:53:33 AM: Post processing - HTML
10:53:34 AM: Finished saving pip cache
10:53:34 AM: Started saving emacs cask dependencies
10:53:34 AM: Finished saving emacs cask dependencies
10:53:34 AM: Started saving maven dependencies
10:53:34 AM: Finished saving maven dependencies
10:53:34 AM: Started saving boot dependencies
10:53:34 AM: Finished saving boot dependencies
10:53:34 AM: Started saving rust rustup cache
10:53:34 AM: Finished saving rust rustup cache
10:53:34 AM: Started saving go dependencies
10:53:34 AM: Finished saving go dependencies
10:53:35 AM: Post processing - header rules
10:53:35 AM: Post processing - redirect rules
10:53:35 AM: Post processing done
10:53:35 AM: Site is live ✨
10:53:37 AM: Build script success
10:53:47 AM: Finished processing build request in 25.098250576s

ruby のバージョンが違いますね。

あと、このテストサイトでは、 Hugo のバージョン指定も行っていませんでした(既存サイトは 0.77 で固定)。 Hugo のほうは、既存のバージョンと同じ 0.77 を指定してみて、もう一度 deploy を試すと、問題なく deploy に成功しますね。

ということで、どこかで ruby まわりの依存関係の問題が起こっているようです。

あと、 hugo そのものは、 ruby の依存性を持っていないようなので、なんでこれがインストールされるのか、というところも疑問です。

デフォルトの依存関係について

ということで、Netlify の依存関係について改めて調べてみました。

まず、 Netlify の手順を改めて読みなおすと、新しいビルドイメージで動かすためのステップのところに、

Note: if the dependency version was not explicitly set by you, then it’s set to a version selected by default when you created your site. You can “reset” this default version selection by re-linking your site repository. Go to Site settings > Build & deploy > Build settings , select Link to a different repository , and then select the same repository and build settings.

とあります。

明示していない依存関係は、サイト構築時に決まる、ということのようです。

さらに、少しググると、 Netlify のドキュメントに、ビルドイメージが持っている依存性についての記事がありました。 これを見ると、 ビルとイメージ自体が、 ruby をはじめとするいくつかのアプリケーションをデフォルトでインストールするようです。

なるほど。Netlify では、構築積みのサイトについて、この依存関係を明示的に表示する方法は提供されていない(っぽい)ので、あくまでも推測になりますが、

  • サイトを構築する。当時のデフォルトのビルドイメージは Ubuntu 14.04 。
  • 14.04 のビルドイメージとその当時のバージョンを元に依存関係が設定される
  • ビルドイメージを 20.04 に変更する
  • 依存関係はサイト構築時のものが使われる
  • 20.04 ではサポートされていないバージョンが含まれているため、エラーになる

ということではないでしょうか? (もっとも、ログを見ると、最後のところは、もうちょっと複雑で ruby が依存している libssl1.0-dev が見つからない、というもののようです。でも、私のような一般ユーザーからすると同じようなものですが。)

ちなみに、github には各ビルドイメージがサポートしているバージョンなどの情報も載ってますので、ご参考にしてください(過去のもありましたよ)。

解決策

ということで、 hugo の問題ではなく、ビルドイメージの持つ依存性が問題のようなので、この依存性を一度リセットしてやれば、良さそうです。

Netlify のガイドを見ると、このやり方も載っていました(似たようなトラブルがよくあるんでしょうね、きっと)。

  1. 設定済みの環境変数があれば、保存しておく(『Site settings』->『Build & Deploy』 -> 『Environment』で確認できます)(megane42 さんご指摘ありがとうございます!)
  2. 『Site settings』->『Build & Deploy』を選択する
  3. 『Build settings』で『Edit settings』ボタンを押す f:id:junichim:20210730125037p:plain
  4. Repositoryにある『Link to a different repository』をクリックする f:id:junichim:20210730125258p:plain
  5. 同じリポジトリを指定し、『Deploy site』ボタンを押す

とすればよいようです。

で、実際に試してみると、

f:id:junichim:20210730125709p:plain

となり、問題なく deploy に成功しました。わかってしまえば簡単ですね。

後始末

最後に、後始末として、 『Deploys』を開き、『Start auto publishing』を押し、自動での公開を有効にします。

f:id:junichim:20210730125942p:plain

とはいえ、この設定は deploy しないと働かないので、新しいビルドイメージで作成した deploy と既存の Published の deploy は、ずれたままです。これも修正するなら、もう一度 『Trigger Deploys』を実行すれば、新しいビルドイメージで作成した deploy が公開されます。

f:id:junichim:20210730130647p:plain

OKですね。あとは、テスト用に作成したサイトも削除しておきます。

これで、無事にビルドイメージの移行ができました。よかった、よかった。