平常我們在pipeline裡面執行docker build的操作的時候,一般是下面的步驟,登入registry,根據dockerfile生成鏡像,給鏡像打标簽,然後推送到registry裡面。
docker login
docker build
docker tag
docker push
這種操作很常見。如果我們的CI工具本身是一個容器,我們會遇到docker in docker的問題。解決這種dind的一種做法是在挂載CI的容器的時候,挂載主控端的docker daemon, 比如 /var/run/docker.sock。另外一種方式就是使用dind的鏡像,在容器裡面嵌套容器。這兩種方式都有安全方面的問題,因為需要運作在特權模式下。
現在還有一種方式,就是kaniko。kaniko不依賴于docker daemon,每條docker指令都在使用者空間執行。是以很适合k8s這樣的環境。
官方文檔
https://github.com/GoogleContainerTools/kaniko
下面是一個例子,我把一個.net core app的docker 鏡像推送到Azure Container Registry裡面。 我已經在CI Variable裡面定義了三個變量用于驗證登入。kaniko可以把build,tag和push等操作一條指令就實作了,而且無需考慮docker in docker的問題。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5SM3ETO0UzN5MTO3EDM2YTMvwVMxgDMyIDMy8CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
build-code-job-main-V2:
image:
name: gcr.io/kaniko-project/executor:debug
entrypoint: [""]
stage: build
variables:
IMAGE_NAME: "dotnet_demo"
CONTAINER_SERVER: "gitlabazuredemo.azurecr.io"
script:
- echo "kaniko test"
- echo "$(pwd)"
- >-
/kaniko/executor
--context "$(pwd)"
--dockerfile "$(pwd)/Dockerfile"
--destination "${CONTAINER_SERVER}/${IMAGE_NAME}:${tagName}"
--destination "${CONTAINER_SERVER}/${IMAGE_NAME}:latest"
--destination "${CONTAINER_SERVER}/${IMAGE_NAME}:${CI_COMMIT_SHORT_SHA}"
rules:
- if: $CI_COMMIT_TAG =~ /^\d+\.\d+\.\d+.*/
- if: $CI_COMMIT_REF_NAME == "main"