Jenkins 多语言 Agent 完整部署教程

📋 前置条件

  • 已安装 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 管理界面创建节点

  1. 登录 Jenkins → 管理 Jenkins节点管理
  2. 点击 新建节点 3 次,创建:
    • node-agent
    • java-agent-17
    • java-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 管理界面

  1. 登录 Jenkins → 管理 Jenkins节点管理
  2. 检查所有 3 个节点是否显示为 "Online"
  3. 如果显示 "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
相关推荐
草莓熊Lotso33 分钟前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
历程里程碑36 分钟前
Linux22 文件系统
linux·运维·c语言·开发语言·数据结构·c++·算法
七夜zippoe9 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy64810 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满10 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠10 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Harvey90311 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技12 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀12 小时前
Linux环境变量
linux·运维·服务器
zzzsde12 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器