使用 Docker 快速搭建 Jenkins 持续集成服务,支持 Docker in Docker 和 WebSocket。

Docker 部署

docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
version: '3'
services:
jenkins:
image: jenkins/jenkins:lts
user: root
restart: always
container_name: jenkins
extra_hosts:
- "git.example.com:192.168.1.100" # 内部 Git 服务器
ports:
- "127.0.0.1:8080:8080" # Web UI
- "127.0.0.1:50000:50000" # Agent 连接
volumes:
- ${HOME}/jenkins/jenkins_home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock # Docker in Docker
- ${HOME}/.docker:/root/.docker # Docker 配置
- ${HOME}/.ssh:/root/.ssh # SSH 密钥
environment:
# Session 超时设置(秒)
- JENKINS_OPTS=--sessionTimeout=43200 --sessionEviction=604800

启动

1
2
3
4
docker-compose up -d

# 查看初始密码
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

Nginx 反向代理

WebSocket 支持配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# WebSocket 升级映射
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}

# Upstream 配置
upstream jenkins {
keepalive 32;
server 127.0.0.1:8080;
}

server {
listen 80;
server_name jenkins.example.com;
return 301 https://$host$request_uri;
}

server {
listen 443 ssl;
server_name jenkins.example.com;

# SSL 证书
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

# 日志
access_log /var/log/nginx/jenkins.access.log;
error_log /var/log/nginx/jenkins.error.log;

# 允许无效 Header(Jenkins 需要)
ignore_invalid_headers off;

# 静态文件优化
location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
}

# UserContent 目录
location /userContent {
root /var/jenkins_home/;
if (!-f $request_filename) {
rewrite (.*) /$1 last;
break;
}
sendfile on;
}

# 主要代理配置
location / {
sendfile off;
proxy_pass http://jenkins;
proxy_redirect default;
proxy_http_version 1.1;

# WebSocket 支持(Agent 连接必需)
proxy_set_header Connection $connection_upgrade;
proxy_set_header Upgrade $http_upgrade;

# 标准 Header
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

# 上传大小限制
client_max_body_size 10m;
client_body_buffer_size 128k;

# 超时设置
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;

# 禁用缓冲(HTTP CLI 命令必需)
proxy_buffering off;
proxy_request_buffering off;
proxy_max_temp_file_size 0;

# Keepalive 设置
proxy_set_header Connection "";
}
}

Docker in Docker 配置

安装 Docker 客户端

进入 Jenkins 容器安装 Docker CLI:

1
2
3
4
5
6
7
8
docker exec -it jenkins bash

# 安装 Docker CLI
apt-get update
apt-get install -y docker.io

# 验证
docker ps

或使用自定义镜像

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
FROM jenkins/jenkins:lts

USER root

# 安装 Docker CLI
RUN apt-get update && \
apt-get install -y docker.io && \
rm -rf /var/lib/apt/lists/*

# 安装 Docker Compose
RUN curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose && \
chmod +x /usr/local/bin/docker-compose

USER jenkins

构建:

1
docker build -t my-jenkins .

Pipeline 示例

Jenkinsfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
pipeline {
agent any

environment {
DOCKER_REGISTRY = 'docker.example.com'
IMAGE_NAME = 'myapp'
}

stages {
stage('Checkout') {
steps {
git 'https://github.com/example/repo.git'
}
}

stage('Build') {
steps {
sh 'docker build -t ${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER} .'
}
}

stage('Push') {
steps {
script {
docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-credentials') {
sh 'docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}'
}
}
}
}

stage('Deploy') {
steps {
sh '''
docker stop myapp || true
docker rm myapp || true
docker run -d --name myapp -p 8080:8080 \
${DOCKER_REGISTRY}/${IMAGE_NAME}:${BUILD_NUMBER}
'''
}
}
}

post {
always {
cleanWs()
}
}
}

常用插件

1
2
3
4
5
6
# 在 Jenkins 插件管理中安装
- Blue Ocean # 现代化 UI
- Docker Plugin # Docker 集成
- Git Plugin # Git 集成
- Pipeline # Pipeline 支持
- Kubernetes Plugin # K8s 部署

注意事项

  • WebSocket 配置对 Agent 连接至关重要
  • 定期备份 /var/jenkins_home 目录
  • user: root 是为了访问 Docker socket,生产环境建议使用 Docker 组
  • Session 超时设置避免频繁登录
  • 建议配置 HTTPS 和 CSRF 保护

参考资料