Nokogiriのインストール時に発生するエラー解消方法の説明

# はじめに
`bundle update ...`をすると、必ず`nokogiri`のインストールでエラーが出てしまい、アップデートできませんでした...。
今回は、その時に出たエラーの内容と解消法を説明しようと思います。

# Nokogiri とは

エラー内容の共有の前に、Nokogiriについて、簡単に説明しようと思います。

https://nokogiri.org/index.html

Nokogiriとは、DOM操作するためのRubyのGemです。
使用すると、Ruby から XML と HTML を簡単に操作できるようになります。

Rubyでスクレイピングをする際は、よく使用されると思います。

続いて、今回`bundle update ...`をした際のエラーを共有します。


# エラー内容

```shell
Installing nokogiri 1.13.10 (was 1.12.5) with native extensions
 Gem::Ext::BuildError: ERROR: Failed to build gem native extension.
 
     current directory: /app/vendor/bundle/gems/nokogiri-1.13.10/ext/nokogiri
 /usr/local/bin/ruby -I /usr/local/lib/ruby/2.6.0 -r ./siteconf20240321-2435-1qo43vm.rb extconf.rb
 checking for whether -std=c99 is accepted as CFLAGS... yes
 checking for whether -Wno-declaration-after-statement is accepted as CFLAGS... yes
 checking for whether -g is accepted as CFLAGS... yes
 checking for whether -Winline is accepted as CFLAGS... yes
 checking for whether -Wmissing-noreturn is accepted as CFLAGS... yes
 Building nokogiri using packaged libraries.
 Static linking is enabled.
 Cross build is disabled.
 Using mini_portile version 2.8.5
 checking for iconv... yes
 ---------- IMPORTANT NOTICE ----------
 Building Nokogiri with a packaged version of libxml2-2.10.3.
 Configuration options: --host\=x86_64-pc-linux-musl --enable-static --disable-shared --libdir\=/app/vendor/bundle/gems/nokogiri-1.13.10/ports/x86_64-linux-musl/libxml2/2.10.3/lib --with-iconv\=yes --disable-dependency-tracking --without-python
 --without-readline --with-c14n --with-debug --with-threads --disable-shared --enable-static CFLAGS\=-O2\ -U_FORTIFY_SOURCE\ -g\ -fPIC
 The following patches are being applied:
   - 0001-Remove-script-macro-support.patch
   - 0002-Update-entities-to-remove-handling-of-ssi.patch
   - 0003-libxml2.la-is-in-top_builddir.patch
   - 0005-avoid-isnan-isinf.patch
   - 0009-allow-wildcard-namespaces.patch
 
 The Nokogiri maintainers intend to provide timely security updates, but if
 this is a concern for you and want to use your OS/distro system library
 instead, then abort this installation process and install nokogiri as
 instructed at:
 
   https://nokogiri.org/tutorials/installing_nokogiri.html#installing-using-standard-system-libraries
 
 Note, however, that nokogiri cannot guarantee compatibility with every
 version of libxml2 that may be provided by OS/package vendors.
 
 [{:url=>
    "https://mirror.csclub.uwaterloo.ca/gnome/sources/libxml2/2.10/libxml2-2.10.3.tar.xz",
   :sha256=>"5d2cc3d78bec3dbe212a9d7fa629ada25a7da928af432c93060ff5c17ee28a9c"}]
 Extracting libxml2-2.10.3.tar.xz into tmp/x86_64-pc-linux-musl/ports/libxml2/2.10.3... ERROR. Please review logs to see what happened:
 ----- contents of '/app/vendor/bundle/gems/nokogiri-1.13.10/ext/nokogiri/tmp/x86_64-pc-linux-musl/ports/libxml2/2.10.3/extract.log' -----
 tar (child): xz: Cannot exec: No such file or directory
 tar (child): Error is not recoverable: exiting now
 tar: Child returned status 2
 tar: Error is not recoverable: exiting now
 ----- end of file -----
 *** extconf.rb failed ***
 Could not create Makefile due to some reason, probably lack of necessary
 libraries and/or headers.  Check the mkmf.log file for more details.  You may
 need configuration options.
 
 Provided configuration options:
         --with-opt-dir
         --without-opt-dir
         --with-opt-include
         --without-opt-include=${opt-dir}/include
         --with-opt-lib
         --without-opt-lib=${opt-dir}/lib
         --with-make-prog
         --without-make-prog
         --srcdir=.
         --curdir
         --ruby=/usr/local/bin/$(RUBY_BASE_NAME)
         --help
         --clean
         --prevent-strip
         --enable-system-libraries
         --disable-system-libraries
         --use-system-libraries
         --enable-system-libraries
         --disable-system-libraries
         --use-system-libraries
         --enable-static
         --disable-static
         --enable-cross-build
         --disable-cross-build
         --with-zlib-dir
         --without-zlib-dir
         --with-zlib-include
         --without-zlib-include=${zlib-dir}/include
         --with-zlib-lib
         --without-zlib-lib=${zlib-dir}/lib
         --with-xml2-source-dir
 /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:612:in `block in execute': Failed to complete extract task (RuntimeError)
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:578:in `chdir'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:578:in `execute'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:564:in `extract_file'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:138:in `block in extract'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:136:in `each'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:136:in `extract'
         from /app/vendor/bundle/gems/mini_portile2-2.8.5/lib/mini_portile2/mini_portile.rb:231:in `cook'
         from extconf.rb:529:in `block (2 levels) in process_recipe'
         from extconf.rb:309:in `chdir'
         from extconf.rb:309:in `chdir_for_build'
         from extconf.rb:529:in `block in process_recipe'
         from extconf.rb:428:in `tap'
         from extconf.rb:428:in `process_recipe'
         from extconf.rb:782:in `<main>'
 
 To see why this extension failed to compile, please check the mkmf.log which can be found here:
 
   /app/vendor/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.13.10/mkmf.log
 
 extconf failed, exit code 1
 
 Gem files will remain installed in /app/vendor/bundle/gems/nokogiri-1.13.10 for inspection.
 Results logged to /app/vendor/bundle/extensions/x86_64-linux/2.6.0/nokogiri-1.13.10/gem_make.out
 
 An error occurred while installing nokogiri (1.13.10), and Bundler cannot continue.
 Make sure that `gem install nokogiri -v '1.13.10' --source 'https://rubygems.org/'` succeeds before bundling.
 
 In Gemfile:
   ・・・
   nokogiri
```

:::note warn
一部内容を省いています。
ですが、エラー内容に関しては内容を省いていないので、問題ございません。
:::

とても長いですね...。
今回は、`bundle update`の対象となっているGemで`nokogiri`を使用しているため、エラーとなりました。

ただよく見ると、エラー出ている原因をちゃんと説明してくれています。

```shell
tar (child): xz: Cannot exec: No such file or directory
tar (child): Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error is not recoverable: exiting now
```

`xz`コマンドを実行しようとしたら、`xz`が入っておらず、エラーになっているみたいです。
おそらく`nokogiri`をインストールする際に、`.xz`拡張子に圧縮されているファイルを、解凍するために必要だと思われます。


# 解決方法

`Dockerfile`で、`apk add`している箇所に、`xz`を追加するだけで、エラーは解消され、無事`bundle update`することが出来ました。

```dockerfile
apk add --no-cache ... xz
```

:::note alert
現在（2024/04/01）で、`xz`に関して、脆弱性が確認されています。
バージョンにはお気をつけください。
https://zenn.dev/levtech/articles/1dda57cac26d78
:::


# まとめ
解決自体はとても簡単ですが、ここまで辿り着くのに、かなり時間がかかってしまいました...。
エラー解決には、ログを見るのが一番だなと改めて思いました。

`nokogiri`のインストールでエラーになる内容で検索すると、結構以下の箇所がおかしいと言われる気がします。

```shell
Make sure that `gem install nokogiri -v '1.13.10' --source 'https://rubygems.org/'` 
```

ただ、今回の内容とは全く関係がありませんでした...。
エラーがかなり長い内容でも、しっかり目を通せば、解決の糸口は記載されているので、諦めずにゆっくり読んでいきましょう。

最後まで、ご覧いただき、ありがとうございました。