📋 前置条件
- 已安装 Docker 和 Docker Compose
- Linux/Mac 环境(或 WSL2)
- 有一个运行中的 Jenkins 实例
- SSH 密钥对用于部署(可选但建议)
🏗️ 第一步:创建项目目录结构
# 进入你的工作目录,比如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/workmkdir-p jenkins-agents/agent-java-17/workmkdir-p jenkins-agents/agent-java-21/work# 查看目录结构tree -L2# 或者用 ls -lals-la目录结构应该如下:
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 管理界面创建节点中获取,当前步骤先用占位符
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
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"] EOF3.1.2 创建 Node.js Agent start-agent.sh
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" EOF3.2.1 创建 Java 17 Agent Dockerfile
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"] EOF3.2.2 创建 Java 17 start-agent.sh
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" EOF3.3.1 创建 Java 21 Agent Dockerfile
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"] EOF3.3.2 创建 Java 21 start-agent.sh
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 已创建:
ls-la agent-*/Dockerfile📦 第四步:创建 docker-compose.yml
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🔐 第五步:设置文件权限
# 切换到 jenkins-agents 目录cd/home/jenkins-agents# 设置所有者(根据你的用户调整)sudochown-R1000:1000 jenkins-homesudochown-R1000:1000 jenkins-cache# 设置权限sudochmod-R755jenkins-homesudochmod-R755jenkins-cache# 创建必要的子目录权限sudochmod-R777jenkins-cache/pnpm-storesudochmod-R777jenkins-cache/m2sudochmod-R777jenkins-cache/docker-cache# 验证权限ls-la|grepjenkins如果你用的是当前用户(非 root):
# 如果 jenkins-agents 在你的用户目录下chmod-R755jenkins-homechmod-R755jenkins-cachechmod-R777jenkins-cache/pnpm-storechmod-R777jenkins-cache/m2chmod-R777jenkins-cache/docker-cache🚀 第六步:启动所有服务
# 进入项目目录cd/home/jenkins-agents# 构建所有镜像(第一次运行)docker compose build# 启动所有服务docker compose up -d# 查看启动日志docker compose logs -f# 检查所有容器状态docker composeps预期输出:
NAME STATUS jenkins Up2minutes jenkins-agent-node Up1minute jenkins-agent-java-17 Up1minute jenkins-agent-java-21 Up1minute🔐 第七步:生成 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,如下:
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”,查看节点日志
方式二:通过命令行查看日志
# 查看 Node agent 日志docker compose logs jenkins-agent-node# 查看 Java 17 agent 日志docker compose logs jenkins-agent-java-17# 实时查看所有日志docker compose logs -f成功连接的日志示例:
jenkins-agent-node|2024-12-1010:15:30... Successfully connected🧪 第九步:测试 Pipeline
在 Jenkins 创建一个测试 Pipeline,使用以下 Jenkinsfile:
pipeline{agent{label'node'// 使用 node-agent}stages{stage('Test Node'){steps{sh'node --version'sh'pnpm --version'sh'git --version'}}}}测试 Java 17
pipeline{agent{label'java-agent-17'}stages{stage('Test Java 17'){steps{sh'java -version'sh'mvn --version'sh'gradle --version'}}}}🛠️ 常用命令
# 启动服务docker compose up -d# 停止服务docker compose down# 重启特定服务docker compose restart jenkins-agent-node# 查看实时日志docker compose logs -f jenkins-agent-node# 进入容器调试docker composeexecjenkins-agent-nodebash# 重新构建镜像docker compose build --no-cache# 查看容器资源使用docker stats# 删除所有数据(谨慎!)docker compose down -v🔧 故障排查
问题 1:节点显示 “Offline”
# 查看连接日志docker compose logs jenkins-agent-node# 检查 .env 中的 Secret 是否正确cat.env|grepJENKINS_SECRET# 重启 agentdocker compose restart jenkins-agent-node问题 2:构建时权限错误
# 检查缓存目录权限ls-la jenkins-cache/# 重新设置权限chmod-R777jenkins-cache/m2chmod-R777jenkins-cache/pnpm-store问题 3:DNS 解析错误
编辑.env,将 JENKINS_URL 改为你的真实地址:
# 如果 Jenkins 在外部JENKINS_URL=http://192.168.1.100:8080# 或使用 Docker 网络 DNSJENKINS_URL=http://jenkins:8080问题 4:Docker 权限错误
# 检查 docker.sock 挂载docker composeexecjenkins-agent-dockerls-la /var/run/docker.sock# 添加权限docker composeexecjenkins-agent-dockerchmod666/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 |