終於,我們來到了整個系列的起點:CICD全容器化作業的野望。
曾經使用過Azure DevOps、Jenkins、Gitlab等CICD工具,也有一說是使用Dockerfile與Docker compose yaml來做CICD,都算是太過複雜跟難入門,而我的目標就是每個編譯環境我都要在同一個HOST做出來,彼此不受影響,甚至用過就拋棄,Jenkins跟Docker也有整合,但Jenkins也太肥大。
某次意外看到Drone CI這個工具,也就是容器原生的CICD工具,就想說,這應該就是我想要的了。
一開始用了gogs+drone,很明顯gogs是比較沒有維護的專案,所以遇到問題比較找不到資源,所以本次就改用gitlab+drone,經歷過幾次錯誤與排除,終於完整上線。
我這邊先講已經完成的CI pipeline:
version: "3"
name: cicd
services:
gitlab:
image: gitlab/gitlab-ce:16.4.1-ce.0
restart: always
networks:
ap_net:
ipv4_address: 172.18.0.2
ports:
- 8080:80
- 8443:443
- 22:22
volumes:
- "/home/ted/project/gitlab/config:/etc/gitlab"
- "/home/ted/project/gitlab/logs:/var/log/gitlab"
- "/home/ted/project/gitlab/data:/var/opt/gitlab"
drone:
image: drone/drone:2.20.0
volumes:
- "/home/ted/project/drone:/data"
environment:
- DRONE_GITLAB_SERVER=http://172.18.0.2
- DRONE_GITLAB_CLIENT_ID=xxx
- DRONE_GITLAB_CLIENT_SECRET=xxxxx
- DRONE_RPC_SECRET=xxxx
- DRONE_SERVER_HOST=172.18.0.4
- DRONE_SERVER_PROTO=http
- DRONE_USER_CREATE=username:root,admin:true
depends_on:
gitlab:
condition: service_healthy
ports:
- 80:80
- 8000:443
networks:
ap_net:
ipv4_address: 172.18.0.4
sonarqube:
image: sonarqube:8.9.10-community
volumes:
- "/home/ted/project/sonarqube/data:/opt/sonarqube/data"
- "/home/ted/project/sonarqube/logs:/opt/sonarqube/logs"
- "/home/ted/project/sonarqube/extensions:/opt/sonarqube/extensions"
ports:
- 9000:9000
networks:
ap_net:
ipv4_address: 172.18.0.6
networks:
ap_net:
external: true
version: "3"
name: runner
services:
drone-runner:
image: drone/drone-runner-docker:1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
ports:
- 3000:3000
environment:
- DRONE_RPC_PROTO=http
- DRONE_RPC_HOST=172.18.0.4
- DRONE_RPC_SECRET=xxxx
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=my-first-runner
- DRONE_RUNNER_NETWORKS=ap_net
- DRONE_USER_CREATE=username:root,admin:true
networks:
ap_net:
ipv4_address: 172.18.0.5
networks:
ap_net:
external: true
kind: pipeline
name: default
steps:
- name: package&scan
image: docker:dind
volumes:
- name: dockersock
path: /var/run/docker.sock
commands:
- docker compose -f docker-compose-build.yaml up
- name: sbom scan
image: docker:dind
volumes:
- name: dockersock
path: /var/run/docker.sock
commands:
- docker compose -f docker-compose-grype.yaml up
volumes:
- name: dockersock
host:
path: /var/run/docker.sock
總共兩個步驟,我用兩支compose yaml來寫:
version: "3"
name: scan
services:
sonarqube:
image: sonarqube:8.9.10-community
volumes:
- "/home/ted/project/sonarqube/data:/opt/sonarqube/data"
- "/home/ted/project/sonarqube/logs:/opt/sonarqube/logs"
- "/home/ted/project/sonarqube/extensions:/opt/sonarqube/extensions"
ports:
- 9000:9000
networks:
ap_net:
ipv4_address: 172.18.0.6
networks:
ap_net:
external: true
version: "3"
name: maven
services:
maven:
image: maven:3.9.4-eclipse-temurin-8-alpine
volumes:
- "/home/ted/project/xxx/source:/usr/src/mymaven"
- "/home/ted/project/xxx/m2:/root/.m2"
working_dir: /usr/src/mymaven
command: mvn clean package sonar:sonar -Dsonar.projectKey=xxx -Dsonar.host.url=http://sonarqube:9000 -Dsonar.login=xxx
networks:
- ap_net
networks:
ap_net:
external: true
version: "3"
name: grype
services:
grype:
image: anchore/grype:v0.69.1
volumes:
- "/home/ted/project/grypedb:/cache"
- "/home/ted/project/xxxx/source/target:/tmp"
environment:
- GRYPE_DB_CACHE_DIR=/cache
- GRYPE_DB_AUTO_UPDATE=false
command: /tmp/web.war -v --only-fixed
進入drone就可以看到,只要git push,就會自動啟動pipeline。
可以看到sonarqube的掃描紀錄
也可以進入drone去看grype掃描的結果。
後續可能再增加gate機制,如sonarqube掃描不通過,就run不下去,grype掃描war有critical也可以不run下去,或是跟webhook整合,通知執行結果。