| title |
|---|
GitLab CI/CD / Docker |
GitLab CI/CD / Docker
- Building Docker images with GitLab CI/CD | GitLab #ril
- 目前 CI/CD 的趨勢是先建立 application image、針對該 image 做測試、把 image 推到 remote registry,最後從拿推上去的 image 直接佈署;這裡有個範例
docker build -t my-image dockerfiles/->docker run my-docker-image /script/to/run/tests(test code 是放 image 裡??) ->docker tag my-image my-registry:5000/my-image->docker push my-registry:5000/my-image,注意 image 通過測試後才加上另一個 tag。 - GitLab CI 支援用 Docker Engine 去 build & test docker-based project,也就是 script 可以調用得到
docker或其他 docker-enabled tools (例如docker-compose)。用 shell executor 是一個方式 (加裝 Docker),但採用 docker-in-docker (dind) executor (priviledge mode) 是比較建議的 -- 其實是 docker executor + dind image,因為--docker-image只是預設的 image,若選用的 image 非 dind,還是調用不到docker` 指令。 - 要在 job 裡執行
docker build/run有 3 種方法 -- shell executor、docker-in-docker executor、使用 Docker socket binding。 - Use shell executor 的執行身份是
gitlab-runner,將它加到可以存取 Docker 的 group (docker) 即可。
- 目前 CI/CD 的趨勢是先建立 application image、針對該 image 做測試、把 image 推到 remote registry,最後從拿推上去的 image 直接佈署;這裡有個範例
- Setting up GitLab Runner For Continuous Integration | GitLab (2016-03-01) #ril
- GitLab runner 在 register 的過程中會被問 Please enter the default Docker image,預設值就是
ruby:2.1,而 "Note that the default Docker image specified here will be used only when .gitlab-ci.yml file does not contain an image declaration" 清楚說明了image:與--docker-image(default) 的關係。 - 實驗發現
gitlab register --docker-image所描述的 image 只有在.gitlab-ci.yml沒有自訂image:時才會作用,也就是預設的 image,可以從 job log 一開頭的 "Using Docker executor with image XXX ..." 及 "Using docker image XXX ID=sha256:... for build container..." 識別出來。
- GitLab runner 在 register 的過程中會被問 Please enter the default Docker image,預設值就是
- Using Docker images | GitLab #ril
- 原來 job 就是獨立執行,加上 Docker 就變成在獨立的 container 執行,讓 build environment 更為 reproducible。
image指定 docker exectutor 要採用哪個 image 來執行 job。services宣告 job 執行過程中要連結的其他 container (透過 hostname 存取);雖然 Extended Docker configuration options 能擴充的點不多,但 Configuring services 提到可以透過環境變數來組態這些 service #ril
- Register Docker Runner - Using Docker images - GitLab Documentation 出現
--docker-image ruby:2.1的用法,但ruby:2.1裡並沒有docker指令。 - Run GitLab Runner in a container - GitLab Documentation 跟 docker executor 不同?。
- DinD - Cannot connect to the Docker daemon. Is the docker daemon running on this host? (#1986) · Issues · GitLab.org / gitlab-runner · GitLab Alexander Herold: 建立
/var/run/docker.sock:/var/run/docker.sock的 mapping,但 Michael Potthoff: 問題在DOCKER_DRIVER: overlay因為沒這個 module,安裝 module 或拿掉這一行就可以了 (privileged要設為true),根本不用加/var/run/docker.sock:/var/run/docker.sock#ril
- Use docker-in-docker executor - Building Docker images with GitLab CI/CD | GitLab #ril
- The second approach is to use the special docker-in-docker (dind) Docker image with all tools installed (docker and docker-compose) and run the job script in context of that image in privileged mode. 這句話應該有誤? 基本上是搭配兩個 image,一個是 service container (
docker:dind) 提供 Docker daemon,另一個是 build/job/runner container (docker:stable) 做為 job script 的執行環境。而且docker:dind跟docker:stable裡都找一到docker-compose?? - 註冊 runner 時採
--executor docker、--docker-image "docker:stable"(Docker image to be used)、--docker-privileged(Give extended privileges to container)。感覺所有包話 service container (docker:dind) 也會執行在 priviledged mode,雖然官方 DinD 的說法,只有docker:dind要... - 使用 dind 時,每個 job 都執行在乾淨的環境下,concurrent jobs 間不會互相干擾,但由於沒有 caching of layers 的關係,速度會較慢。
- Since the
docker:dindcontainer and the runner container DON'T SHARE THEIR ROOT FILESYSTEM, the job's WORKING DIRECTORY can be used as a mount point for children containers. 搭配/builds/$CI_PROJECT_PATH(用$CI_PROJECT_DIR更好) 就可以把 working directory 的內容以 bind mount 的方式掛進 child container;這裡沒講清楚的是,也只有$CI_PROJECT_DIR底下的東西才能掛進 child container。
- The second approach is to use the special docker-in-docker (dind) Docker image with all tools installed (docker and docker-compose) and run the job script in context of that image in privileged mode. 這句話應該有誤? 基本上是搭配兩個 image,一個是 service container (
- Docker volumes not mounted when using docker:dind (#41227) · Issues · GitLab.org / GitLab Community Edition · GitLab 上面的 Use docker-in-docker executor - Building Docker images with GitLab CI/CD 提到這份文件 -- for a more thorough explanation, check issue #41227 重點都在 Tomasz Maczukin 的答覆
- Because each container by default is separated from other containers, the / filesystem in context of every one is also separated. Only volume mounts can be shared with HOST or with other container. Runner is creating few volumes (for cache, for job, defined in config.toml). For the purpose of this issue let's consider only the /builds volume. 這段話是關鍵,HOST (執行 GitLab Runner 的地方) 上面有個
buildsvolume,會掛進所有 container 的/builds下,所以只能先把資料放進/builds底下,再叫 Docker daemon 掛進 child container。 - When you're executing
docker run -v /mnt:/mnt ubuntu ls /mntyou're instructing Docker Engine inside ofdocker:dindservice to start a new, internal container and mount the local/mnt/directory under containers/mnt/directory. The important thing is that local/mntdirectory is local in context ofdocker:dindservice. 因為 Docker daemon 會以自己的角度解讀-v host_path:container_path中的host_path。
- Because each container by default is separated from other containers, the / filesystem in context of every one is also separated. Only volume mounts can be shared with HOST or with other container. Runner is creating few volumes (for cache, for job, defined in config.toml). For the purpose of this issue let's consider only the /builds volume. 這段話是關鍵,HOST (執行 GitLab Runner 的地方) 上面有個
- Build directory in service - The Docker executor | GitLab
- GitLab Runner 1.5 開始,會把
/builds掛進所有的 shared services。 - Mount volume with code from repository in services (#1520) · Issues · GitLab.org / gitlab-runner · GitLab 原來掛進 service 的說法並不正確,範例
docker run ... -v $(pwd):/tests是想把 working directory 的 test code 掛進去ruby:2.2執行,而非 service (docker:1.11-dind),不過 Tomasz Maczukin 跳出來說,這個問題早就解決,!272 是額外將/builds/my/project/掛進其他 service -- 這也包括docker:dindservice container?
- GitLab Runner 1.5 開始,會把
- continuous integration - Role of docker-in-docker (dind) service in gitlab ci - Stack Overflow
- 為什麼同時需要 service (
docker:dind) 與 docker image (docker:latest)? - saraedum:
docker:latest與docker:dind的內容很像,只不過docker:dind的 entrypoint 會啟動 Docker daemon,而docker:latest(或docker:stable) 的 entrypoint 會先組態往tcp://docker::2375找 Docker daemon。寫service: docker:dind就不需要在before_script啟動dockerd。
- 為什麼同時需要 service (
- library/docker - Docker Hub 觀察
docker:dind與docker:stable的Dockerfile,前者docker:dind的 entrypoint 會啟動 docker daemon 在 2375 port 服務,而後者docker:stable的 entrypoint 會先做export DOCKER_HOST='tcp://docker:2375'再執行 command,也因此有搭配--link dind-container:docker的話,在docker:stable內需要用到 Docker daemon 時,就會找tcp://docker:2375。
.gitlab-ci.yml:
image: docker:stable
variables:
CI_DEBUG_TRACE: "true"
MY_IMAGE: "nginx:1.15.0"
stages:
- test
test:
stage: test
tags:
- dind
script:
- echo 'settings (generated dynamically)' > settings.cfg
- docker run --rm -v $CI_PROJECT_DIR/settings.cfg:/workspace/settings.cfg $MY_IMAGE cat /workspace/settings.cfg
加上下面的宣告就沒問題了:
services:
- docker:dind
- Docker volumes not mounted when using docker:dind (#41227) · Issues · GitLab.org / GitLab Community Edition · GitLab 有討論到
docker:dind的作用? #ril
要在 docker:stable (Alpine) 下安裝 Docker Compose 其實不太容易,最簡單的方法就是直接利用官方提供的 docker/compose。
不過 docker/compose 的設定跟 docker:stable 不太一樣,要做些調整才能取代 docker:stable:
docker/compose的 entrypoint 是docker-compose,要改成/bin/sh -c。docker/compose不像docker:stable的 entrypoint 會自動加上DOCKER_HOST='tcp://docker:2375'的設定,會有檔案掛不進下一層 container 的問題。
所以使用 docker/compose 時,必要的配置會像是:
image:
name: docker/compose:1.24.0
entrypoint: ["/bin/sh", "-c"]
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_DRIVER: overlay2
參考資料:
-
Run docker-compose build in .gitlab-ci.yml - Stack Overflow
-
webmaster777: Docker compose also has an official image:
docker/composeThis is the ideal solution if you don't want to install it every pipeline. It has currently no latest tag, so you'll have to update manually.
Since the image uses
docker-composeas entrypoint you'll need to override the entrypoint back to /bin/sh -cin your.gitlab-ci.yml. Otherwise your pipeline will fail withNo such command: sh# Official docker compose image. image: name: docker/compose:1.22.0 # update tag to whatever version you want to use. entrypoint: ["/bin/sh", "-c"] services: - docker:dind before_script: - docker version - docker-compose version build: stage: build script: - docker-compose down - docker-compose build - docker-compose up tester-image
-
-
Use docker-in-docker executor - Building Docker images with GitLab CI/CD | GitLab #ril
image: docker:stable variables: # When using dind service we need to instruct docker, to talk with the # daemon started inside of the service. The daemon is available with # a network connection instead of the default /var/run/docker.sock socket. # # The 'docker' hostname is the alias of the service container as described at # https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#accessing-the-services # # Note that if you're using Kubernetes executor, the variable should be set to # tcp://localhost:2375 because of how Kubernetes executor connects services # to the job container DOCKER_HOST: tcp://docker:2375/ # When using dind, it's wise to use the overlayfs driver for # improved performance. DOCKER_DRIVER: overlay2 services: - docker:dind