前言
| 构建工具 | 优点 | 缺点 | 参考构建链接 |
|---|---|---|---|
| buildkit | 并发构建、缓存复用高效,支持 secrets 安全传递,增量构建 | 配置较复杂,需要Docker 18.09+,部分旧Dockerfile指令不支持 | buildkit |
| kaniko | 专为K8s设计,无需Docker守护进程,在容器内安全执行构建 | 构建速度较慢,本地开发体验差,缓存管理较复杂 | kaniko |
| pod man | daemonless架构,rootless运行,兼容Docker CLI,集成了Buildah | 在macOS/Windows需要虚拟机,网络配置较复杂,企业生态不及Docker | podman |
| img | 基于BuildKit但更简单,并行构建高效,缓存利用好 | 项目活跃度下降,维护更新少,社区支持有限 | img |
| buildah | 无需守护进程,rootless构建,精细控制镜像层,可生成OCI镜像 | CLI与Docker不完全兼容,需要学习新命令,生态系统较小 | buildah |
| docker | 生态最成熟,CLI用户体验好,支持多阶段构建,集成镜像管理 | 需要守护进程,有root权限安全风险,构建缓存层多导致镜像较大 | docker |
| nerdctl | 兼容Docker CLI,直接使用containerd,支持rootless,集成了BuildKit | 相对较新,某些高级功能可能缺失,文档较少 | nerdctl |
选择建议
- 本地开发:Docker/Podman(体验好)
- CI/CD流水线:Kaniko/BuildKit(安全性好)
- Kubernetes环境:Kaniko/nerdctl(云原生集成)
- 精细控制:Buildah(无守护进程需求)
- 性能优先:BuildKit/img(缓存和并行优化)
PS:
- k8s+containerd可以优先考虑buildkit、podman、kaniko
- k8s+docker可以优先考虑原生docker构建功能
1、BuildKit
1.1 Jenkinsfile
1.1.1 忽略证书语法
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、buildkit、kubectl三个容器模板,buildkit需要root特权模式运行
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'buildkit', image: 'harbor.test.com/devops/buildkit:v0.23.2', command: 'cat', ttyEnabled: true, privileged: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('buildkit构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('buildkit') {
echo "2.构建镜像"
sh """
#创建harbor认证文件
mkdir -p /root/.docker
cat > /root/.docker/config.json << EOF
{
"auths": {
"${registryUrl}": {
"auth": "\$(echo -n "${HARBOR_USER}:${HARBOR_PASSWORD}" | base64)"
}
}
}
EOF
#需创建配置文件,否则无法进行证书忽略或校验
mkdir -p /etc/buildkit
cat > /etc/buildkit/buildkitd.toml << EOF
[registry."${registryUrl}"]
insecure = true
mirrors = ["${registryUrl}"]
EOF
#启动buildkitd守护进程
buildkitd &
sleep 5
buildctl build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=.\
--export-cache type=inline \
--import-cache type=registry,ref=${image}:buildcache \
--output type=image,name=${image},push=true \
--registry-auth-tlscontext host=${registryUrl},insecure=true
"""
}
}
}
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
1.1.2 证书校验语法
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'buildkit', image: 'harbor.test.com/devops/buildkit:v0.23.2', command: 'cat', ttyEnabled: true, privileged: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn'),
//挂载harbor证书目录
hostPathVolume(mountPath: '/tmp/certs.d', hostPath: '/data/nfs-data/certs.d')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('buildkit构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('buildkit') {
echo "2.构建镜像"
sh """
#创建harbor认证文件
mkdir -p /root/.docker
cat > /root/.docker/config.json << EOF
{
"auths": {
"${registryUrl}": {
"auth": "\$(echo -n "${HARBOR_USER}:${HARBOR_PASSWORD}" | base64)"
}
}
}
EOF
#需创建配置文件,否则无法进行证书忽略或校验
mkdir -p /etc/buildkit
cat > /etc/buildkit/buildkitd.toml << EOF
[registry."${registryUrl}"]
insecure = true
mirrors = ["${registryUrl}"]
EOF
#启动buildkitd守护进程
buildkitd &
sleep 5
buildctl build \
--frontend dockerfile.v0 \
--local context=. \
--local dockerfile=.\
--export-cache type=inline \
--import-cache type=registry,ref=${image}:buildcache \
--output type=image,name=${image},push=true \
--registry-auth-tlscontext host=${registryUrl},insecure=false,ca=/tmp/certs.d/ca.pem,cert=/tmp/certs.d/cert.pem,key=/tmp/certs.d/key.pem
"""
}
}
}
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
1.2 Dockerfile
FROM harbor.test.com/jdk/openjdk:8-jre-alpine
#FROM openjdk:8-jre-alpine
WORKDIR /app
COPY target/hello-world-app-0.0.1-SNAPSHOT.jar /app/app.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
1.3 流水线运行情况

1.4 访问demo

2、Kaniko
2.1 Jenkinsfile
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'kaniko', image: 'swr.cn-north-4.myhuaweicloud.com/ddn-k8s/gcr.io/kaniko-project/executor:v1.9.1-debug', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "172.16.10.131"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('kaniko构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('kaniko') {
echo "2.构建镜像"
sh """
# 创建 .docker 目录
mkdir -p /kaniko/.docker
# 生成 base64 编码的认证信息,'echo -n' 非常重要,它不会在末尾添加换行符
AUTH=\$(echo -n "${HARBOR_USER}:${HARBOR_PASSWORD}" | base64 -w 0)
# 创建 Kaniko 需要的 config.json 文件
cat <<EOF > /kaniko/.docker/config.json
{
"auths": {
"${registryUrl}": {
"auth": "\${AUTH}"
}
}
}
EOF
#skip-tls-verify参数可以忽略自签证书的报错问题,${WORKSPACE}确认目前jenkins-agent的工作目录,否则是kaniko的默认工作目录/workspace
/kaniko/executor \
--context=${WORKSPACE} \
--dockerfile=Dockerfile \
--destination=${image} \
--cache=true \
--cache-repo=${registryUrl}/cache \
--skip-tls-verify
"""
}
}
}
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
2.2 Dockerfile
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openjdk:8-jre-alpine
WORKDIR /app
COPY target/hello-world-app-0.0.1-SNAPSHOT.jar /app/app.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
2.3 流水线运行情况
耗时:6分16秒

2.4 访问demo

3、pod man
3.1 Jenkinsfile
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'podman', image: 'quay.io/podman/stable', command: 'cat', ttyEnabled: true, privileged: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn'),
//挂载harbor证书目录
hostPathVolume(mountPath: '/tmp/certs.d', hostPath: '/data/nfs-data/certs.d')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('buildah构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('podman') {
echo "2.构建镜像"
sh """
cp /tmp/certs.d/ca.pem /etc/pki/ca-trust/source/anchors/ca.crt
update-ca-trust
#--tls-verify=false绕过harbor的ssl证书检查
podman login --username ${HARBOR_USER} --password ${HARBOR_PASSWORD} ${registryUrl}
#使用 VFS 存储驱动,避免需要 FUSE
podman build -t ${image} .
podman push ${image}
"""
}
}
}
//第三阶段
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
3.2 Dockerfile
FROM harbor.test.com/jdk/openjdk:8-jre-alpine
#FROM openjdk:8-jre-alpine
WORKDIR /app
COPY target/hello-world-app-0.0.1-SNAPSHOT.jar /app/app.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
3.3 流水线运行情况

3.4 访问demo

4、img
4.1 Jenkinsfile
def label = "jenkins-agent"
podTemplate(label: label,
containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'img', image: 'harbor.test.com/devops/img', command: 'cat', ttyEnabled: true, runAsUser: '0', runAsGroup: '0', privileged: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn'),
hostPathVolume(mountPath: '/tmp/certs.d', hostPath: '/data/nfs-data/certs.d')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com:443"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('Img构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('img') {
echo "2.构建镜像"
sh """
#强制信任harbor证书
cat >> /etc/ssl/certs/ca-certificates.crt << EOF
\$(cat /tmp/certs.d/ca.pem)
EOF
#img创建本地密码验证,额外登录可能无法跳过ssl证书检查
mkdir -p \$HOME/.docker
cat > \$HOME/.docker/config.json << EOF
{
"auths": {
"${registryUrl}": {
"auth": "\$(echo -n ${HARBOR_USER}:${HARBOR_PASSWORD} | base64)"
}
}
}
EOF
#构建和推送镜像
img build -t ${image} .
img push ${image}
"""
}
}
}
//第三阶段
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
4.2 Dockerfile
FROM harbor.test.com/jdk/openjdk:8-jre-alpine
#FROM openjdk:8-jre-alpine
WORKDIR /app
COPY target/hello-world-app-0.0.1-SNAPSHOT.jar /app/app.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
4.3 流水线运行情况

4.4 访问demo

5、Buildah
5.1 Jenkinsfile
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'buildah', image: 'quay.io/buildah/stable', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "172.16.10.131"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('buildah构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('buildah') {
echo "2.构建镜像"
sh """
#--tls-verify=false绕过harbor的ssl证书检查
buildah login --tls-verify=false --username ${HARBOR_USER} --password ${HARBOR_PASSWORD} ${registryUrl}
#使用 VFS 存储驱动,避免需要 FUSE
buildah bud --storage-driver vfs -t ${image} .
buildah --storage-driver vfs push --tls-verify=false ${image}
"""
}
}
}
//第三阶段
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
5.2 Dockerfile
5.3 流水线运行情况
耗时:

5.4 访问demo

6、Docker
6.1 DinD
6.1.1 Jenkinsfile
因本服务器k8s集群基于containerd运行时,没有docker-cli环境,理论上挂载/var/run/docker.sock套接字文件,也可能需要挂载docker的运行目录,即可实现docker in docker模式
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'docker', image: 'harbor.test.com/devops/docker:dind', command: 'cat', ttyEnabled: true);
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn'),
//挂载本机docker套接字
hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock')
])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('tcp docker推送镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('docker') {
echo "2.构建镜像"
sh """
#创建harbor认证文件
#export DOCKER_HOST=tcp://172.16.10.131:2375
#sleep 100
mkdir -p /root/.docker
cat > /root/.docker/config.json << EOF
{
"auths": {
"${registryUrl}": {
"auth": "\$(echo -n "${HARBOR_USER}:${HARBOR_PASSWORD}" | base64)"
}
}
}
EOF
#docker ps
docker login ${registryUrl}
docker build -t ${image} .
docker push ${image}
"""
}
}
}
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
6.2 外部Docker
6.2.1 Jenkinsfile
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'docker', image: 'harbor.test.com/devops/docker:20.10.12', command: 'cat', ttyEnabled: true,envVars: [
envVar(key: 'DOCKER_HOST', value: 'tcp://172.16.10.131:2375')
]
),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('tcp docker推送镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('docker') {
echo "2.构建镜像"
sh """
#创建harbor认证文件
#export DOCKER_HOST=tcp://172.16.10.131:2375
#sleep 100
mkdir -p /root/.docker
cat > /root/.docker/config.json << EOF
{
"auths": {
"${registryUrl}": {
"auth": "\$(echo -n "${HARBOR_USER}:${HARBOR_PASSWORD}" | base64)"
}
}
}
EOF
#docker ps
docker login ${registryUrl}
docker build -t ${image} .
docker push ${image}
"""
}
}
}
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
6.2.2 Dockerfile
FROM harbor.test.com/jdk/openjdk:8-jre-alpine
#FROM openjdk:8-jre-alpine
WORKDIR /app
COPY target/hello-world-app-0.0.1-SNAPSHOT.jar /app/app.jar
# 启动命令
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
6.2.3 流水线运行情况

6.2.4 访问demo

7、nerdctl
7.1 Jenkinsfile
nerdctl是containerd的额外前端组件,完善ctr命令的不足,但是需要运行nerdctl容器需要额外挂载本机的containerd运行目录,若数据目录过大,可能较消耗资源,不推荐此种方式,不做演示。
def label = "jenkins-agent"
podTemplate(label: label, containers: [
//设置mvn、kaniko、kubectl三个容器模板
containerTemplate(name: 'maven', image: 'harbor.test.com/devops/maven:3.8.5-openjdk-11', command: 'cat', ttyEnabled: true),
containerTemplate(name: 'nerdctl', image: 'harbor.test.com/devops/nerdctl', command: 'cat', ttyEnabled: true, privileged: true),
containerTemplate(name: 'kubectl', image: 'harbor.test.com/devops/kubectl', command: 'cat', ttyEnabled: true)],
//sa权限
serviceAccount: 'jenkins-master',
volumes: [
hostPathVolume(mountPath: '/root/.m2', hostPath: '/data/nfs-data/mvn'),
hostPathVolume(mountPath: '/var/run/containerd/containerd.sock', hostPath: '/run/containerd/containerd.sock'),
//额外挂载containerd的运行目录,耗资源,不推荐
hostPathVolume(mountPath: '/data/containerd', hostPath: '/data/containerd')
])
//挂载harbor证书目录
// hostPathVolume(mountPath: '/tmp/certs.d', hostPath: '/data/nfs-data/certs.d')])
{
node(label) {
// 拉取git代码
def myRepo = checkout scm
// 获取 git commit id 作为镜像标签
def imageTag = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
// 仓库地址
def registryUrl = "harbor.test.com"
def imageEndpoint = "java-demo/demo"
// 镜像标签
def image = "${registryUrl}/${imageEndpoint}:${imageTag}"
//第一阶段
stage('mvn构建jar包') {
container('maven') {
echo "1.mvn构建"
sh """
export JAVA_HOME=/usr/local/openjdk-11
mvn -B -q clean install -DskipTests
"""
}
}
//第二阶段
stage('nerdctl构建镜像') {
//引入harbor仓库认证
withCredentials([usernamePassword(
// 凭据id以实际为准
credentialsId: 'harbor_auth',
passwordVariable: 'HARBOR_PASSWORD',
usernameVariable: 'HARBOR_USER')]) {
container('nerdctl') {
echo "2.构建镜像"
sh """
#cp /tmp/certs.d/ca.pem /etc/pki/ca-trust/source/anchors/ca.crt
#update-ca-trust
#--tls-verify=false绕过harbor的ssl证书检查
buildkitd &
sleep 5
mkdir -p /data/containerd/root
ls /data/containerd/
#ls
#nerdctl --help
nerdctl login --insecure-registry --username ${HARBOR_USER} --password ${HARBOR_PASSWORD} ${registryUrl}
#使用 VFS 存储驱动,避免需要 FUSE
nerdctl build -t ${image} .
nerdctl push --insecure-registry ${image}
"""
}
}
}
//第三阶段
stage('kubectl一键部署') {
withCredentials([file(
credentialsId: 'kubeconfig',
variable: 'KUBECONFIG')]) {
container('kubectl') {
echo "3.kubectl更新镜像"
sh """
kubectl --kubeconfig=$KUBECONFIG set image deployment/java-demo java-demo=${image} -n devops
sleep 10
kubectl --kubeconfig=$KUBECONFIG get pod -n devops |grep java-demo|grep Running
"""
}
}
}
}
}
评论区