初めに
コンテナを利用するにあたり、避けて通れないのがコンテナイメージのビルドです。
簡単にビルドするのであれば、 docker と Dockerfile を利用してビルドするのがよいとおもいます。
ただ、 docker を使っていない 各種クラウドのマネージドサービスや、kubernetes 環境の場合、docker build
を使うことはできません。
最近、kubernetes しかない環境でコンテナイメージをビルドする必要ができたため、
以前から名前だけ知っていた kaniko というビルドツールを使ってみました。
kaniko 概要
kaniko は google が開発しているビルドツールで コンテナ内で稼働します。
他に、以下のような特徴があります。
- Dockerfile を使ってビルドする
- docker デーモンが無くてもビルドできる
- 特権は不要
- ビルド結果は指定したコンテナレジストリに格納する
kaniko の動作の概要としては、下図のようになります。
- kaniko イメージを用い、Pod (コンテナ)を作成する
- Pod 内で稼働する executor が GitHub (またはその他の格納場所)からビルドコンテキストを取得する
- Dockerfile を読み取り、 FROM で指定された base image を取得する
- Dockerfile 内のコマンドに沿って Image Layer を追加していき、新しいコンテナイメージをビルドする
- 指定したコンテナレジストリに push する (secret に登録した認証情報を利用する)
![]() |
---|
※ ビルドコンテキスト と呼ばれる ビルドに必要な各種ファイル類は、上図では GitHub に入れていますが、 GitHub 以外に S3、GCS、ローカルディレクトリ、ローカルファイル(.tar.gz)、はては標準入力(.tar.gz を流し込む)まで利用できます。
ビルド手順
ビルドの動作としては、上記 1.~5. ですが、実際の手順は以下のようになります。
- ビルド関連のファイルを GitHub に配置
- push 先コンテナレジストリの認証情報を secret として定義
- kaniko Pod を作成(ここで 上記 1.~5. が実行される)
1点目の GitHub に配置するところは割愛し、 secret の作成から記載していきます。
コンテナレジストリ用 secret の作成
最終的にイメージを push するコンテナレジストリの認証情報を secret として作成します。
今回は docker hub を利用します。
secret のタイプはよく使う generic
ではなく、docker-registry
タイプです。 初めて使いました。
以下の例では、regcred
という名前の secret を作成しています。
kubectl create secret docker-registry regcred \
--docker-server=https://index.docker.io/v1/ \
--docker-username=ユーザー名 \
--docker-password=パスワード \
--docker-email=メールアドレス
※ユーザー名などは、 docker hub のアカウントの ユーザー名、パスワード、メールアドレスです。
また、 docker hub を利用する場合の --docker-server
は上記の内容を指定すればよいようです。
※ secret 内のパスワードデータ等は base64 エンコードされているだけですので、デコードすれば読み取れます。取扱いに注意が必要です。
kaniko 用 YAML の準備
kaniko Pod を作成するため、 YAML ファイルを準備します。(ここでは pod.yamlとします)
apiVersion: v1
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
args: ["--dockerfile=Dockerfile",
"--context=git://github.com/s*******-*****/*****.git",
"--destination=s*******/liberty-counter"]
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker
restartPolicy: Never
volumes:
- name: kaniko-secret
secret:
secretName: regcred
items:
- key: .dockerconfigjson
path: config.json
- gcr.io/kaniko-project/executor:latest
- kaniko イメージです。オフィシャルイメージ以外の利用はサポートされていません
- --dockerfile=Dockerfile
- Dockerfile のパスを指定します。
- ローカルファイル等の場合は volumeMounts でコンテナにマップされているパスを指定します。(/workspace/Dockerfile など)
- この例では、GitHub リポジトリのトップに Dockerfile があるため、Dockerfile としています。
- --context
- GitHub リポジトリの URL を指定します。 接頭辞は
https://
ではなくgit://
です。 - プライベートリポジトリを指定する場合は、git://GIT_TOKEN@github.com/... とするか、環境変数 GIT_TOKEN にリポジトリアクセス用のトークンを設定します
- GitHub リポジトリの URL を指定します。 接頭辞は
- --destination
- push 先コンテナレジストリの ID/リポジトリ名を指定します
また、 secret を volumeMount する部分は下図のようなイメージです。
(左が secret の yaml 出力、右が Pod の yaml です)
一言で言うと、secret 内の .dockerconfigjson の値を Pod 内の /kaniko/.docker/config.json にマップしています。
![]() |
---|
kaniko Pod の作成・コンテナイメージのビルド
Pod を作成すると、Dockerfile に沿ってイメージがビルドされ、コンテナレジストリに push されます
# kubectl apply -f pod.yaml
Pod の STATUS が Completed になれば完了です。
# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
kaniko 0/1 Completed 0 110s 10.200.211.221 k8swkr21 <none> <none>
Pod のログを確認します。(空行部分は、ログが一部省略されています)
# kubectl logs -f kaniko
Enumerating objects: 29, done.
Counting objects: 100% (29/29), done.
Compressing objects: 100% (22/22), done.
Total 29 (delta 3), reused 28 (delta 2), pack-reused 0
INFO[0009] Retrieving image manifest docker.io/websphere-liberty:webProfile8
INFO[0009] Retrieving image docker.io/websphere-liberty:webProfile8 from registry index.docker.io
INFO[0012] Retrieving image manifest docker.io/websphere-liberty:webProfile8
INFO[0012] Unpacking rootfs as cmd ADD --chown=1001:0 ./files /config requires it.
INFO[0031] LABEL maintainer "s*******@example.com"
INFO[0031] Applying label maintainer=s*******@example.com
INFO[0031] USER 1001
INFO[0031] cmd: USER
INFO[0031] Using files from context: [/kaniko/buildcontext/files]
INFO[0031] ADD --chown=1001:0 ./files /config
INFO[0031] Taking snapshot of files...
INFO[0031] COPY --chown=1001:0 ./war/LibertyCounter.war /config/dropins
INFO[0031] Taking snapshot of files...
INFO[0031] RUN configure.sh
INFO[0031] Taking snapshot of full filesystem...
INFO[0033] cmd: /bin/sh
INFO[0033] args: [-c configure.sh]
INFO[0033] Running: [/bin/sh -c configure.sh]
INFO[0080] Taking snapshot of full filesystem...
INFO[0085] Pushing image to s*******/liberty-counter
INFO[0110] Pushed image to 1 destinations
ビルド後、push したコンテナレジストリを確認すると、コンテナイメージが格納されていることがわかります。
![]() |
---|
(参考)ローカルディレクトリを利用する場合
kaniko のチュートリアル にもありますが、ローカルディレクトリ上に配置することも可能です。
ローカルディレクトリに配置する場合、 PV/PVC で volumeMount し、コンテナ内からアクセスできるようにする必要があります。
以下は チュートリアルの例に簡単な説明を付け加えた内容です。
まず、 適当なディレクトリ配下に Dockerfile と関連するファイル類を配置します。
(ここでは、 /data/tools/kaniko01
以下に配置しています)
そのディレクトリを Persistent Volume として定義します。( hostPath として /data/tools/kaniko01 を指定しています)
※ hostPath なので、ワーカーノードから見えるところに配置しておく必要があります。
apiVersion: v1
kind: PersistentVolume
metadata:
name: dockerfile
labels:
type: local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: local-storage
hostPath:
path: /data/tools/kaniko01
次に Persistent Volume Claim を作成して、先程の PV を claim します。
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: dockerfile-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: local-storage
PV、PVC の状態は以下のように STATUS が Bound になっています。
# kubectl get pv -o wide
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE VOLUMEMODE
dockerfile 10Gi RWO Retain Bound default/dockerfile-claim local-storage 7d Filesystem
# kubectl get pvc -o wide
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE VOLUMEMODE
dockerfile-claim Bound dockerfile 10Gi RWO local-storage 7d Filesystem
このPVC を Pod から利用します。
基本的には、secret の利用も含め最初に記載した pod と同じ形態ですが、
kaniko に渡す引数は以下の点が異なります。
- --dockerfile
- /workspace/Dockerfile としています。これは Dockerfile があるパスをコンテナの /workspace 以下にマウントするためです。
- --context
- dir://workspace です。ローカルディレクトリを使うため、
dir://
で、パスは workspace を指定しています。
- dir://workspace です。ローカルディレクトリを使うため、
apiVersion: v1
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
args: ["--dockerfile=/workspace/Dockerfile",
"--context=dir://workspace",
"--destination=s*******/hello-kaniko"]
volumeMounts:
- name: kaniko-secret
mountPath: /kaniko/.docker
- name: dockerfile-storage
mountPath: /workspace
restartPolicy: Never
volumes:
- name: kaniko-secret
secret:
secretName: regcred
items:
- key: .dockerconfigjson
path: config.json
- name: dockerfile-storage
persistentVolumeClaim:
claimName: dockerfile-claim
PV/PVC/Pod の関係は下図のようになります。
なお、Pod はどの worker ノード上で稼働するかわかりませんので、 PV はそれを考慮して共有のストレージ上に定義しておく必要があります。
![]() |
---|
ここまで準備ができればあとは、 pod を作成し、ビルドするだけです。
内容的には前述の内容と同じですので割愛します。
終わりに
コンテナイメージをビルドする際 docker は便利ですが、最近はdocker が無いコンテナ環境も多くなっています。
そういった環境下では kaniko が利用可能であることがわかりました。
kaniko Pod を作成し、GitHub 上のビルドコンテキストを取得、ビルドする、という方式は
将来的に CI/CD 等に拡張しやすいのではないかと思います。
今回、私にとっては (docker のない) kubernetes 環境のみでビルドが可能になる点がメリットになりました。
(ただし、普通は専用のビルド環境があると思いますので、限定されたケースかもしれません)
この先 kaniko を利用される方の参考になればうれしいです。
また、コメントやアドバイスなどがあればコメント欄でお知らせいただければ幸いです。
参考)
■ kaniko
https://github.com/GoogleContainerTools/kaniko