【UBI】Red Hatの新しい最軽量コンテナーイメージ:UBI Microの紹介

Red Hatでソリューションアーキテクトをしている田中司恩(@tnk4on)です。今回はRed Hatの新しい最軽量なコンテナーイメージについて紹介します。

UBI Microのリリース

2021年5月18日にRed Hat Enterprise Linux(以下、RHEL) 8.4がリリースされたのと同時に新しいRed Hat Universal Base Image (以下、UBI)、UBI Microがリリースされました。

RHEL 8.4のリリースに先立って投稿されたRed Hat公式ブログ記事にもUBI Microについての記載があります。

www.redhat.com

上記ブログ記事より抜粋

With RHEL 8.4, we're announcing the Red Hat Universal Base Image (UBI) Micro to help reduce the attack surface, and deliver smaller footprint images of your containerized applications. UBI Micro joins the Standard, Minimal, and Multi-service images to provide the right options for you to build your applications on.

(翻訳)RHEL 8.4 では、Red Hat Universal Base Image (UBI) Micro が発表され、攻撃対象を減らし、コンテナ化されたアプリケーションのより小さなフットプリントのイメージを提供します。UBI Micro は Standard、Minimal、Multi-service の各イメージに加えて、アプリケーションを構築するための適切なオプションを提供します。

UBI Microはすでに公開済みのUBI(Standard)、UBI Minimal、UBI Init(Multi-service)に加えて、4つ目の種類のUBIコンテナーイメージとなります。

リリース版イメージのバグ

以前からこのUBI Microの紹介をしようと思っていたのですが、実はリリース版のubi8-micro:8.4-72イメージにバグがあり、修正が完了するまで保留にしていました。 このバグは、/etc/yum.repos.dディレクトリにRed Hat社内向けのURLが含まれた*.repoファイルが含まれており、それらのファイルを取り除かないとdnfコマンドが使えないという内容でした。詳細な内容については下記Bugzilla IDのコメントで確認することができます。

これからUBI Microを使う場合はubi-micro:8.4-84以降をお使いください。

(参考)UBIについて

UBIについては詳細がまとまった電子書籍 Red Hat's Universal Base Image ebookがあります。下記の記事では電子書籍についての紹介と翻訳した目次を掲載しています。

rheb.hatenablog.com

UBI Microとは

UBI Micro
UBI Micro

UBI Microはこれまでに公開されているUBIの中で最軽量サイズのコンテナイメージになります。UBI Microの詳細はRed Hatの認定コンテナーカタログページから確認できます。

上記カタログページより抜粋

Universal Base Image Micro (UBI Micro) is a stripped down image that uses the package manager on the underlying host to install packages, typically using Buildah, or Multi-stage builds with Podman.

(翻訳)Universal Base Image Micro (UBI Micro)は、基盤となるホスト上のパッケージマネージャーを使用してパッケージをインストールするストリップダウンされたイメージで、通常はBuildah、またはPodmanを使用したマルチステージビルドを使用します。

UBIにはRHEL 7をベースにしたUBI 7とRHEL 8をベースにしたUBI 8がありますが、UBI MicroはUBI 8のみになります。

UBI 8のイメージ一覧

公開済みのUBI 8と並べてみるとUBI Microのサイズの小ささが小ささがよくわかります。

UBI 8の種類 イメージ名 サイズ
Red Hat Universal Base Image 8 ubi8/ubi 79.5 MB
(215.2 MB uncompressed)
Red Hat Universal Base Image 8 Minimal ubi8/ubi-minimal 37.7 MB
(98.2 MB uncompressed)
Red Hat Universal Base Image 8 Init ubi8/ubi-init 85.3 MB
(235.2 MB uncompressed)
Red Hat Universal Base Image 8 Micro ←🆕 ubi8/ubi-micro 12.9 MB
(35.0 MB uncompressed)

UBI Microをコンテナのベースイメージ使用することでUBI Minimalよりさらにサイズを抑えたコンテナイメージの作成が可能です。

DistrolessなUBI Microの特徴

UBI MicroにはUBI/UBI Minimal/Initにあるようなパッケージマネージャー(dnf/microdnf)がありません。パッケージマネージャーと関連する依存関係を除外することでサイズを抑えることができています。このようにディストリビューションのパッケージ管理ツールを使用せずにコンテナイメージを構築するのはDistrolessとも呼ばれます*1。UBI MicroはホストOSのdnfコマンドを使ってパッケージの追加を行います(詳細は後述)。UBI Microは他のUBIイメージと同様の品質を保ちながらサイズを最小化したい場合に有効です。コンテナのサイズが小さくなるといことは悪意のある攻撃者から攻撃範囲を減らすことにもなりセキュリティ面でも有利です。

UBI Microを使ってみる

UBI MicroはこれまでのUBIと同様の方法でコンテナの操作が可能です。UBI Microのイメージ取得はRed HatのサイトだけでなくDocker Hubからも可能です。

# podman pull registry.access.redhat.com/ubi8/ubi-micro
# podman images --filter label=name=ubi8/ubi-micro
REPOSITORY                                 TAG         IMAGE ID      CREATED      SIZE
registry.access.redhat.com/ubi8/ubi-micro  latest      c5ba898d3645  2 weeks ago  38.9 MB
# podman run --rm -it ubi-micro
sh-4.4#
sh-4.4# dnf;microdnf
sh: dnf: command not found
sh: microdnf: command not found

UBI Micro上のシェルに入ることはできますが、dnfやmicrodnfなどのパッケージマネージャーは存在しないことが確認できます

UBI Microにパッケージを追加する

UBI Microにパッケージを追加するにはBuildahを使用します。事前にBuildahまたはContainer Toolsモジュールをインストールしておいてください。 手順についてはRHEL 8のドキュメントに記載があります。下記も参考にしてください。

下記の例ではUBI Microにpython39を追加します。なお下記例で実行はrootモードで行っていますが、ルートレスモードで実行する場合は事前にbuildah unshareを実行して名前空間に入ってから作業してください。 また、ホストOSにRHEL(またはCentOS Stream)が必要です*2。

# containername=ubi-micro-python
# microcontainer=$(buildah from --name ${containername} registry.access.redhat.com/ubi8/ubi-micro)
# micromount=$(buildah mount ${microcontainer})

# dnf install \
>     --installroot ${micromount} \
>     --releasever 8 \
>     --setopt install_weak_deps=false \
>     --nodocs -y \
>     python39
# dnf clean all \
    --installroot ${micromount}

# buildah umount ${microcontainer}
# buildah commit ${microcontainer} ${containername}
# buildah rm ${containername} 

ビルド後のイメージの確認

# podman images --filter label=name="ubi8/ubi-micro"
REPOSITORY                                 TAG         IMAGE ID      CREATED        SIZE
localhost/ubi-micro-python                 latest      82921a06b57c  9 minutes ago  104 MB
registry.access.redhat.com/ubi8/ubi-micro  latest      c5ba898d3645  2 weeks ago    38.9 MB
# podman run --rm ubi-micro-python python --version
Python 3.9.2

これまでのUBIイメージと同様にベースイメージ上にパッケージの追加を行うことができました。ただし、最小限のパッケージ追加にも関わらずパッケージ自体の依存関係により多数のパッケージが追加されるのでどうしても出来上がったイメージのサイズは元のサイズに比べると膨らんでしまいます*3。 UBI Microのサイズの小ささを生かす場合は極力パッケージの追加を行わないようなシングルバイナリを実行するような用途に向いていると考えられます。 次のマルチステージビルドの例ではGoのシンプルなバイナリを追加してコンテナイメージを作成してみます。

UBI Microを使ったマルチステージビルド

マルチステージビルドを用いてビルド済みのシングルバイナリをUBI Microにコピーすることでサイズの増加を抑えたコンテナイメージの作成が可能です。マルチステージビルドではContainerfileやDockerfile(以下、Containerfile)を使用した通常手順でのビルドが可能です。

今回はGoで書いた実行すると「Hello,World!」返すシンプルなアプリを使います。なお、Podmanを使ったGoのサンプルバイナリのビルド方法については下記の記事を参照ください。 zenn.dev

Containerfileは下記を使用します

FROM docker.io/library/golang as go-build
ENV APP_ROOT /go/src
WORKDIR ${APP_ROOT}
COPY ./hello.go .
RUN go mod init hello && go build 

FROM registry.access.redhat.com/ubi8/ubi-micro
COPY --from=go-build /go/src/hello /usr/local/bin/
CMD ["hello"]

Buildah(またはPodman)を使用してビルドします

# ls Containerfile hello.go
Containerfile  hello.go
# buildah bud -t ubi-micro-hello-world .
# podman run --rm ubi-micro-hello-world
Hello, World!
# podman images --filter label=name=ubi8/ubi-micro
REPOSITORY                                 TAG         IMAGE ID      CREATED         SIZE
localhost/ubi-micro-hello-world            latest      56fcfe57af0e  6 minutes ago   40.7 MB
localhost/ubi-micro-python                 latest      3bb4998a2f2c  29 minutes ago  104 MB
registry.access.redhat.com/ubi8/ubi-micro  latest      c5ba898d3645  2 weeks ago     38.9 MB

このように出来上がったubi-micro-hello-world という名前のコンテナイメージは元のイメージとほぼ変わらないサイズに抑えられています。

まとめ

Red Hatの新しい軽量なコンテナベースイメージであるUBI Microについて紹介しました。パッケージマネージャが搭載されていないDistrolessなイメージでサイズが小さいだけでなくセキュリティ面でも有利なイメージとなっています。パッケージを追加する場合はホストOSのdnfコマンドを使用するなどこれまでのUBIとは若干使い方が異なる点が注意です。また従来通りのContainerfileを使ったマルチステージビルドも可能で、シングルバイナリを配置するようなイメージであれば十分に元のサイズを保った小さなコンテナイメージを作成することが可能です。 UBI/UBI Minimal/UBI Init/UBI Microと多彩な種類のイメージが揃ったことでUBIを使ったコンテナイメージ作成の幅が広がりました。UBIは無料で使用、配布可能(一部制限あり)が可能となっていますので是非UBIを活用したコンテナイメージの作成に取り組んでみてください。

リンク

*1:UBI Microを紹介したRed Hatのブログ記事でも同様の記載あり → https://www.redhat.com/ja/blog/introduction-ubi-micro

*2:Fedoraのdnfでは /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release が取得できずエラー

*3:UBI Minimalに同様に追加した場合は151MBほどなので十分に小さいサイズとも言える

* 各記事は著者の見解によるものでありその所属組織を代表する公式なものではありません。その内容については非公式見解を含みます。