Kubernetesはその役割的に「Dockerfileからイメージのビルド」などの下準備部分は担当範囲ではなく、yaml書かれたimage名に応じてどこかからpullして動かすような前提に立っているため、事前にイメージが準備できていないと
Error: ErrImagePull
みたいなのが出て動きません。
Docker Hubにパブリック公開したくない、でもAWS ECRなど準備するのはめんどい…ということもあると思います。
そんなときローカルだけで開発する方法です。
概要
MinikubeのDocker環境に対してイメージをビルドし、imagePullPolicyをNeverにすることでMinikube環境にあるイメージを使うようにする。
前提条件
ローカル環境にはMinikubeを使用します。(それ以外のは知りません)
Dockerイメージビルド
Dockerfile
これはなんでもいいので適当な例です。
FROM busybox
CMD ["sleep", "10"]
10秒sleepして終わるだけです。終わるコマンドなのでJobにします。
事前準備
dockerコマンドの対象をMinikube内のDocker環境に向くようにする。(イメージもMinikube内にできる)
eval $(minikube docker-env)
$()の中身のminikube docker-envを実行してみればわかりますが、環境変数を設定しているだけです。
なのでターミナルウィンドウ1つ単位での設定となるので、ビルドを行いたいターミナルで毎回上記が先に実行することを忘れないでください。
(これを忘れてホストマシンのDocker上にイメージを作っても意味がありません)
ビルド
仮にfoo/barというイメージ名(タグ)にしたいとします。
docker image build -t foo/bar .
# . はDockerfileのあるディレクトリ
docker image lsで確認するとKubernetes関連イメージと並んでfoo/barが表示されると思います。
またここで他のターミナルウィンドウを開いてdocker image lsをしてもfoo/barが無いことからイメージはMinikube環境内にビルドされたことがわかります。
このままだとyamlにimage: foo/barと書いてもFailed to pull imageと言われて動かないのでyamlにも設定を追加します。
yaml設定
yamlにimagePullPolicy: Neverを設定します。
そうするとK8sはイメージをpullしにいかず、ローカルにあるものを使おうとします。ローカルというのはMinikube VM内にあるイメージです。
今回の例は10秒sleepして終わるのでJobとします。
apiVersion: batch/v1
kind: Job
metadata:
name: example-job
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: bar
image: foo/bar # これが自作イメージ
imagePullPolicy: Never # ローカルにあるイメージを使う
ダッシュボードのPodのイベントでもContainer image “foo/bar” already present on machineみたいなローカルからイメージ使いました的な意味のログが確認できると思います。
この手段とは別にskaffoldというツールを使うことでもローカル開発はできますが、「Pod内からyamlテンプレートを使って別のJobを作成したい」みたいな複雑なことをしようとすると対応しきれない気がします。
コメント