Red Hat Universal Base Image (UBI)の使い方ヒント

### 注意

当記事は執筆者の独自研究によるもので、Red Hat社の公式見解ではないことに注意してください。

### UBIとは

Red Hat Universal Base Image (UBI)は、Red Hat社が公開しているLinuxコンテナイメージです。UBIはRed Hat Enterprise Linux（RHEL）のサブセットと言うこともでき、バージョンもRHELに合わせて7,8,9と続けてリリースされています。

### UBIを使う理由

##### (1) Red Hat社による公式リリース物である

野良イメージに比べて信頼できること、修正やバージョンアップが継続されることが挙げられます。以前の私はよくCent OSのイメージを使っていましたが、ご存じのとおりCent OSは昨年末で終了してしまったので、現在Docker Hubで公開されているものも更新が停止してしまいました。UBIは8系は更新継続していますし、最近9もリリースされました。

##### (2) 非Red Hat環境でも使用できる

UBIを使って作られたイメージはRed Hat環境、例えばRHELやOpenShift（OCP）以外で利用や再配布をしてもいいことになっています。ただしサポートは受けられません。

##### (3) 限られた条件だがサポートを受けられる

どうしてもサポートが必要であれば、正式なEntitlementがあるRHEL+PodmanやOCP環境を利用すればよいです。



##### (4) Yumで必要なパッケージを追加できる

RHELと同様、UBI内でyum（dnf）コマンドを使って必要なパッケージを追加することができます。ただしUBIが標準で対応しているYumリポジトリがRHELとは異なりUBI用のものになります。RHELに比べ利用可能なパッケージは限定されています。

```
# yum repolist
Updating Subscription Management repositories.
Unable to read consumer identity
Subscription Manager is operating in container mode.

This system is not registered with an entitlement server. You can use subscription-manager to register.

repo id                                                                   repo name
ubi-9-appstream                                                           Red Hat Universal Base Image 9 (RPMs) - AppStream
ubi-9-baseos                                                              Red Hat Universal Base Image 9 (RPMs) - BaseOS
ubi-9-codeready-builder                                                   Red Hat Universal Base Image 9 (RPMs) - CodeReady Builder
```

RHELのリポジトリにはあるのにUBIにはないがどうしても欲しいものがあった場合、サポートがあればリクエストをすることはできます。

https://qiita.com/teruq/items/9a51c73c08b54a03d9e2

ちなみに、RHELの正規のEntitlementを持ち込んでRHELのリポジトリを使うことも可能なようですがおすすめしません。配布先でもEntilementを購入しないとライセンス違反になるためです。


### UBIの入手方法

現在は大きく3種類の方法があります

##### (1) Red Hatコンテナレジストリ（要認証 registy.redhat.io）から入手する

この方法がおそらくはRed Hat社が最も想定している方法です。認証のためにRed Hatカスタマーポータルのアカウントが必要です。アカウントを使えるようにするためには、商用製品を購入するか開発者登録をする必要があります。

ちなみにですが、``Red Hat OpenShift on IBM Cloud``とAWSの``ROSA``ではregistry.redhat.ioのイメージを認証なしでプルすることができます。

```
$ oc run ubi --image=registry.redhat.io/ubi9/ubi -- tail -f /dev/null
pod/ubi created

$ oc get pods
NAME   READY   STATUS    RESTARTS   AGE
ubi    1/1     Running   0          17s
```

Azureの``ARO``では残念ながら認証エラーとなりました。このあたりの違いはよくわかっていません。

```
$ oc run ubi --image=registry.redhat.io/ubi9/ubi -- tail -f /dev/null
pod/ubi created

$ oc get pods
NAME   READY   STATUS             RESTARTS   AGE
ubi    0/1     ImagePullBackOff   0          5s

$ oc describe pod ubi
...
Events:
  Type     Reason          Age              From               Message
  ----     ------          ----             ----               -------
  Normal   Scheduled       8s               default-scheduler  Successfully assigned default/ubi to ********
  Normal   AddedInterface  6s               multus             Add eth0 [10.129.2.11/23] from openshift-sdn
  Normal   Pulling         6s               kubelet            Pulling image "registry.redhat.io/ubi9/ubi"
  Warning  Failed          6s               kubelet            Failed to pull image "registry.redhat.io/ubi9/ubi": rpc error: code = Unknown desc = unable to retrieve auth token: invalid username/password: unauthorized: Please login to the Red Hat Registry using your Customer Portal credentials. Further instructions can be found here: https://access.redhat.com/RegistryAuthentication
  Warning  Failed          6s               kubelet            Error: ErrImagePull
  Normal   BackOff         5s (x2 over 6s)  kubelet            Back-off pulling image "registry.redhat.io/ubi9/ubi"
  Warning  Failed          5s (x2 over 6s)  kubelet            Error: ImagePullBackOff
```

##### (2) Red Hatコンテナレジストリ（認証不要 registy.access.redhat.com）から入手する

イメージは(1)と同じものですが、イメージをプルする際に認証は不要です。では(2)だけでいいじゃないかと思うかもしれませんが、このレジストリは将来廃止になるとRed Hatはかつてアナウンスしていました。しかし今調べてみたところそのアナウンスを見つけることができませんでした。もしかしたら方針が変わったのかもしれません。詳しい方がいらっしゃいましたら教えてください。

(1)(2)のいいところは、UBIの他にUBIを利用したさまざまな認定コンテナを見つけることができる点です。これはRed Hat Ecosystem Catalogと呼ばれています。

https://catalog.redhat.com/software/container-stacks/search

ここで公開されているものは、Red Hat社やサードパーティ製を含め全てUBI上に作られており、公開にあたってRed Hat社の審査を受けた認定コンテナイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/fa812c68-839a-7f2f-6d6c-aceb958093fa.png)

##### (3) Docker Hubから入手する

昨年からだったと記憶していますが、UBIのうち最も基礎となるイメージはDocker Hubでも公開されています。

https://hub.docker.com/u/redhat

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241424/ab6b82b9-5d57-9eb6-ee54-941af4a4a117.png)

ただしRed Hat Ecosystem Catalogで公開されているその他イメージはありません。

私見ですが、現時点では(2)の方法を利用するのがいいと思っています。

### とりあえずUBIを試してみる

DockerやPodmanを使っている人は次のコマンドだけでUBI9のシェルを起動することができます。

```
$ docker run -it registry.access.redhat.com/ubi9/ubi bash
# cat /etc/redhat-release
Red Hat Enterprise Linux release 9.0 (Plow)
```

厳密にはRHEL9とは異なりますが、雰囲気を知ることはできます。昔ならDVDのisoイメージをダウンロードして仮想マシンを作ってインストールしなければならなかったことを考えるといい時代になったものです。

### 使い方のヒント

##### (1) yum(dnf)時にThis system is not registered with an entitlement server. You can use subscription-manager to registerと表示されるのを消したい

DockerfileのRUNやシェルで普通にyumやdnfコマンドを使うとこのようなメッセージが出力されます。

```
# dnf list | more
Updating Subscription Management repositories.
Unable to read consumer identity
Subscription Manager is operating in container mode.

This system is not registered with an entitlement server. You can use subscription-manager to register.

Last metadata expiration check: 0:00:19 ago on Wed Jun 22 17:08:33 2022.
Installed Packages
acl.x86_64                                     2.3.1-3.el9                      @System
alternatives.x86_64                            1.20-2.el9                       @System
```

使用上問題はありませんが精神衛生上気になる人は、``--disableplugin subscription-manager``を付けることで抑止できます。

```
# dnf --disableplugin subscription-manager list | more
Last metadata expiration check: 0:02:19 ago on Wed Jun 22 17:08:33 2022.
Installed Packages
acl.x86_64                                     2.3.1-3.el9                      @System
alternatives.x86_64                            1.20-2.el9                       @System
```

##### (2) 任意のUIDで実行できるようにする

UBIに限った話ではないですが、OCPはデフォルトでイメージのUSER指定を無視してランダムなUIDでコンテナが実行されます。SCCと呼ばれるOCP独自の機能です。Red Hat Ecosystem Catalogで公開されているイメージは恐らくは多くのものでそれを考慮していると思いますが、自分でカスタムイメージを作る場合は気にした方がいいでしょう。

下記は私がsquidを実行するコンテナイメージを作成したときのものです。Red Hat Ecosystem Catalogにsquidのイメージがなかったので自作せざるを得ませんでした。

```
FROM registry.access.redhat.com/ubi9/ubi:9.0.0-1468.1655190709

RUN dnf -y --disableplugin subscription-manager install squid && \
    dnf clean all

ADD squid /etc/squid
ADD https://github.com/boynux/squid-exporter/releases/download/v1.10.3/squid-exporter /usr/local/bin/

RUN chmod 755 /usr/local/bin/squid-exporter && \
    chgrp -R 0 /etc/squid /run /usr/local/bin && \
    chmod -R g=u /etc/squid /run /usr/local/bin

USER 1001

CMD ["/usr/sbin/squid", "-NC"]

EXPOSE 3128/tcp
```

肝となる部分ですが、``USER 1001``はローカルのDockerやPodmanで実行するときは有効ですが、OCPでは無視されランダムなUIDで実行されます。一方、GIDは常に0（root）になる特性を利用し、コンテナ内で読み書きが必要なディレクトリをGID 0にchownし、元のユーザーと同じパーミッションにグループをchmodすることで、実行時にUIDが変わってもGIDで動くようにしています。この作法はOCPのコンテナ開発では一般的なやり方です。