プライベートレジストリを導入したら(プライベートレジストリの利用方法)

投稿者: | 6月 15, 2025

何年か前に思ったのだが、所詮、Kubernetesなんて、熱狂的な人が飛びついて、ユーザ会なんかを作って、適当に盛り上がって終わる。CloudStackやOpenStackみたいな感じになるのではと思っていた。CloudStackは、企業を渡り歩いて今でも製品として存在してはいる。OpenStackも開発はされていて進化をしている。2つともあの時のユーザ会がぁという熱はどうなってしまったんだろうか。OpenStackは結構企業を巻き込んでいたが。。。ユーザ会が立ち上がるものは、なんとなく先がないような気がする。ユーザ会を建てるだけの仕事とかありそう。

Kubernetesはどうやらその道から外れて、結構使われ始めてきたような気がする。

ただ、やはりインフラ屋さんには扱いが難しい。アプリが絡むから。そもそもインフラ屋さんはアプリなんてあんまり気にしないし、アプリを作れと言われても作りたいアプリもそんなに思い浮かばない。いまやAIがプログラムを書いてくれるので、なんか願えばいいのにと思うのだが。そもそもそれ以前の話なのかもしれない。

 

閑話休題

 

今更、こんなことを書くのはどうかと思うが、多分知らない人は全く知らないので改めて記載してみた。

Dockerのプライベートレジストリを作る記事を以前書いたが、一体どのように使うのか?

ちなみに、このコンテナ環境は、1台 4vCPU 8GB RAM 100GB HDDのUbuntu Server 22.04あるいは24.04のフレッシュインストール環境に以下のシェルを流しただけの環境。このシェルでKubernetes (k3s)とDocker、プライベートレジストリの環境が全部できる。

https://gist.github.com/masezou/65c29fcff3a761335506b908f97228a3

sudo -i
wget https://gist.github.com/masezou/65c29fcff3a761335506b908f97228a3
bash ./k8s-setup.sh

以後に出てくる”192.168.11.58”というアドレスは、構築した1台のUbuntuサーバのIPアドレス。

余談だが、このスクリプトはライセンスは放棄しているので、勝手にご利用どうぞなんだが。どこかの会社が使いたいからライセンスを決めてくダサいと言われたことがある。一応、M.I.Tでいいと答えたが。もちろん入手元さえ明記してくれれば、無償でどうぞとなっている。確かにインフラの人が理解するための必要な装備が全部入っているから便利かも。

 

例えばBitnamiのWordpressは以下のようにして簡単に構築することができる。(WordPressもアクセス方法やチューニングにコツがあるのだが、今回はアクセス確認すら割愛)

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami \
  --create-namespace

  名前空間wordpress-bitnamiでwordpressが展開できた。

以下を実行してみる。

kubectl get pods -n wordpress-bitnami -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”

wp-release-mariadb-0: docker.io/bitnami/mariadb:11.4.5-debian-12-r12

wp-release-wordpress-85cfc9b9cd-msmjp: docker.io/bitnami/wordpress:6.8.1-debian-12-r5

名前空間wordpress-bitnamiでは、コンテナイメージは、docker.ioのイメージを使っている。

このようにインターネットからイメージを落とせるので、単純に動かすだけでは、プライベートレジストリはいらない。ただ、コンテナ環境がインターネットにつながっていないのであれば、プライベートイメージに一度コピーをしてから使う必要がある。

docker.ioにあるコンテナイメージをプライベートレジストリ192.168.11.58:5000にコピー(Pull / Push)をしてみる。

docker pull docker.io/bitnami/wordpress:6.8.1-debian-12-r5
docker tag docker.io/bitnami/wordpress:6.8.1-debian-12-r5 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
docker push 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
reg tags -f 192.168.11.58:5000/bitnami/wordpress
docker image rmi bitnami/wordpress:6.8.1-debian-12-r5
docker pull docker.io/bitnami/mariadb:11.4.5-debian-12-r12
docker tag docker.io/bitnami/mariadb:11.4.5-debian-12-r12 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
docker push 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12
reg tags -f 192.168.11.58:5000/bitnami/mariadb
docker image rmi bitnami/mariadb:11.4.5-debian-12-r12

プライベートレジストリ192.168.11.58:5000にあるイメージを利用して、名前空間wordpress-bitnami-localで展開してみる。

bitnamiのイメージを手元に持ってきた場合は、 allowInsecureImages: trueをつけないと、mariadbがDigestと違うといってエラーになる。namespaceを変えて展開する。

cat << EOF > values.yaml
global:
imageRegistry: 192.168.11.58:5000
security:
    allowInsecureImages: true

image:
repository: bitnami/wordpress
  tag: 6.8.1-debian-12-r5

mariadb:
image:
  repository: bitnami/mariadb
  tag: 11.4.5-debian-12-r12
EOF

helm install wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami-local \
--create-namespace \
  -f values.yaml

新しく展開したwordpressのイメージを確認すると、ちゃんとプライベートレジストリから起動している。

kubectl get pods -n wordpress-bitnami-local -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”

wp-release-mariadb-0: 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12

wp-release-wordpress-85c7f7dc76-kngp8: 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5

 

以下で脆弱性スキャンができる。(grypeのインストールはダウンロードするだけなので割愛)

grype 192.168.11.58:5000/bitnami/wordpress:6.8.1-debian-12-r5
grype 192.168.11.58:5000/bitnami/mariadb:11.4.5-debian-12-r12

いくつかの脆弱性が報告されたと思う。

少なくともベースのdebian-12のパッケージだけでも最新にしたいが、毎回展開のたびにコンテナに入ってapt updateなんかしていられないのでイメージ側で更新しておくべき。

よって、イメージを更新する。

mkdir -p wordpress
cd wordpress
cat << 'EOF' > Dockerfile
FROM bitnami/wordpress:6.8.1-debian-12-r5

USER root

RUN apt-get update && \
  apt-get upgrade -y && \
  apt-get autoremove -y && \
  apt-get clean && \
    rm -rf /var/lib/apt/lists/*

USER 1001
EOF
docker build -t bitnami-update/wordpress:1.0.0 -f Dockerfile .
docker tag bitnami-update/wordpress:1.0.0 192.168.11.58:5000/bitnami-update/wordpress:1.0.0
docker tag bitnami-update/wordpress:1.0.0 192.168.11.58:5000/bitnami-update/wordpress:latest
docker push 192.168.11.58:5000/bitnami-update/wordpress:1.0.0
docker push 192.168.11.58:5000/bitnami-update/wordpress:latest
reg tags -f 192.168.11.58:5000/bitnami-update/wordpress
docker image rmi bitnami-update/wordpress:1.0.0
cd ..
mkdir -p mariadb
cd mariadb
cat << 'EOF' > Dockerfile
FROM bitnami/mariadb:11.4.5-debian-12-r12

USER root

RUN apt-get update && \
  apt-get upgrade -y && \
  apt-get autoremove -y && \
  apt-get clean && \
    rm -rf /var/lib/apt/lists/*

USER 1001
EOF
docker build -t bitnami-update/mariadb:1.0.0 -f Dockerfile .
docker tag bitnami-update/mariadb:1.0.0 192.168.11.58:5000/bitnami-update/mariadb:1.0.0
docker tag bitnami-update/mariadb:1.0.0 192.168.11.58:5000/bitnami-update/mariadb:latest
docker push 192.168.11.58:5000/bitnami-update/mariadb:1.0.0
docker push 192.168.11.58:5000/bitnami-update/mariadb:latest
reg tags -f 192.168.11.58:5000/bitnami-update/mariadb
docker image rmi bitnami-update/mariadb:1.0.0
cd ..

これで、新しいイメージができた

ので、bitnamiのイメージをレジストリに持ってきただけのwordpress-bitnami-localのイメージを入れ替える。

名前空間wordpress-bitnami-localで動いているdocker.ioから持ってきただけのイメージを修正済みのイメージと入れ替えてみる。

cat << EOF > values.yaml
global:
imageRegistry: 192.168.11.58:5000
security:
    allowInsecureImages: true

image:
repository: bitnami-update/wordpress
  tag: 1.0.0

mariadb:
image:
  repository: bitnami-update/mariadb
  tag: 1.0.0
EOF

helm upgrade wp-release bitnami/wordpress \
--version 24.2.9 \
--namespace wordpress-bitnami-local \
  -f values.yaml

 

しばらく待つと、名前空間wordpress-bitnami-localで動作しているイメージが以下のように入れ替わる。

kubectl get pods -n wordpress-bitnami-local -o jsonpath="{range .items[*]}{.metadata.name}{':\t'}{range .spec.containers[*]}{.image}{'\n'}{end}{end}”

wp-release-mariadb-0: 192.168.11.58:5000/bitnami-update/mariadb:1.0.0

wp-release-wordpress-dff6c8568-q7p59: 192.168.11.58:5000/bitnami-update/wordpress:1.0.0

 

自作のイメージをコンテナに作成する場合のEnd 2 Endのデモ

今までは、作成済みのコンテナイメージに手を入れることをやったが、自作のイメージを動かすためのデモ。

これから作るコンテナイメージは、Horizontal Pod AutoscalerでWebフロントエンドを作成したときに、複数のWebフロントエンド(つまりPod)が応答しているはずだが、実際にどのPodが応答しているか知りたいという目的で作ったもの。WebアクセスをするとPod名が表示されるようになっている。

まずは、コンテナイメージの作成

mkdir demo-nginx 
cd demo-nginx

docker pull debian:trixie-slim

# Dockerfile
cat <<'EOF' >Dockerfile
FROM debian:trixie-slim

COPY default.conf /etc/nginx/conf.d/
COPY index.sh /usr/share/nginx/html/
COPY entrypoint.sh /entrypoint.sh

RUN apt-get update && \
  apt-get install -y --no-install-recommends nginx fcgiwrap spawn-fcgi procps && \
  apt-get autoclean && \
  rm -rf /var/lib/apt/lists/* && \
  rm -f /etc/nginx/sites-enabled/default && \
  chmod 744 /usr/share/nginx/html/index.sh && \
    chown www-data:www-data /usr/share/nginx/html/index.sh

ENTRYPOINT ["/entrypoint.sh”]
EOF

# default.conf
cat <<'EOF' >default.conf
server {
  listen 80;
    server_name localhost;

  location ~ \.sh$ {
      root /usr/share/nginx/html/;
      include /etc/nginx/fastcgi_params;
      fastcgi_index index.sh;
      fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
      fastcgi_pass unix:/var/run/fcgiwrap.socket;
  }
}
EOF

# index.sh
cat <<'EOF' >index.sh
#!/bin/sh

host_name=$(cat hostname)
pod_name=$(hostname)

# sleep 5

echo "Content-type:text/html”
echo “”
echo "<html><head>”
echo "<title>${host_name}</title>”
echo '<meta http-equiv="Content-type" content="text/html;charset=UTF-8”>’
echo "</head><body>”
echo "HOSTNAME : ${host_name}”
echo "POD HOSTNAME : ${pod_name}”
echo "</body></html>”
EOF

# entrypoint.sh
cat << 'EOF' > entrypoint.sh
#!/bin/bash
set -e

echo "[INFO] Launching fcgiwrap using spawn-fcgi…”

mkdir -p /var/run

spawn-fcgi -s /var/run/fcgiwrap.socket -U www-data -G www-data -- /usr/sbin/fcgiwrap

if [ ! -S /var/run/fcgiwrap.socket ]; then
echo "[ERROR] fcgiwrap socket not found!”
ls -l /var/run
exit 1
fi

chmod 766 /var/run/fcgiwrap.socket

echo "[INFO] Starting nginx…”
exec nginx -g "daemon off;”
EOF
chmod +x entrypoint.sh

# docker build
docker image build -t nginx-display-hostname .

次に、Dockerレベルでの動作確認

docker run -d --rm --name demo-container -p 8081:80 nginx-display-hostname:latest
curl http://localhost:8081/index.sh

以下のようにコンテナIDが出てくればOK

<html><head>

<title></title>

<meta http-equiv=”Content-type” content=”text/html;charset=UTF-8”>

</head><body>

HOSTNAME :

POD HOSTNAME : 79a7b4116f87

</body></html>

一旦コンテナを止める

docker stop demo-container

プライベートレジストリにこのイメージをPushする。

docker tag debian:trixie-slim 192.168.11.58:5000/debian:trixie-slim
docker push 192.168.11.58:5000/debian:trixie-slim
docker tag nginx-display-hostname:latest 192.168.11.58:5000/nginx-display-hostname:latest
docker push 192.168.11.58:5000/nginx-display-hostname:latest
reg tags -f 192.168.11.58:5000/debian:trixie-slim
reg tags -f 192.168.11.58:5000/nginx-display-hostname:latest
docker rmi debian:trixie-slim
docker rmi nginx-display-hostname

このイメージを利用して、コンテナを作る。

cat << "EOF" > nginx-display.yaml
apiVersion: v1
kind: Namespace
metadata:
name: demo-nginx

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-display
namespace: demo-nginx
labels:
  app: nginx-display
spec:
replicas: 1
selector:
  matchLabels:
    app: nginx-display
template:
  metadata:
    labels:
      app: nginx-display
  spec:
    containers:
    - name: nginx-display
      image: 192.168.11.58:5000/nginx-display-hostname:latest
      ports:
      - containerPort: 80
      resources:
        requests:
          cpu: 10m
        limits:
          cpu: 100m

apiVersion: v1
kind: Service
metadata:
name: nginx-display
namespace: demo-nginx
spec:
type: NodePort
selector:
  app: nginx-display
ports:
- port: 80
  targetPort: 80
  nodePort: 30081

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-display-hpa
namespace: demo-nginx
spec:
scaleTargetRef:
  apiVersion: apps/v1
  kind: Deployment
  name: nginx-display
minReplicas: 1
maxReplicas: 2
metrics:
- type: Resource
  resource:
    name: cpu
    target:
      type: Utilization
      averageUtilization: 20
EOF
kubectl apply -f nginx-display.yaml

以下のコマンドを実行するとプライベートレジストリからロードされているのがわかる。

kubectl get pods -n demo-nginx -o jsonpath="{range .items[]}{.metadata.name}{':\t'}{range .spec.containers[]}{.image}{'\n'}{end}{end}"

nginx-display-857fdcc8c7-nzj5p: 192.168.11.58:5000/nginx-display-hostname:latest

以下のコマンドを実行して、コンテナが起動したかどうかを確認する。Horizon Pod Autoscalerも設定されているのがわかる。

kubectl -n demo-nginx get all

NAME READY STATUS RESTARTS AGE

pod/nginx-display-857fdcc8c7-nzj5p 1/1 Running 0 19m

 

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE

service/nginx-display NodePort 10.43.99.108 <none> 80:30081/TCP 25m

 

NAME READY UP-TO-DATE AVAILABLE AGE

deployment.apps/nginx-display 1/1 1 1 25m

 

NAME DESIRED CURRENT READY AGE

replicaset.apps/nginx-display-55786b9bfd 0 0 0 21m

replicaset.apps/nginx-display-6cd85cdc78 0 0 0 25m

replicaset.apps/nginx-display-857fdcc8c7 1 1 1 19m

 

NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE

horizontalpodautoscaler.autoscaling/nginx-display-hpa Deployment/nginx-display cpu: 0%/20% 1 2 1 25m

動作確認

curl http://192.168.11.58:30081/index.sh

Pod名が出ているのが確認できる。

<html><head>

<title></title>

<meta http-equiv=”Content-type” content=”text/html;charset=UTF-8”>

</head><body>

HOSTNAME :

POD HOSTNAME : nginx-display-857fdcc8c7-nzj5p

</body></html>

もし、Autoscalerを試したいのであれば

apt -y install apache2-utils
ab -n 500 -c 20 http://192.168.11.58:30081/index.sh
kubectl -n demo-nginx get all

負荷に応じて、Podの数が増えていく。

コンテナイメージの修正から、作成、さらにHorizon Pod Autoscalerまで飛躍してしまったが、このようにプライベートレジストリがあると、インターネットにつながっていなくてもコンテナを展開できたり、イメージの更新、あるいは自作イメージの可動をさせるのに便利。というか無くては始まらない。

もし、プライベートレジストリがないのであれば、環境を作るたびにインターネットからダウンロードあるいは、ビルドしなおしということになってしまう。

多分、これは、仮想マシンレベルしか興味がない、知らない人、言うなれば、AWSやAzureをvSphereもどきだと思って、1インスタンスずつ、インスタンス自体を管理、愛でている人が越えなきゃいけない壁の一つなのかもれない。

コメントを残す