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