📋 前置条件
- 已安装 Docker 和 Docker Compose
- Linux/Mac 环境(或 WSL2)
- 有一个运行中的 Jenkins 实例
- SSH 密钥对用于部署(可选但建议)
🏗️ 第一步:创建项目目录结构
bash
# 进入你的工作目录,比如
cd /home
# Jenkins 主目录
mkdir -p jenkins-agents/{jenkins-home,agent-node,agent-java-17,agent-java-21,jenkins-cache/{pnpm-store,m2}}
# 各 agent 的工作目录
mkdir -p jenkins-agents/agent-node/work
mkdir -p jenkins-agents/agent-java-17/work
mkdir -p jenkins-agents/agent-java-21/work
# 查看目录结构
tree -L 2
# 或者用 ls -la
ls -la
目录结构应该如下:
bash
jenkins-agents/
├── agent-java-17
│ ├── Dockerfile
│ ├── start-agent.sh
│ └── work/
├── agent-java-21
│ ├── Dockerfile
│ ├── start-agent.sh
│ └── work/
├── agent-node
│ ├── Dockerfile
│ ├── start-agent.sh
│ └── work/
├── jenkins-cache/
│ ├── m2/
│ └── pnpm-store/
├── jenkins-home/
├── .env
└── docker-compose.yml
🔧 第二步:配置 .env 文件
在 jenkins-agents 目录下创建 .env 文件:xxxxxxxxxxxxxxxxxxxxxxxx,要在 Jenkins 管理界面创建节点中获取,当前步骤先用占位符
bash
cat > .env << 'EOF'
# Jenkins 基础配置
JENKINS_URL=http://jenkins:8080
# Node.js agent Secret(从 Jenkins 获取)
JENKINS_SECRET_NODE=xxxxxxxxxxxxxxxxxxxxxxxx
# Java 17 agent Secret(从 Jenkins 获取)
JENKINS_SECRET_JAVA_17=xxxxxxxxxxxxxxxxxxxxxxxx
# Java 21 agent Secret(从 Jenkins 获取)
JENKINS_SECRET_JAVA_21=xxxxxxxxxxxxxxxxxxxxxxxx
# 时区配置
TZ=Asia/Shanghai
EOF
替换所有 Secret 值为你在 Jenkins 中获取的真实值。
📝 第三步:创建各 Agent 的 Dockerfile
3.1.1 创建 Node.js Agent Dockerfile
bash
cat > agent-node/Dockerfile << 'EOF'
# 基础镜像:包含 JDK 21
FROM eclipse-temurin:21-jdk
# 时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 常用工具
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl unzip zip bash sudo procps openssh-client \
&& rm -rf /var/lib/apt/lists/*
# Node.js 安装
ENV NODE_VERSION=24.1.0
ENV NODE_DIST_URL=https://mirrors.aliyun.com/nodejs-release/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz
RUN curl -fsSL $NODE_DIST_URL -o /tmp/node.tar.gz \
&& tar -xzf /tmp/node.tar.gz -C /opt \
&& rm /tmp/node.tar.gz
ENV NODE_HOME=/opt/node-v${NODE_VERSION}-linux-x64
ENV PATH=$NODE_HOME/bin:$PATH
# pnpm 安装
RUN npm config set registry https://registry.npmmirror.com
RUN npm install -g pnpm
# Jenkins agent 工作目录
ENV JENKINS_AGENT_WORKDIR=/home/jenkins/agent
RUN mkdir -p $JENKINS_AGENT_WORKDIR && chmod -R 777 $JENKINS_AGENT_WORKDIR
WORKDIR $JENKINS_AGENT_WORKDIR
# 拷贝启动脚本
COPY start-agent.sh /home/jenkins/start-agent.sh
RUN chmod +x /home/jenkins/start-agent.sh
# 默认执行启动脚本
ENTRYPOINT ["/home/jenkins/start-agent.sh"]
EOF
3.1.2 创建 Node.js Agent start-agent.sh
bash
cat > agent-node/start-agent.sh << 'EOF'
#!/bin/bash
set -e
echo "等待 Jenkins 启动..."
until curl -sf "$JENKINS_URL/login" > /dev/null; do
sleep 3
done
echo "Jenkins 已就绪,下载 agent.jar..."
curl -sSf "$JENKINS_URL/jnlpJars/agent.jar" -o agent.jar
echo "启动 Jenkins Agent..."
exec java -jar agent.jar \
-url "$JENKINS_URL" \
-secret "$JENKINS_SECRET" \
-name "$JENKINS_AGENT_NAME" \
-webSocket \
-workDir "$JENKINS_AGENT_WORKDIR"
EOF
3.2.1 创建 Java 17 Agent Dockerfile
bash
cat > agent-java-17/Dockerfile << 'EOF'
# 基础镜像:包含 JDK 17
FROM eclipse-temurin:17-jdk
# 时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 常用工具
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl unzip zip bash sudo procps openssh-client \
&& rm -rf /var/lib/apt/lists/*
# Maven
ENV MAVEN_VERSION=3.9.11
ENV MAVEN_DOWNLOAD_URL=https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz
RUN curl -fsSL $MAVEN_DOWNLOAD_URL | tar -xz -C /opt
ENV MAVEN_HOME=/opt/apache-maven-$MAVEN_VERSION
ENV PATH=$MAVEN_HOME/bin:$PATH
# Gradle
ENV GRADLE_VERSION=9.2.1
ENV GRADLE_DOWNLOAD_URL=https://mirrors.aliyun.com/gradle/distributions/v$GRADLE_VERSION/gradle-$GRADLE_VERSION-bin.zip
RUN curl -fsSL $GRADLE_DOWNLOAD_URL -o /tmp/gradle.zip \
&& unzip /tmp/gradle.zip -d /opt && rm /tmp/gradle.zip
ENV GRADLE_HOME=/opt/gradle-$GRADLE_VERSION
ENV PATH=$GRADLE_HOME/bin:$PATH
# Jenkins agent 工作目录
ENV JENKINS_AGENT_WORKDIR=/home/jenkins/agent
RUN mkdir -p $JENKINS_AGENT_WORKDIR && chmod -R 777 $JENKINS_AGENT_WORKDIR
WORKDIR $JENKINS_AGENT_WORKDIR
# 拷贝启动脚本
COPY start-agent.sh /home/jenkins/start-agent.sh
RUN chmod +x /home/jenkins/start-agent.sh
# 默认执行启动脚本
ENTRYPOINT ["/home/jenkins/start-agent.sh"]
EOF
3.2.2 创建 Java 17 start-agent.sh
bash
cat > agent-java-17/start-agent.sh << 'EOF'
#!/bin/bash
set -e
echo "等待 Jenkins 启动..."
until curl -sf "$JENKINS_URL/login" > /dev/null; do
sleep 3
done
echo "Jenkins 已就绪,下载 agent.jar..."
curl -sSf "$JENKINS_URL/jnlpJars/agent.jar" -o agent.jar
echo "启动 Jenkins Agent..."
exec java -jar agent.jar \
-url "$JENKINS_URL" \
-secret "$JENKINS_SECRET" \
-name "$JENKINS_AGENT_NAME" \
-webSocket \
-workDir "$JENKINS_AGENT_WORKDIR"
EOF
3.3.1 创建 Java 21 Agent Dockerfile
bash
cat > agent-java-21/Dockerfile << 'EOF'
# 基础镜像:包含 JDK 21
FROM eclipse-temurin:21-jdk
# 时区
ENV TZ=Asia/Shanghai
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
# 常用工具
RUN apt-get update && apt-get install -y --no-install-recommends \
git curl unzip zip bash sudo procps openssh-client \
&& rm -rf /var/lib/apt/lists/*
# Maven
ENV MAVEN_VERSION=3.9.11
ENV MAVEN_DOWNLOAD_URL=https://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz
RUN curl -fsSL $MAVEN_DOWNLOAD_URL | tar -xz -C /opt
ENV MAVEN_HOME=/opt/apache-maven-$MAVEN_VERSION
ENV PATH=$MAVEN_HOME/bin:$PATH
# Gradle
ENV GRADLE_VERSION=9.2.1
ENV GRADLE_DOWNLOAD_URL=https://mirrors.aliyun.com/gradle/distributions/v$GRADLE_VERSION/gradle-$GRADLE_VERSION-bin.zip
RUN curl -fsSL $GRADLE_DOWNLOAD_URL -o /tmp/gradle.zip \
&& unzip /tmp/gradle.zip -d /opt && rm /tmp/gradle.zip
ENV GRADLE_HOME=/opt/gradle-$GRADLE_VERSION
ENV PATH=$GRADLE_HOME/bin:$PATH
# Jenkins agent 工作目录
ENV JENKINS_AGENT_WORKDIR=/home/jenkins/agent
RUN mkdir -p $JENKINS_AGENT_WORKDIR && chmod -R 777 $JENKINS_AGENT_WORKDIR
WORKDIR $JENKINS_AGENT_WORKDIR
# 拷贝启动脚本
COPY start-agent.sh /home/jenkins/start-agent.sh
RUN chmod +x /home/jenkins/start-agent.sh
# 默认执行启动脚本
ENTRYPOINT ["/home/jenkins/start-agent.sh"]
EOF
3.3.2 创建 Java 21 start-agent.sh
bash
cat > agent-java-21/start-agent.sh << 'EOF'
#!/bin/bash
set -e
echo "等待 Jenkins 启动..."
until curl -sf "$JENKINS_URL/login" > /dev/null; do
sleep 3
done
echo "Jenkins 已就绪,下载 agent.jar..."
curl -sSf "$JENKINS_URL/jnlpJars/agent.jar" -o agent.jar
echo "启动 Jenkins Agent..."
exec java -jar agent.jar \
-url "$JENKINS_URL" \
-secret "$JENKINS_SECRET" \
-name "$JENKINS_AGENT_NAME" \
-webSocket \
-workDir "$JENKINS_AGENT_WORKDIR"
EOF
验证所有 Dockerfile 已创建:
bash
ls -la agent-*/Dockerfile
📦 第四步:创建 docker-compose.yml
bash
cat > docker-compose.yml << 'EOF'
networks:
jenkins-net:
driver: bridge
services:
# Jenkins 主节点
jenkins:
image: jenkins/jenkins:lts
container_name: jenkins
user: "1000:1000"
networks:
- jenkins-net
ports:
- "8080:8080"
- "50000:50000"
volumes:
- ./jenkins-home:/var/jenkins_home
- /var/run/docker.sock:/var/run/docker.sock
environment:
TZ: Asia/Shanghai
restart: unless-stopped
# Node.js agent
agent-node:
build:
context: ./agent-node
dockerfile: Dockerfile
container_name: jenkins-agent-node
networks:
- jenkins-net
env_file:
- .env
environment:
JENKINS_URL: "http://jenkins:8080"
JENKINS_AGENT_NAME: "node-agent"
JENKINS_SECRET: "${JENKINS_SECRET_NODE}"
TZ: Asia/Shanghai
volumes:
- ./agent-node/work:/home/jenkins/agent
- ./jenkins-cache/pnpm-store:/root/.pnpm-store
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- jenkins
restart: unless-stopped
# Java 17 agent
agent-java-17:
build:
context: ./agent-java-17
dockerfile: Dockerfile
container_name: jenkins-agent-java-17
networks:
- jenkins-net
env_file:
- .env
environment:
JENKINS_URL: "http://jenkins:8080"
JENKINS_AGENT_NAME: "java-agent-17"
JENKINS_SECRET: "${JENKINS_SECRET_JAVA_17}"
TZ: Asia/Shanghai
volumes:
- ./agent-java-17/work:/home/jenkins/agent
- ./jenkins-cache/m2:/root/.m2
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- jenkins
restart: unless-stopped
# Java 21 agent
agent-java-21:
build:
context: ./agent-java-21
dockerfile: Dockerfile
container_name: jenkins-agent-java-21
networks:
- jenkins-net
env_file:
- .env
environment:
JENKINS_URL: "http://jenkins:8080"
JENKINS_AGENT_NAME: "java-agent-21"
JENKINS_SECRET: "${JENKINS_SECRET_JAVA_21}"
TZ: Asia/Shanghai
volumes:
- ./agent-java-21/work:/home/jenkins/agent
- ./jenkins-cache/m2:/root/.m2
- /var/run/docker.sock:/var/run/docker.sock
depends_on:
- jenkins
restart: unless-stopped
EOF
🔐 第五步:设置文件权限
bash
# 切换到 jenkins-agents 目录
cd /home/jenkins-agents
# 设置所有者(根据你的用户调整)
sudo chown -R 1000:1000 jenkins-home
sudo chown -R 1000:1000 jenkins-cache
# 设置权限
sudo chmod -R 755 jenkins-home
sudo chmod -R 755 jenkins-cache
# 创建必要的子目录权限
sudo chmod -R 777 jenkins-cache/pnpm-store
sudo chmod -R 777 jenkins-cache/m2
sudo chmod -R 777 jenkins-cache/docker-cache
# 验证权限
ls -la | grep jenkins
如果你用的是当前用户(非 root):
bash
# 如果 jenkins-agents 在你的用户目录下
chmod -R 755 jenkins-home
chmod -R 755 jenkins-cache
chmod -R 777 jenkins-cache/pnpm-store
chmod -R 777 jenkins-cache/m2
chmod -R 777 jenkins-cache/docker-cache
🚀 第六步:启动所有服务
bash
# 进入项目目录
cd /home/jenkins-agents
# 构建所有镜像(第一次运行)
docker compose build
# 启动所有服务
docker compose up -d
# 查看启动日志
docker compose logs -f
# 检查所有容器状态
docker compose ps
预期输出:
bash
NAME STATUS
jenkins Up 2 minutes
jenkins-agent-node Up 1 minute
jenkins-agent-java-17 Up 1 minute
jenkins-agent-java-21 Up 1 minute
🔐 第七步:生成 Jenkins Secret
7.1 在 Jenkins 管理界面创建节点
- 登录 Jenkins → 管理 Jenkins → 节点管理
- 点击 新建节点 3 次,创建:
node-agentjava-agent-17java-agent-21
7.2 配置每个节点
以 node-agent 为例:
- 节点名称 :
node-agent - 类型 :选择
Permanent Agent - Remote root directory :
/home/jenkins/agent - 标签 :
node(可选) - 启动方式 :选择
通过Java Web启动代理 - 自定义 WorkDir 路径 :
/home/jenkins/agent
点击保存后,你会看到一个连接命令,里面有 Secret,如下:
bash
curl -sSf http://YOUR_JENKINS_URL/jnlpJars/agent.jar
java -jar agent.jar -url http://YOUR_JENKINS_URL -secret xxxxxxxxxxxxxxxxxxxxxxxx -name JENKINS_AGENT_NAME -webSocket -workDir JENKINS_AGENT_WORKDIR
提取 Secret 部分 (-secret 后面的那串)并记录下来。
7.3 重复创建其他 3 个节点,记录所有 Secret
7.4 将记录所有 Secret,替换 .env 文件中的 agent Secret,然后重启服务
✅ 第八步:验证节点连接
方式一:通过 Jenkins 管理界面
- 登录 Jenkins → 管理 Jenkins → 节点管理
- 检查所有 3 个节点是否显示为 "Online"
- 如果显示 "Offline",查看节点日志
方式二:通过命令行查看日志
bash
# 查看 Node agent 日志
docker compose logs jenkins-agent-node
# 查看 Java 17 agent 日志
docker compose logs jenkins-agent-java-17
# 实时查看所有日志
docker compose logs -f
成功连接的日志示例:
bash
jenkins-agent-node | 2024-12-10 10:15:30 ... Successfully connected
🧪 第九步:测试 Pipeline
在 Jenkins 创建一个测试 Pipeline,使用以下 Jenkinsfile:
groovy
pipeline {
agent {
label 'node' // 使用 node-agent
}
stages {
stage('Test Node') {
steps {
sh 'node --version'
sh 'pnpm --version'
sh 'git --version'
}
}
}
}
测试 Java 17
groovy
pipeline {
agent {
label 'java-agent-17'
}
stages {
stage('Test Java 17') {
steps {
sh 'java -version'
sh 'mvn --version'
sh 'gradle --version'
}
}
}
}
🛠️ 常用命令
bash
# 启动服务
docker compose up -d
# 停止服务
docker compose down
# 重启特定服务
docker compose restart jenkins-agent-node
# 查看实时日志
docker compose logs -f jenkins-agent-node
# 进入容器调试
docker compose exec jenkins-agent-node bash
# 重新构建镜像
docker compose build --no-cache
# 查看容器资源使用
docker stats
# 删除所有数据(谨慎!)
docker compose down -v
🔧 故障排查
问题 1:节点显示 "Offline"
bash
# 查看连接日志
docker compose logs jenkins-agent-node
# 检查 .env 中的 Secret 是否正确
cat .env | grep JENKINS_SECRET
# 重启 agent
docker compose restart jenkins-agent-node
问题 2:构建时权限错误
bash
# 检查缓存目录权限
ls -la jenkins-cache/
# 重新设置权限
chmod -R 777 jenkins-cache/m2
chmod -R 777 jenkins-cache/pnpm-store
问题 3:DNS 解析错误
编辑 .env,将 JENKINS_URL 改为你的真实地址:
bash
# 如果 Jenkins 在外部
JENKINS_URL=http://192.168.1.100:8080
# 或使用 Docker 网络 DNS
JENKINS_URL=http://jenkins:8080
问题 4:Docker 权限错误
bash
# 检查 docker.sock 挂载
docker compose exec jenkins-agent-docker ls -la /var/run/docker.sock
# 添加权限
docker compose exec jenkins-agent-docker chmod 666 /var/run/docker.sock
📊 完整检查清单
- 创建了
jenkins-agents目录及所有子目录 - 在 Jenkins 创建了 3 个 JNLP 节点
- 复制了所有 3 个 Secret 到
.env文件 - 创建了所有 3 个 Dockerfile
- 创建了
docker-compose.yml - 设置了正确的文件权限
- 运行
docker compose build构建镜像 - 运行
docker compose up -d启动所有服务 - 验证所有 3 个节点在 Jenkins 中显示为 "Online"
- 成功运行了测试 Pipeline
📞 快速参考
| 任务 | 命令 |
|---|---|
| 启动所有服务 | docker compose up -d |
| 停止所有服务 | docker compose down |
| 查看服务状态 | docker compose ps |
| 查看日志 | docker compose logs -f |
| 进入容器 | docker compose exec jenkins-agent-node bash |
| 重建镜像 | docker compose build |
| 查看 .env 内容 | cat .env |