π§ ΠΠ°Π΄Π°ΡΠ°: ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠΉ CI/CD Π΄Π»Ρ Docker-ΠΎΠ±ΡΠ°Π·ΠΎΠ² Π² GitLab
Π£ΡΠ»ΠΎΠ²ΠΈΠ΅:
Π£ Π²Π°Ρ Π΅ΡΡΡ ΡΠ»Π΅Π΄ΡΡΡΠΈΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½:
build_and_push:
image: docker:latest
services:
- docker:dind
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" "$CI_REGISTRY"
- docker build -t "$CI_REGISTRY_IMAGE:latest" .
- docker push "$CI_REGISTRY_IMAGE:latest"
ΠΠ½ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ, Π½ΠΎ ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΡΠ΅ΡΡΡΠ·Π½ΡΠ΅ ΠΏΡΠΎΠ±Π»Π΅ΠΌΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ ΠΈ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ½ΡΠ΅ ΠΎΡΠΈΠ±ΠΊΠΈ.
π¨ ΠΡΠΎΠ±Π»Π΅ΠΌΡ:
1. `docker:dind` ΠΈ `tcp://docker:2375` β ΠΊΡΠΈΡΠΈΡΠ΅ΡΠΊΠΈ ΡΡΠ·Π²ΠΈΠΌΡ.
ΠΡΠΎ Π·Π½Π°ΡΠΈΡ, ΡΡΠΎ Π»ΡΠ±ΠΎΠΉ ΠΏΡΠΎΡΠ΅ΡΡ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠ»ΡΡΠΈΡΡ root-Π΄ΠΎΡΡΡΠΏ ΠΊ Docker-Π΄Π΅ΠΌΠΎΠ½Ρ, Π° Π·Π½Π°ΡΠΈΡ ΠΈ ΠΊ Ρ
ΠΎΡΡΡ ΡΠ°Π½Π½Π΅ΡΠ°.
2. ΠΠ΅Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ ΠΎΠ±ΡΠ°Π·ΠΎΠ² ΠΈΠ»ΠΈ ΡΠΊΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΡ.
Π ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ ΠΌΠΎΠΆΠ΅Ρ ΠΏΠΎΠΏΠ°ΡΡΡ ΡΡΠ·Π²ΠΈΠΌΡΠΉ ΠΎΠ±ΡΠ°Π·.
3. ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ ΡΠ΅Π³Π° `latest`.
Π’Π΅Π³ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΠΈΡΠ°ΡΡ Π² Π»ΡΠ±ΠΎΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ β Π½Π°ΡΡΡΠ°Π΅Ρ ΠΈΠ΄Π΅ΠΌΠΏΠΎΡΠ΅Π½ΡΠ½ΠΎΡΡΡ ΠΈ Π°ΡΠ΄ΠΈΡ.
4. ΠΠ°ΡΠΎΠ»ΠΈ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ
ΡΡΠ΅Π΄Ρ.
ΠΡΡΡΠ΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΡΠ΅ ΡΠΎΠΊΠ΅Π½Ρ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, OIDC).
5. ΠΠ΅Ρ ΠΈΠ·ΠΎΠ»ΡΡΠΈΠΈ ΡΠ±ΠΎΡΠΊΠΈ.
ΠΠ±ΡΠ°Π· ΠΌΠΎΠΆΠ΅Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ --privileged, --network=host, ΠΈ Π½Π΅ Π±ΡΡΡ sandboxed.
β Π¦Π΅Π»Ρ: ΠΠ΅ΡΠ΅Π΄Π΅Π»Π°ΡΡ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½
ΠΠ΅ΡΠ΅Ρ ΠΎΠ΄ ΠΎΡ DIND β kaniko, Π΄ΠΎΠ±Π°Π²ΠΈΡΡ ΠΏΡΠΎΠ²Π΅ΡΠΊΡ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ ΠΈ ΡΡΠ°Π±ΠΈΠ»ΡΠ½ΡΡ Π²Π΅ΡΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ.
π‘οΈ ΠΠ±Π½ΠΎΠ²Π»ΡΠ½Π½ΡΠΉ .gitlab-ci.yml
variables:
IMAGE_TAG: "${CI_COMMIT_SHORT_SHA}"
build_and_push:
image:
name: gcr.io/kaniko-project/executor:latest
entrypoint: [""]
script:
- echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
- /kaniko/executor \
--context $CI_PROJECT_DIR \
--dockerfile $CI_PROJECT_DIR/Dockerfile \
--destination $CI_REGISTRY_IMAGE:$IMAGE_TAG \
--destination $CI_REGISTRY_IMAGE:stable \
--snapshotMode=redo \
--single-snapshot
scan_image:
image: aquasec/trivy:latest
stage: test
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$IMAGE_TAG
π Π Π°Π·Π±ΠΎΡ ΡΠ»ΡΡΡΠ΅Π½ΠΈΠΉ:
β’ Kaniko β ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π±Π΅Π· ΠΏΡΠΈΠ²ΠΈΠ»Π΅Π³ΠΈΠΉ, Π½Π΅ ΡΡΠ΅Π±ΡΠ΅Ρ docker.sock
β’ `IMAGE_TAG` = SHA β Π²Π΅ΡΡΠΈΠΈ ΡΡΠ°Π±ΠΈΠ»ΡΠ½Ρ, audit-friendly
β’ Trivy β Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠ΅ ΡΠΊΠ°Π½ΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ ΡΡΠ·Π²ΠΈΠΌΠΎΡΡΠ΅ΠΉ
β’ Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ `latest` β ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ stable ΠΈ SHA
β’ ΠΠ΅Ρ `docker:dind` β Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π΅Π΅, ΠΏΡΠΎΡΠ΅ ΠΈ Π±ΡΡΡΡΠ΅Π΅
β’ ΠΠ΅Π·ΠΎΠΏΠ°ΡΠ½Π°Ρ Π°ΡΡΠ΅Π½ΡΠΈΡΠΈΠΊΠ°ΡΠΈΡ β ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ username/password Π½Π° OIDC Π² GitLab
π ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΠΎ:
1. ΠΠΎΠ±Π°Π²ΡΡΠ΅ rules: Π² ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½, ΡΡΠΎΠ±Ρ Π·Π°ΠΏΡΡΠΊΠ°ΡΡ ΡΠ±ΠΎΡΠΊΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΠΎ main ΠΈΠ»ΠΈ ΡΡΠ³Π°ΠΌ.
2. ΠΡΠΏΠΎΠ»ΡΠ·ΡΠΉΡΠ΅ readonly ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΡ ΠΈ fsGroup Π΅ΡΠ»ΠΈ ΠΏΡΠΈΠΌΠ΅Π½ΠΈΠΌΠΎ.
3. ΠΠ³ΡΠ°Π½ΠΈΡΡΡΠ΅ Π΄ΠΎΡΡΡΠΏ ΠΊ runner ΡΠ΅ΡΠ΅Π· protected: true.
π£ ΠΠΎΠ½ΡΡ: ΠΏΠΎΡΠ΅ΠΌΡ docker:dind = ΡΡΠ·Π²ΠΈΠΌΠΎΡΡΡ?
ΠΡΠ»ΠΈ runner Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡ Π² privileged ΡΠ΅ΠΆΠΈΠΌΠ΅, ΡΠΎ docker:dind Π΄Π°ΡΡ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡΡ Π²ΡΠΏΠΎΠ»Π½ΡΡΡ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»ΡΠ½ΡΠ΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ ΠΎΡ root Π²Π½ΡΡΡΠΈ ΠΈ Π²Π½Π΅ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ° β Π²ΠΊΠ»ΡΡΠ°Ρ ΠΌΠΎΠ½ΡΠΈΡΠΎΠ²Π°Π½ΠΈΠ΅ Ρ ΠΎΡΡΠΎΠ²ΡΡ Π΄ΠΈΡΠ΅ΠΊΡΠΎΡΠΈΠΉ. ΠΡΠΎ Π΄Π΅Π»Π°Π΅Ρ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΡΠΌ ΠΏΠΎΠ±Π΅Π³ ΠΈΠ· ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ°.
π‘ Π’Π°ΠΊΠΎΠΉ ΠΏΠ°ΠΉΠΏΠ»Π°ΠΉΠ½ Π½Π΅ ΡΠΎΠ»ΡΠΊΠΎ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½Π΅Π΅, Π½ΠΎ ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΏΡΠΎΠ·ΡΠ°ΡΠ΅Π½, ΠΌΠ°ΡΡΡΠ°Π±ΠΈΡΡΠ΅ΠΌ ΠΈ ΠΏΡΠ΅Π΄ΡΠΊΠ°Π·ΡΠ΅ΠΌ.