概要
k3dで、ローカルのDockerレジストリに格納されているコンテナイメージをデプロイする方法について説明します。
私自身たまにk3dを触るのですが、そのたびに自分で作ったコンテナイメージの扱いに困っていたので、備忘録として残すことにしました。
※ 本記事は、Ubuntu 22.04 で動作検証しています。
手順の概要
以下がおおまかな手順です。
- k3dで利用するコンテナレジストリを作成
- 作成したコンテナレジストリにコンテナイメージをpush。今回はbusyboxを利用
- k3dでクラスターの作成
- ローカルレジストリのコンテナイメージをpullしてPodが立ち上がることを確認
余談
最初は作成済みのクラスターにローカルレジストリを追加したかったのですが、それは困難または不可能ということがわかったので、「k3dで新たにクラスターを作る」前提で説明していきます。
手順
コンテナレジストリの作成
k3dのコマンドで、以下のように簡単にコンテナレジストリを作成できます。
k3d registry create registry --port 5000
コマンド実行後、k3d-registry
という名前のコンテナレジストリがDockerコンテナとして作成されていることを確認できます。(k3d registry create
の後の文字列 registry
が、 k3d-
の後ろに付与されるようです)
$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES IMAGE PORTS
k3d-registry registry:2 0.0.0.0:5000->5000/tcp
k3dのコマンドでも、以下のように確認可能です。
$ k3d registry ls
NAME ROLE CLUSTER STATUS
k3d-registry registry running
--port 5000
を指定しない場合は、ホストOSの任意のポート番号(例:40787
)が割り当てられてしまうのでご注意ください。
コンテナイメージをpush
作成したコンテナレジストリに、コンテナイメージをpushします。今回はサンプルとしてbusyboxのイメージを使います。
最初に、docker.ioからbusyboxのコンテナイメージを取得します。
docker pull busybox:1.37
"ローカルレジストリのホスト名:ポート番号" という形式で、新しいタグを付与します。
docker tag busybox:1.37 localhost:5000/busybox:1.37
ローカルレジストリにbusyboxのコンテナイメージをpushします。
docker push localhost:5000/busybox:1.37
以下のコマンドで、ローカルレジストリにbusyboxのコンテナイメージが追加されているのを確認できます。
$ curl -k http://localhost:5000/v2/_catalog
{"repositories":["busybox"]}
$ curl -k http://localhost:5000/v2/busybox/tags/list
{"name":"busybox","tags":["1.37"]}
コンテナイメージのpushに失敗する場合は、/etc/docker/daemon.json
の設定変更が必要な可能性があります。筆者の記事になりますがdocker pushとpullを可能にするための設定などを参考に、Dockerが http://localhost:5000
に対してコンテナイメージをpushできるように設定してください。
クラスターの作成
事前準備
k3dコマンドでクラスターを作成する前に、次のようなコンテナレジストリの設定ファイルを用意します。
mirrors:
"localhost:5000":
endpoint:
- http://k3d-registry:5000
設定ファイルが必要な理由
先ほど localhost:5000
というホスト名でbusyboxのコンテナイメージをpushしましたが、次に作成するクラスターでPodをデプロイする際、ホスト名 localhost:5000
でイメージをpullしようとしてもレジストリにアクセスできません。これは、クラスターが作られるDockerのネットワークがホストOSのネットワークとは異なるためです。Dockerのネットワーク内では、レジストリに k3d-registry:5000
というホスト名でアクセスできます。そこで、この設定ファイルでは「localhost:5000
へのリクエストを http://k3d-registry:5000
に転送する」ように設定しています。
k3dコマンドでクラスターを作成
以下のコマンドで、k3dを使って(k3sの)クラスターを作成します。
k3d cluster create \
--registry-config registries.yaml \
--registry-use k3d-registry
k3s-default
という名前のk3sクラスターが作成されます。
$ k3d cluster ls
NAME SERVERS AGENTS LOADBALANCER
k3s-default 1/1 0/0 true
デフォルトでは k3s-default
という名前のクラスターが作成されますが、クラスター名をカスタマイズしたい場合は、k3d cluster create
の後に任意のクラスター名を指定します。
k3d cluster create [cluster-name] \
--registry-config registries.yaml \
--registry-use k3d-registry
ローカルレジストリのコンテナイメージをpullしてPodが立ち上がることを確認
先ほどpushしたコンテナイメージを使ってPodを起動できるかを確認します。
kubectl -n default run busybox \
--rm -it \
--image=localhost:5000/busybox:1.37
問題なくbusyboxをpullできれば、以下のようにコンテナ内に入れるはずです。
/ # date
Tue Sep 23 07:26:07 UTC 2025
/ #
別のターミナルを開くと、busyboxのPodが立ち上がっているのを確認できます。
$ kubectl get po -n default
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 3s
ついでに、コンテナイメージが正常にpullできていることも確認してみます。
$ kubectl describe po -n default busybox | grep -A 32 ^Events:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 4m7s default-scheduler Successfully assigned default/busybox to k3d-k3s-default-server-0
Normal Pulling 4m7s kubelet Pulling image "localhost:5000/busybox:1.37"
Normal Pulled 4m7s kubelet Successfully pulled image "localhost:5000/busybox:1.37" in 97ms (97ms including waiting). Image size: 2283988 bytes.
Normal Created 4m7s kubelet Created container busybox
Normal Started 4m7s kubelet Started container busybox
補足: コンテナレジストリを "k3d registry create" を使わずに作った場合の対応
コンテナレジストリを k3d registry create
コマンドではなく、Docker Composeなどで自前で作成している場合、k3dでクラスターを作成する手順が若干異なります。
例えば、以下のように自前でコンテナレジストリを起動している状況を考えます。
$ docker ps --format "table {{.Names}}\t{{.Image}}\t{{.Ports}}"
NAMES IMAGE PORTS
docker-registry registry:2 0.0.0.0:5000->5000/tcp, [::]:5000->5000/tcp
クラスター作成前に、以下の registries.yaml
を用意する点は同じです。(ホスト名が docker-registry
に変わっている点に注意してください)
mirrors:
"localhost:5000":
endpoint:
- http://docker-registry:5000
クラスターを作成するコマンドは先ほどと異なり、--registry-use
のオプションなしで実行します。
k3d cluster create \
--registry-config registries.yaml
この状態だとk3sクラスターから http://docker-registry:5000
へのリクエストが通らないため、docker-registry
コンテナを k3d-k3s-default
のDockerネットワークに追加する必要があります。
最初に以下のコマンドで、k3sのネットワーク名を特定します。
$ docker network ls | grep k3s
22e23f936ef6 k3d-k3s-default bridge local
特定したネットワークに、docker-registry
のコンテナを追加します。
docker network connect k3d-k3s-default docker-registry
これで、k3sクラスターからローカルレジストリのコンテナイメージをpullできるようになるはずです。