1. はじめに
Docker で作成したイメージを個人でのみ利用したい場合 Docker Hub などのプライベートレジストリが利用できますがオンプレミスの Kubernetes 環境に Docker Registry を作成しプライベートリポジトリとして使用することもできます。本文章では Docker Registry を Kubernetes 上に作成し Dockerfile から NGINX が動作するコンテナイメージを登録しそのコンテナイメージを元に Pod を Kubernetes 上に作成する方法を記します。
尚、私の Kubernetes 環境はこんな感じなのでこれをベースとした説明となります。また認証はせず HTTP での通信となります。
$ kubectl get node -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
k60h Ready control-plane,master 20h v1.23.1 10.185.1.60 <none> Ubuntu 20.04.3 LTS 5.4.0-91-generic docker://20.10.7
k61h Ready <none> 20h v1.23.1 10.185.1.61 <none> Ubuntu 20.04.3 LTS 5.4.0-91-generic docker://20.10.7
k62h Ready <none> 20h v1.23.1 10.185.1.62 <none> Ubuntu 20.04.3 LTS 5.4.0-91-generic docker://20.10.7
k63h Ready <none> 20h v1.23.1 10.185.1.63 <none> Ubuntu 20.04.3 LTS 5.4.0-91-generic docker://20.10.7
全ての node で /etc/hosts を用いて k60h.local の名前解決ができるようにしています。本記事でホストと記されているのは k60h.local を指しています。
$ egrep k60h /etc/hosts
10.185.1.60 k60h.local k60h
2. Docker Registry を Kubernetes にデプロイする
まず Docker Registry が push されたコンテナイメージを保存するディレクトリをホスト上に作成します。Docker Registry のコンテナ上から見ると /var/lib/registry を使用するのでホストも同様に /var/lib/registry を作成しても良いです。
$ sudo mkdir /var/local/registry
以下の yaml ファイルを作成します。kubernetes.io/hostname で該当の Pod が動作するホストを指定しています。私の環境では master に Docker Registry を兼用させることにしました。
$ cat docker-registry.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-registry
labels:
app: docker-registry
spec:
replicas: 1
selector:
matchLabels:
app: docker-registry
template:
metadata:
labels:
app: docker-registry
spec:
hostNetwork: true
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
nodeSelector:
kubernetes.io/hostname: k60h
containers:
- name: docker-registry
image: registry:2
ports:
- containerPort: 5000
volumeMounts:
- name: registry
mountPath: /var/lib/registry
volumes:
- name: registry
hostPath:
type: Directory
path: /var/local/registry
上記 yaml を apply し http://localhost:5000/ から HTTP の応答があることを確認します。
$ kubectl apply -f ./docker-registry.yaml
deployment.apps/docker-registry created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
docker-registry-87b77c57c-d8kfz 1/1 Running 1 (87m ago) 88m
$ curl -I http://localhost:5000/
HTTP/1.1 200 OK
Cache-Control: no-cache
Date: Mon, 20 Dec 2021 01:49:31 GMT
3. コンテナイメージを作成し Docker Registry に Push する
自分が使用する Docker コンテナイメージ用の Dockerfile を作成します。今回は以下のような Dockerfile を使用します。html ディレクトリには適当な html ファイルを作成します。
$ mkdir my-nginx
$ cd my-nginx
~/my-nginx$ vi Dockerfile
~/my-nginx$ cat Dockerfile
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get install -y nginx
COPY ./html /var/www/html
EXPOSE 80
STOPSIGNAL SIGQUIT
CMD ["nginx", "-g", "daemon off;"]
~/my-nginx$ mkdir html
~/my-nginx$ vi html/index.html
~/my-nginx$ cat html/index.html
<html><body>Hello World!</body></html>
上記 Dockerfile を元にコンテナイメージを作成します。コンテナイメージは自動的に Docker に追加されます。
~/my-nginx$ docker build -t my-nginx .
Sending build context to Docker daemon 5.632kB
Step 1/8 : FROM ubuntu:20.04
---> ba6acccedd29
Step 2/8 : RUN apt-get update
---> Running in 076fc7382a2e
Get:1 http://archive.ubuntu.com/ubuntu focal InRelease [265 kB]
<snip>
Successfully tagged my-nginx:latest
~/my-nginx$ docker images | grep my-nginx
my-nginx latest ccc3acacf1ce 22 seconds ago 177MB
Docker 上でコンテナイメージが正しく動作するか確認します。http://localhost:8080 から idnex.html の内容が返ってくれば正常に動作しています。
~/my-nginx$ docker run --name mytest -p 8080:80 -d my-nginx
0ca08080c313ac9757a1c5f05cf2e4183a932cc39e20fcdb605a4595fe9c2f18
~/my-nginx$ docker ps | grep my-nginx
0ca08080c313 my-nginx "nginx -g 'daemon of…" 56 seconds ago Up 55 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp mytest
~/my-nginx$ curl http://localhost:8080
<html><body>Hello World!</body></html>
コンテナイメージに Tag 付をし Docker Registry にコンテナイメージを Push します。k60h.local は適時自分の環境に合わせ読み替えてください。Docker Registry から正しく /var/local/registry が mount されていた場合ホスト上に docker ディレクトリが作成されホストが再起動された場合などにもイメージが残ります。
$ docker tag my-nginx k60h.local:5000/my-nginx
$ docker push k60h.local:5000/my-nginx
Using default tag: latest
The push refers to repository [k60h.local:5000/my-nginx]
92d1830d3944: Pushed
a23d7252aa4b: Pushed
2bfe651cb586: Pushed
51b1fda25509: Pushed
9f54eef41275: Mounted from ubuntu-nginx
latest: digest: sha256:74e4ee005fb6a23423eb0e32cefc0172eee267c80e661ac4ff9a815a9cfdeec8 size: 1371
$ ls -l /var/local/registry/
total 4
drwxr-sr-x 3 root staff 4096 Dec 20 00:19 docker
ホスト上で動作しているコンテナやコンテナイメージを削除します。
$ docker container stop mytest
$ docker container rm mytest
$ docker rmi k60h.local:5000/my-nginx
$ docker rmi my-nginx
4. Docker Registry からコンテナイメージを Pull できるか試す
Docker から HTTP でコンテナイメージを PULL するには以下のような記述を各 node の /etc/docker/daemon.json に追加する必要があります。
{
"insecure-registries" : ["k60h.local:5000"]
}
私の環境では /etc/docker/daemon.json は以下のようになっています。
$ cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2",
"insecure-registries" : ["k60h.local:5000"]
}
Docker の設定ファイルを再読み込みします。
$ sudo systemctl reload docker
以下は k61h での実行結果となります。他の node からも k60h で動作する Docker Registry からコンテナイメージを pull できることが確認できます。pull したイメージは削除します。
$ sudo docker pull k60h.local:5000/my-nginx
Using default tag: latest
latest: Pulling from ubuntu-nginx
7b1a6ab2e44d: Pull complete
544fed566923: Pull complete
7db40321f9e0: Pull complete
b74505b5a888: Pull complete
b3c005019179: Pull complete
Digest: sha256:9da756d1a9e50198d75bb669de126bd8a17858336dde70d1f093661111448225
Status: Downloaded newer image for k60h.local:5000/ubuntu-nginx:latest
k60h.local:5000/ubuntu-nginx:latest
$ sudo docker rmi k60h.local:5000/ubuntu-nginx
5. Kubernetes 上に Docker Registry のコンテナイメージを使用し Pod を作成する
kubectl run を使うと以下のように確認することができます。テスト実施後作成した Pod を削除しています。
$ kubectl run mytest --image=k60h.local:5000/my-nginx
pod/mytest created
$ kubectl get pod -o wide | grep mytest
mytest 1/1 Running 0 7s 10.244.3.27 k63h <none> <none>
$ curl 10.244.3.27
<html><body>Hello World!</body></html>
$ kubectl delete pod mytest
pod "mytest" deleted
yaml を利用して Deployment として利用することも可能です。テスト実施後 Deployment も削除しています。
$ cat my-nginx.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
app: ubuntu-nginx
replicas: 1
template:
metadata:
labels:
app: ubuntu-nginx
spec:
containers:
- name: ubuntu-nginx
image: k60h.local:5000/ubuntu-nginx
ports:
- containerPort: 80
$ kubectl get pods -o wide | grep my-nginx
my-nginx-6b48b4d4f9-4p888 1/1 Running 0 19s 10.244.3.28 k63h <none> <none>
$ curl 10.244.3.28
<html><body>Hello World!</body></html>
$ kubectl delete -f ./my-nginx.yaml
deployment.apps "my-nginx" deleted