在容器代理上运行流水线

Beginner

简介

许多 Jenkins 安装环境都在基于容器的环境中运行构建。在本 LabEx 镜像中,Jenkins 本身运行在一个 Docker 容器内。由于控制器(Controller)不会向构建任务暴露宿主机的 Docker 套接字,因此本实验重点介绍流水线如何在不拉取外部镜像的情况下,从容器化的执行上下文中收集实际证据。

在本实验中,你将检查本地的 Jenkins 镜像,创建一个用于检查容器证据的流水线任务,运行构建,并验证控制台输出。

检查可用的容器镜像

在此步骤中,你将检查虚拟机宿主机上的本地 Docker 镜像。Jenkins 控制器容器是从本地的 jenkins/jenkins:latest 镜像启动的,流水线构建将在这个基于容器的 Jenkins 环境中运行。

列出可用镜像:

docker images --format '{{.Repository}}:{{.Tag}}' | sort

检查正在运行的 Jenkins 容器:

docker ps --filter name=jenkins --format 'container={{.Names}} image={{.Image}} status={{.Status}}'

你应该能看到 jenkins/jenkins:latest 以及一个名为 jenkins 的运行中容器。

编写容器感知流水线

在此步骤中,你将编写一个用于检查其执行环境的流水线脚本。文件 /.dockerenv 通常存在于 Docker 容器内部。该流水线还将打印主机名、工作空间以及操作系统详细信息。

创建流水线脚本:

cat > /home/labex/project/container-agent-pipeline.groovy <<'GROOVY'
node {
    stage('Container Context') {
        echo 'Checking container-backed Jenkins execution context'
        sh '''
set -e
echo "Container marker:"
test -f /.dockerenv && echo "INSIDE_CONTAINER=true"
echo "Container hostname: $(hostname)"
echo "Workspace: $WORKSPACE"
grep '^PRETTY_NAME=' /etc/os-release
'''
    }
}
GROOVY

打印脚本以便查看阶段(stage)和 shell 步骤:

nl -ba /home/labex/project/container-agent-pipeline.groovy

创建流水线任务

在此步骤中,你将创建一个名为 container-agent-demo 的 Jenkins 流水线任务。Python 将对 Groovy 脚本进行 XML 转义并写入流水线任务配置。

生成 Jenkins 任务配置:

python3 - <<'PY'
from html import escape
from pathlib import Path

script = Path("/home/labex/project/container-agent-pipeline.groovy").read_text()
config = f"""<?xml version='1.1' encoding='UTF-8'?>
<flow-definition plugin="workflow-job">
  <actions/>
  <description>Capture container execution evidence from a Pipeline build.</description>
  <keepDependencies>false</keepDependencies>
  <properties/>
  <definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps">
    <script>{escape(script)}</script>
    <sandbox>true</sandbox>
  </definition>
  <triggers/>
  <disabled>false</disabled>
</flow-definition>
"""
Path("/home/labex/project/container-agent-demo-config.xml").write_text(config)
PY

将任务复制到 Jenkins 并重新加载:

docker exec jenkins mkdir -p /var/jenkins_home/jobs/container-agent-demo
docker cp /home/labex/project/container-agent-demo-config.xml jenkins:/var/jenkins_home/jobs/container-agent-demo/config.xml
CRUMB=$(curl -fsS -c /tmp/jenkins-container-reload.cookies 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -fsS -b /tmp/jenkins-container-reload.cookies -H "$CRUMB" -X POST http://localhost:8080/reload >/dev/null || true
sleep 5

确认 Jenkins 可以加载该任务:

curl -fsS http://localhost:8080/job/container-agent-demo/api/json | grep -o '"name":"container-agent-demo"'

运行容器感知流水线

在此步骤中,你将运行流水线并等待 Jenkins 完成构建 #1

触发构建:

CRUMB=$(curl -fsS -c /tmp/jenkins-container-build.cookies 'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)')
curl -fsS -b /tmp/jenkins-container-build.cookies -H "$CRUMB" -X POST http://localhost:8080/job/container-agent-demo/build

等待构建完成:

until curl -fsS http://localhost:8080/job/container-agent-demo/1/api/json >/tmp/container-agent-build-1.json 2>/dev/null && grep -q '"building":false' /tmp/container-agent-build-1.json; do
  echo "Waiting for container-aware pipeline build #1..."
  sleep 3
done

确认结果:

curl -fsS http://localhost:8080/job/container-agent-demo/1/api/json | grep -o '"result":"SUCCESS"'

检查容器执行证据

在此步骤中,你将检查控制台输出。重要的证据包括 INSIDE_CONTAINER=true、容器主机名以及 Jenkins 工作空间路径。

打印关键的控制台行:

curl -fsS http://localhost:8080/job/container-agent-demo/1/consoleText | grep -E 'INSIDE_CONTAINER|Container hostname|Workspace|PRETTY_NAME|Finished: SUCCESS'

从桌面界面打开 Firefox 并访问 http://localhost:8080/job/container-agent-demo/1/console。控制台页面应显示容器标记和工作空间信息。

Jenkins 容器感知流水线控制台输出

总结

你检查了本地的 Jenkins 容器镜像,创建了一个容器感知流水线任务,运行了它,并从 Jenkins 控制台输出中验证了容器执行证据。你还了解了为什么此 LabEx 环境能够在不依赖外部镜像拉取或挂载 Docker 套接字的情况下,验证基于容器的执行过程。