Chuyển tới nội dung chính

Tài liệu CI/CD

1. Mục tiêu​

Tài liệu này hướng dẫn triển khai GitLab Runner bằng Docker theo mô hình:

  • GitLab Server: 192.168.1.234
  • GitLab Runner: 192.168.1.154
  • Docker Executor
  • Docker image docker:25.0.3
  • Docker daemon của máy Runner thông qua /var/run/docker.sock
  • GitLab Container Registry
  • HTTPS với CA nội bộ
  • Build và push Docker image từ GitLab CI/CD

Không sử dụng Docker-in-Docker (DinD).​

2. Kiến trúc hệ thống

┌──────────────────────────┐
│ GitLab Server │
│ │
│ Repository │
│ Container Registry :5050 │
│ HTTPS + CA nội bộ myCA │
└────────────┬─────────────┘
│
HTTPS / Git / Registry
│
▼
┌──────────────────────────┐
│ GitLab Runner │
│ │
│ Docker Executor │
│ privileged = true │
└────────────┬─────────────┘
│
│ tạo Job Container
▼
┌──────────────────────────┐
│ Job Container │
│ │
│ docker:25.0.3 │
│ Docker CLI │
└────────────┬─────────────┘
│
│ /var/run/docker.sock
▼
┌──────────────────────────┐
│ Docker daemon │
│ trên máy GitLab Runner │
│ Docker 25.x │
└────────────┬─────────────┘
│
docker push
│
▼
┌──────────────────────────┐
│ GitLab Container Registry│
│ :5050 │
└──────────────────────────┘

3. Luồng​

Thay vào đó, Job Container sử dụng Docker CLI và kết nối trực tiếp tới Docker daemon của máy Runner thông qua:

/var/run/docker.sock

Luồng:

GitLab CI Job
|
| docker CLI
v
/var/run/docker.sock
|
v
Docker daemon trên Runner
|
| HTTPS
v
GitLab Container Registry

4. Cài GitLab Runner bằng Docker

4.1. Pull image​

docker pull gitlab/gitlab-runner:latest

4.2. Tạo volume​

docker volume create gitlab-runner-config

4.3. Chạy GitLab Runner​

docker run -d \
--name gitlab-runner \
--restart always \
-v gitlab-runner-config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

Điểm quan trọng:

-v /var/run/docker.sock:/var/run/docker.sock

cho phép GitLab Runner sử dụng Docker daemon của máy host.

4.4. Kiểm tra​

docker ps
docker exec -it gitlab-runner gitlab-runner --version

5. Register GitLab Runner

Vào GitLab: https://gitlab-bh.sfb-cloud.local/ cấu hình:

  • Lưu ý: User phải có quyền Admin
Project
-> Settings
-> CI/CD
-> Runners

Sau đó: đăng ký gitlab runner có tên gitlab-bss-runner (tên runner này tùy mn đặt là gì cũng được)

docker exec -it gitlab-runner gitlab-runner register

Ví dụ:

Enter the GitLab instance URL:
https://gitlab-bh.sfb-cloud.local

Enter the registration token:
xxxxxxxx

Enter a description:
gitlab-bss-runner

Enter tags:
docker

Enter executor:
docker

Enter the default Docker image:
docker:25.0.3

6. Cấu hình config.toml

File:

/etc/gitlab-runner/config.toml

Ví dụ:

concurrent = 1
check_interval = 0
shutdown_timeout = 0
[session_server]
session_timeout = 1800
[[runners]]
name = "gitlab-bss-runner"
url = "https://gitlab-bh.sfb-cloud.local"
id = 4
token = "glrt-75gk_nXSn8Duhyp3XRgCZm86MQp0OjEKdToxCw.01.120of6y1v"
token_obtained_at = 2026-07-31T06:51:49Z
token_expires_at = 0001-01-01T00:00:00Z
executor = "docker"
[runners.cache]
MaxUploadedArchiveSize = 0
[runners.cache.s3]
AssumeRoleMaxConcurrency = 0
[runners.cache.gcs]
[runners.cache.azure]
[runners.docker]
tls_verify = false
image = "docker:25.0.3"
pull_policy = "if-not-present"
#privileged = true
privileged = false

services_privileged = false
disable_entrypoint_overwrite = false
oom_kill_disable = false
disable_cache = false
volumes = [
"/cache",
"/home/duchq/run/docker.sock:/var/run/docker.sock",
"/home/duchq/gitlab-runner/certs/ca.crt:/etc/gitlab-runner/certs/ca.crt:ro"
]
extra_hosts = [
"gitlab-bh.sfb-cloud.local:192.168.1.234"
]
volume_keep = false
shm_size = 0
network_mtu = 0

Điểm quan trọng nhất:

volumes = [
"/var/run/docker.sock:/var/run/docker.sock",
"/cache"
]

Job Container sẽ sử dụng Docker daemon của host Runner.

Sau khi thay đổi:

docker restart gitlab-runner

7. Docker Executor

GitLab Runner sử dụng Docker Executor để tạo container cho từng CI job.

Ví dụ:

image: docker:25.0.3

Container này chứa:

Docker CLI

Docker CLI kết nối tới Docker daemon của máy Runner thông qua:

/var/run/docker.sock

Không có Docker daemon thứ hai trong Job Container.

Mô hình:

┌─────────────────────────────┐
│ GitLab Runner │
│ │
│ ┌─────────────────────────┐ │
│ │ Job Container │ │
│ │ docker:25.0.3 │ │
│ │ │ │
│ │ Docker CLI │ │
│ └───────────┬─────────────┘ │
│ │ │
│ │ docker.sock │
│ ▼ │
│ ┌─────────────────────────┐ │
│ │ Docker daemon │ │
│ │ Host Runner │ │
│ └─────────────────────────┘ │
└─────────────────────────────┘

8. Docker 25.0.3

Job image:

image: docker:25.0.3

Kiểm tra:

docker --version

Ví dụ:

Docker version 25.0.3

Kiểm tra daemon:

docker info

Trong CI:

script:
- docker --version
- docker info

Nếu docker info chạy thành công thì Job Container đã kết nối được Docker daemon của Runner.


9. GitLab Container Registry

Ví dụ Registry:

gitlab-bh.sfb-cloud.local:5050

Đăng nhập:

docker login gitlab-bh.sfb-cloud.local:5050

Build:

docker build \
-t gitlab-bh.sfb-cloud.local:5050/project/app:latest \
.

Push:

docker push \
gitlab-bh.sfb-cloud.local:5050/project/app:latest

Trong GitLab CI nên sử dụng các biến:

CI_REGISTRY
CI_REGISTRY_IMAGE
CI_REGISTRY_USER
CI_REGISTRY_PASSWORD

Ví dụ:

docker login "$CI_REGISTRY" \
-u "$CI_REGISTRY_USER" \
-p "$CI_REGISTRY_PASSWORD"

10. Private CA

10.1. Vấn đề​

Nếu GitLab sử dụng certificate do CA nội bộ cấp:

GitLab Server
|
| Certificate
v
myCA

Docker có thể báo:

x509: certificate signed by unknown authority

Ví dụ:

Error response from daemon:
Get "https://gitlab-bh.sfb-cloud.local:5050/v2/":
tls: failed to verify certificate:
x509: certificate signed by unknown authority

10.2. Vị trí CA trong mô hình hiện tại​

Do không sử dụng DinD, Docker daemon thực hiện kết nối TLS là Docker daemon của máy GitLab Runner.

Do đó CA phải được cài cho Docker daemon trên máy Runner.

Không cần copy CA vào DinD vì không có DinD.

Cấu trúc:

Runner Host
└── Docker daemon
└── /etc/docker/certs.d/
└── gitlab-bh.sfb-cloud.local:5050/
└── ca.crt

11. Cấu hình CA trên Docker daemon của Runner

Trên máy GitLab Runner, tạo thư mục: user cũng cần có quyền sudo

sudo mkdir -p \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050

Copy CA:

sudo cp myCA.crt \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/ca.crt

Kiểm tra:

sudo ls -l \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/

Kết quả:

ca.crt

Sau đó restart Docker:

sudo systemctl restart docker

Kiểm tra:

docker info

Thử:

docker login \
gitlab-bh.sfb-cloud.local:5050 \
-u USER \
-p PASSWORD

Nếu thành công:

Login Succeeded

12. Nếu Runner không có sudo

Nếu user chạy GitLab Runner không có quyền sudo, việc cài CA vào Docker daemon phải được thực hiện bởi administrator của máy Runner.

Cần administrator thực hiện:

mkdir -p \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050
cp myCA.crt \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/ca.crt

Sau đó:

systemctl restart docker

Kiểm tra:

docker login \
gitlab-bh.sfb-cloud.local:5050

13. Cấu hình GitLab CI/CD hoàn chỉnh

.gitlab-ci.yml hoàn chỉnh:

Ví dụ:

variables:
GIT_DEPTH: "50"
TAG: "$CI_PIPELINE_ID-$CI_COMMIT_SHORT_SHA"
GIT_STRATEGY: clone

stages:
- build
- deploy

build-job:
stage: build
services:
- name: docker:25.0.3
script:
- cat /etc/hosts
- cd $CI_PROJECT_DIR
- git config --global http.sslverify false
- git clone -b dev https://$CI_USER:$CI_PASS@gitlab-bh.sfb-cloud.local/bh/v3/services/scheduler-service.git
- cd scheduler-service
- docker login $CI_REGISTRY -u $CI_USER -p $CI_PASS
- docker build -t scheduler-service:latest .

- |
if docker container inspect scheduler-service >/dev/null 2>&1; then
docker stop scheduler-service
docker rm scheduler-service
fi

- |
docker run -d \
--name scheduler-service \
--restart unless-stopped \
--env-file .env \
-p 8887:8887 \
scheduler-service
only:
- dev
tags:
- gitlab-bss-runner

deploy-job:
stage: deploy
services:
- name: docker:25.0.3
script:
- echo "Deploying application..."
- cd $CI_PROJECT_DIR
- mkdir gitops
- cd gitops
- git config --global http.sslverify false
- echo $CD_USER
- echo $CD_PASS
- git clone -b dev https://$CD_USER:$CD_PASS@gitlab-bh.sfb-cloud.local/devops/scheduler-service.git
- cd scheduler-service
- echo "New TAG=$TAG"
- oldTag=$(grep "tag:" values.yaml | awk -F' ' '{print $2}' | sed 's/"//g')
- echo "Old TAG=$oldTag"
- sed -i "s/$oldTag/$TAG/1" values.yaml
- grep "tag" values.yaml
- git config --global user.email "project_9_bot_a91df91cc59fe06a23f5a5b7e6b78379@noreply.gitlab-bh.sfb-cloud.local"
- git config --global user.name "project_9_bot_a91df91cc59fe06a23f5a5b7e6b78379"
- git add .
- git commit -m "deploy scheduler service with tag version $TAG"
- git push https://$CD_USER:$CD_PASS@gitlab-bh.sfb-cloud.local/devops/scheduler-service.git
- echo "Application successfully deployed."
only:
- dev
when: manual
tags:
- gitlab-bss-runner

14. Kiểm tra Docker socket

Trên Runner host:

ls -l /var/run/docker.sock

Ví dụ:

srw-rw---- 1 root docker ...

Kiểm tra GitLab Runner container:

docker exec -it gitlab-runner ls -l /var/run/docker.sock

Nếu thấy:

/var/run/docker.sock

thì socket đã được mount.


15. Kiểm tra Docker daemon từ Job Container

Tạo job:

test-docker:
image: docker:25.0.3

script:
- echo "===== DOCKER CLI ====="
- docker --version

- echo "===== DOCKER DAEMON ====="
- docker info

- echo "===== DOCKER PS ====="
- docker ps

Nếu:

docker info

thành công thì Docker CLI trong Job Container đang kết nối được Docker daemon của Runner.


16. Kiểm tra Registry

Trên Runner host:

docker login \
gitlab-bh.sfb-cloud.local:5050

Nếu lỗi:

x509: certificate signed by unknown authority

kiểm tra:

ls -l \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/

Phải có:

ca.crt

Kiểm tra certificate:

openssl s_client \
-connect gitlab-bh.sfb-cloud.local:5050 \
-showcerts

Kiểm tra CA:

openssl x509 \
-in myCA.crt \
-text \
-noout

17. Debug TLS

Có thể kiểm tra từ Runner host:

curl -v \
https://gitlab-bh.sfb-cloud.local:5050/v2/

Hoặc:

openssl s_client \
-connect gitlab-bh.sfb-cloud.local:5050 \
-CAfile myCA.crt

Nếu certificate hợp lệ sẽ không xuất hiện lỗi:

unable to get local issuer certificate

hoặc:

certificate verify failed

nếu hệ thống đã có:

HTTPS
+
Certificate
+
CA nội bộ

Nên sử dụng:

Docker daemon trên Runner
|
| Trusted CA
v
HTTPS
|
v
GitLab Container Registry

18. Bảo mật Docker socket

Mô hình:

/var/run/docker.sock

có ưu điểm:

  • Không cần DinD.
  • Cấu hình đơn giản hơn.
  • Build nhanh.
  • Không phải quản lý thêm Docker daemon.
  • Dễ debug.
  • Docker daemon là Docker daemon thật của Runner host.

Nhưng có một điểm bảo mật quan trọng:

Job Container
|
v
/var/run/docker.sock
|
v
Docker daemon trên Runner

Container có quyền truy cập Docker socket về cơ bản có khả năng điều khiển Docker daemon của host.

Vì vậy chỉ nên dùng mô hình này với:

  • Runner được tin tưởng.
  • Project/repository được kiểm soát.
  • Không chạy untrusted CI code trên Runner này.
  • Không dùng chung Runner cho các project không tin cậy.

19. Quy trình CI hoàn chỉnh

Developer
│
│ git push dev
▼
┌──────────────────────────┐
│ GitLab Server │
│ gitlab-bh.sfb-cloud.local│
└────────────┬─────────────┘
│
│ Trigger Pipeline
▼
┌──────────────────────────┐
│ GitLab Runner │
│ tag: gitlab-bss-runner │
└────────────┬─────────────┘
│
▼
┌──────────────┐
│ BUILD STAGE │
└──────┬───────┘
│
├── clone scheduler-service
│
├── docker login
│
├── docker build
│
├── stop container cũ
│
├── remove container cũ
│
└── docker run container mới
│
▼
┌──────────────┐
│ DEPLOY STAGE │
└──────┬───────┘
│
├── manual approval
│
├── clone GitOps repo
│
├── đọc tag cũ
│
├── thay tag mới
│
├── git commit
│
└── git push
│
▼
GitOps Repository

20. Kiểm tra hệ thống theo từng tầng

Tầng 1 - GitLab Runner​

docker ps
docker exec -it gitlab-runner gitlab-runner verify

Tầng 2 - Runner configuration​

Kiểm tra:

cat /home/duchq/gitlab-runner/config/config.toml

Đặc biệt:

executor = "docker"

và:

volumes = [
"/var/run/docker.sock:/var/run/docker.sock",
"/cache"
]

Tầng 3 - Job Container​

Kiểm tra:

docker --version

Phải là:

Docker version 25.0.3

Tầng 4 - Docker socket​

Kiểm tra: url: /home/duchq theo từng thư mục

ls -l /home/duchq/run/docker.sock

Tầng 5 - Docker daemon​

Kiểm tra:

docker info

Tầng 6 - CA​

Kiểm tra:

ls -l \
/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/

Phải có:

ca.crt

Tầng 7 - Registry​

Kiểm tra:

docker login \
gitlab-bh.sfb-cloud.local:5050

Tầng 8 - Build​

docker build -t test-image:latest .

Tầng 9 - Push​

docker push \
gitlab-bh.sfb-cloud.local:5050/project/app:latest

21. Các lỗi thường gặp

21.1. Cannot connect to the Docker daemon​

Lỗi:

Cannot connect to the Docker daemon

Kiểm tra Runner có mount socket:

volumes = [
"/var/run/docker.sock:/var/run/docker.sock",
"/cache"
]

Kiểm tra Job:

ls -l /var/run/docker.sock

Kiểm tra:

docker info

21.2. x509 unknown authority​

Lỗi:

x509: certificate signed by unknown authority

Trong mô hình không dùng DinD, CA phải nằm trên Runner host, tại:

/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/ca.crt

Không phải:

Job Container

và không phải:

DinD Container

vì hệ thống không sử dụng DinD.


21.3. docker login thất bại​

Kiểm tra:

docker login \
gitlab-bh.sfb-cloud.local:5050

Kiểm tra:

CI_REGISTRY
CI_REGISTRY_IMAGE
CI_REGISTRY_USER
CI_REGISTRY_PASSWORD

21.4. Build thành công nhưng push thất bại​

Nếu:

docker build

thành công nhưng:

docker push

thất bại với:

x509: certificate signed by unknown authority

thì kiểm tra CA của Docker daemon trên Runner:

/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/ca.crt

22. Tài liệu chính thức

GitLab Runner:

https://docs.gitlab.com/runner/

Docker Executor:

https://docs.gitlab.com/runner/executors/docker/

GitLab Container Registry:

https://docs.gitlab.com/user/packages/container_registry/


23. Mô hình khuyến nghị cho hệ thống hiện tại

Với hệ thống:

GitLab:
gitlab-bh.sfb-cloud.local

Registry:
gitlab-bh.sfb-cloud.local:5050

CA:
myCA

Runner:
gitlab-bss-runner

Executor:
Docker

Job Image:
docker:25.0.3

Docker daemon:
Docker daemon trên Runner host

mô hình:

┌───────────────────────────────────────────────┐
│ GitLab Server │
│ │
│ gitlab-bh.sfb-cloud.local │
│ │
│ ┌──────────────┐ ┌─────────────────────┐ │
│ │ GitLab │ │ Container Registry │ │
│ │ Repository │ │ :5050 │ │
│ └──────┬───────┘ └──────────▲──────────┘ │
└────────┼─────────────────────────┼────────────┘
│ │
│ Git │ HTTPS + myCA
│ │
▼ │
┌──────────────────────────────────┴────────────┐
│ GitLab Runner Host │
│ │
│ ┌───────────────────────────────────────────┐ │
│ │ GitLab Runner │ │
│ │ Docker Executor │ │
│ │ │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ Job Container │ │ │
│ │ │ │ │ │
│ │ │ image: docker:25.0.3 │ │ │
│ │ │ │ │ │
│ │ │ Docker CLI │ │ │
│ │ └──────────────────┬────────────────────┘ │ │
│ │ │ │ │
│ │ │ /var/run/docker.sock │ │
│ │ ▼ │ │
│ │ ┌───────────────────────────────────────┐ │ │
│ │ │ Docker daemon │ │ │
│ │ │ │ │ │
│ │ │ /etc/docker/certs.d/ │ │ │
│ │ │ gitlab-bh.sfb-cloud.local:5050/ │ │ │
│ │ │ ca.crt │ │ │
│ │ └───────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────┘ │
└───────────────────────────────────────────────┘

Điểm cốt lõi:

docker:25.0.3
|
| Docker CLI
v
/var/run/docker.sock
|
v
Docker daemon trên Runner Host
|
| HTTPS + myCA
v
GitLab Registry :5050

CA được cấu hình tại Docker daemon của Runner Host:

/etc/docker/certs.d/gitlab-bh.sfb-cloud.local:5050/ca.crt