Mac/Linux 使用 Docker Jenkins 自动部署 Spring Boot 后端

本文以项目名称 joy-admin-backend 为例,搭建一套可重复使用的 Jenkins 自动部署流程,包含:

  • Docker 部署 Jenkins
  • Jenkins 通过 SSH 拉取阿里云 Codeup 代码
  • JDK 21、Maven 3.9.9 构建
  • Docker Compose 发布 Spring Boot 后端
  • 版本化 Docker 镜像
  • 健康检查
  • 发布失败自动回滚
  • 手动回滚历史版本

后端仓库:

git@codeup.aliyun.com:xxxxx/xxxxx.git

一、整体架构

Codeup
   ↓ SSH
Docker Jenkins
   ↓ docker compose build
joy-admin-backend:构建号-GitCommit
   ↓ docker compose up
后端容器
   ↓ 健康检查失败
自动恢复上一个 Docker 镜像

代码每次从 Codeup 拉取,环境配置保存在 Jenkins Credentials,不依赖本机已有项目。

二、环境要求

推荐配置:

Docker Desktop / Docker Engine
Docker Compose 2.20+
Jenkins LTS + JDK 21
Maven 3.9.9
至少 4 核 CPU
至少 6 GB 内存
至少 50 GB 可用磁盘

在宿主机检查环境:

1. 检查机器环境
执行:
uname -m
sw_vers
sysctl -n hw.memsize
df -h /

uname -m 输出 arm64:Apple Silicon 或 x86_64:Intel

2. 检查Docker
先启动Docker Desktop,然后执行:
docker version
docker compose version
docker info --format 'OS={{.OSType}}, Arch={{.Architecture}}, CPUs={{.NCPU}}, Memory={{.MemTotal}}'
docker run --rm hello-world

要求:
docker version同时显示Client和Server。
docker compose version正常输出。
hello-world运行成功。
Docker运行Linux容器。

3. 检查构建镜像
docker run --rm eclipse-temurin:21-jdk java -version

docker run --rm \
  maven:3.9.9-eclipse-temurin-21 \
  mvn -version

docker run --rm \
  node:16.20.2-bullseye \
  sh -c 'node -v && npm -v'

预期输出:
Java 21
Apache Maven 3.9.9
Node v16.20.2
npm 8.x

4. 检查Maven仓库挂载
先确认目录存在:
ls -ld /Users/mac/Documents/work/repo

测试容器读取:
docker run --rm \
  -v /Users/mac/Documents/work/repo:/maven-repo:ro \
  alpine:3.20 \
  sh -c 'test -d /maven-repo && ls -la /maven-repo | head'

如果出现Mounts denied,在Docker Desktop中打开:
Settings
→ Resources
→ File Sharing
加入:
/Users/mac/Documents/work
然后Apply并重启Docker Desktop。

5. 检查端口
lsof -nP -iTCP:8080 -sTCP:LISTEN
lsof -nP -iTCP:1024 -sTCP:LISTEN
lsof -nP -iTCP:9080 -sTCP:LISTEN
规划:
8080:Jenkins
1024:Joy Admin前端
9080:后端,仅在需要本机调试时映射
没有输出代表端口空闲。如果8080已占用,后面改用18080。

三、配置 Codeup SSH

1. 生成 Jenkins 专用密钥

在宿主机执行:

ssh-keygen \
  -t ed25519 \
  -C "jenkins-codeup" \
  -f ~/.ssh/joy-admin-jenkins-codeup

密钥位置:

~/.ssh/joy-admin-jenkins-codeup       私钥
~/.ssh/joy-admin-jenkins-codeup.pub   公钥

登陆Aliyun Codeup 的个人设置 》添加 SSH 公钥,将 .pub 公钥内容添加进去。

2. 验证 Codeup 主机指纹(机子能否链接到Codeup拉取代码)

Codeup 返回的是 RSA 主机密钥:

ssh-keyscan -T 10 -t rsa codeup.aliyun.com \
  > /tmp/codeup_known_hosts

ssh-keygen -lf /tmp/codeup_known_hosts

返回下面官方 SHA256 指纹就说明是正常的:

SHA256:yEGmgQNVrc3QAvDvoBrTxxxxxxx+AbWi9vSt/fE

验证访问codeup:

ssh -T \
  -i ~/.ssh/joy-admin-jenkins-codeup \
  -o IdentitiesOnly=yes \
  git@codeup.aliyun.com

出现 Welcome to Codeup 表示成功。

验证访问自己的仓库:

GIT_SSH_COMMAND='ssh -i ~/.ssh/joy-admin-jenkins-codeup -o IdentitiesOnly=yes' \
git ls-remote \
git@codeup.aliyun.com:xxxxxx/xxxxxx.git \
refs/heads/main

出现类似 9e7f396c0226cfa7cfebefeeebcef341752cb58 refs/heads/main 表示成功。

以上确认完成后,加入本机信任列表:

mkdir -p ~/.ssh
chmod 700 ~/.ssh
touch ~/.ssh/known_hosts
chmod 600 ~/.ssh/known_hosts

ssh-keygen -F codeup.aliyun.com >/dev/null \
  || cat /tmp/codeup_known_hosts >> ~/.ssh/known_hosts

四、创建 Jenkins Docker 环境

目录结构预览:

joy-admin-deploy/
├── .env
├── compose.jenkins.yml
└── jenkins/
    ├── Dockerfile
    └── known_hosts

创建上面的预览目录结构:

mkdir -p /Users/mac/Documents/work/joy-admin-deploy/jenkins
cd /Users/mac/Documents/work/joy-admin-deploy
cp /tmp/codeup_known_hosts jenkins/known_hosts
chmod 644 jenkins/known_hosts

1. 创建Jenkins镜像Jenkins Dockerfile

可以使用命令创建

nano jenkins/Dockerfile

写入:

FROM maven:3.9.9-eclipse-temurin-21 AS maven_tool
FROM node:16.20.2-bullseye AS node_tool

FROM jenkins/jenkins:lts-jdk21

USER root

RUN printf '%s\n' \
      'Acquire::Retries "5";' \
      'Acquire::http::Timeout "60";' \
      'Acquire::https::Timeout "60";' \
      > /etc/apt/apt.conf.d/80-network-retries \
    && sed -i \
       's|http://deb.debian.org|https://deb.debian.org|g' \
       /etc/apt/sources.list.d/debian.sources \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
       ca-certificates curl gnupg git openssh-client rsync \
    && install -m 0755 -d /etc/apt/keyrings \
    && curl --retry 5 --retry-delay 3 --retry-all-errors \
       -fsSL https://download.docker.com/linux/debian/gpg \
       -o /etc/apt/keyrings/docker.asc \
    && chmod a+r /etc/apt/keyrings/docker.asc \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
       https://download.docker.com/linux/debian \
       $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
       > /etc/apt/sources.list.d/docker.list \
    && apt-get update \
    && apt-get install -y --no-install-recommends \
       docker-ce-cli \
       docker-buildx-plugin \
       docker-compose-plugin \
    && rm -rf /var/lib/apt/lists/*

COPY --from=maven_tool /usr/share/maven /usr/share/maven
COPY --from=node_tool /usr/local /usr/local

ENV MAVEN_HOME=/usr/share/maven
ENV PATH=/usr/share/maven/bin:/usr/local/bin:${PATH}

RUN mkdir -p /root/.ssh \
    && chmod 700 /root/.ssh \
    && java -version \
    && mvn -version \
    && node -v \
    && npm -v \
    && docker --version \
    && docker buildx version \
    && docker compose version

RUN jenkins-plugin-cli --plugins \
    workflow-aggregator \
    pipeline-stage-view \
    git \
    ssh-credentials \
    ssh-agent \
    credentials-binding \
    docker-workflow \
    timestamper \
    ws-cleanup

USER root

docker-buildx-plugin不能省略,因为目前我的后端项目Dockerfile配置了
RUN --mount=type=cache,target=/root/.m2

该语法只能通过 BuildKit 执行。

2. Jenkins Compose

创建 compose.jenkins.yml

services:
  jenkins:
    build:
      context: ./jenkins
      dockerfile: Dockerfile
    image: joy-jenkins:lts-jdk21
    container_name: joy-jenkins
    user: root
    restart: unless-stopped
    ports:
      - "${JENKINS_BIND_ADDRESS}:${JENKINS_HTTP_PORT}:8080"
    environment:
      TZ: UTC
      JAVA_OPTS: >-
        -Duser.timezone=UTC
        -Djenkins.install.runSetupWizard=true
    volumes:
      - jenkins_home:/var/jenkins_home
      - jenkins_npm_cache:/root/.npm
      - "${HOST_MAVEN_REPO}:/maven-repo"
      - /var/run/docker.sock:/var/run/docker.sock
      - ./jenkins/known_hosts:/root/.ssh/known_hosts:ro

volumes:
  jenkins_home:
    name: joy_jenkins_home
  jenkins_npm_cache:
    name: joy_jenkins_npm_cache

创建 .env

JENKINS_BIND_ADDRESS=127.0.0.1
JENKINS_HTTP_PORT=8080
HOST_MAVEN_REPO=/Users/mac/Documents/work/repo

在其他机器构建时只需要修改 HOST_MAVEN_REPO

3. 构建并启动 Jenkins

cd /Users/mac/Documents/work/joy-admin-deploy

构建(如果compose.jenkins.yml或者Dockfile有改动,这个命令也可以重新构建)docker compose \
  --env-file .env \
  -f compose.jenkins.yml \
  build --pull

启动:
docker compose \
  --env-file .env \
  -f compose.jenkins.yml \
  up -d

检查状态:
docker compose \
  --env-file .env \
  -f compose.jenkins.yml \
  ps
  
docker logs --tail 100 joy-jenkins

获取初始化密码:

docker exec joy-jenkins \
  cat /var/jenkins_home/secrets/initialAdminPassword

打开:

http://127.0.0.1:8080

完成管理员创建和推荐插件安装。

验证工具:

docker exec joy-jenkins bash -lc '
java -version
mvn -version
node -v
npm -v
git --version
docker version
docker buildx version
docker compose version
'

验证Jenkins中的主机指纹:

docker exec joy-jenkins \
  ssh-keygen -lf /root/.ssh/known_hosts

输出必须包含类似:

SHA256:yEGmgQNVrc3QAvDvoBrTCF2s07Kwxxxxxx/fE

五、配置 Jenkins 凭据

http://127.0.0.1:8080先登陆Jenkins

1. Codeup 私钥凭据

进入:

Manage Jenkins
→ Credentials
→ System
→ Global credentials
→ Add Credentials

填写:

Kind:SSH Username with private key
Username:git
#可以命令行 pbcopy < ~/.ssh/joy-admin-jenkins-codeup 复制内容
Private Key:粘贴不带 .pub 后缀的私钥
ID:codeup-ssh
Description:Codeup只读拉取凭据

注意:

joy-admin-jenkins-codeup       私钥,可以填入Jenkins
joy-admin-jenkins-codeup.pub   公钥,不能填入Jenkins

如果错误粘贴公钥,会出现:

Load key: error in libcrypto
Permission denied (publickey)

2. 后端环境配置凭据

根据实际生成 .env
关键配置示例(以下内容是我的后端项目里面已有的内容,我就直接使用了,你们根据自己的配置来生成 .env内容):

# Docker image and host binding
JOY_ADMIN_IMAGE=joy-admin-backend
JOY_ADMIN_IMAGE_TAG=latest
JOY_ADMIN_BIND_ADDRESS=0.0.0.0
JOY_ADMIN_HOST_PORT=9080

# Docker宿主机公共工作根目录
HOST_MACHINE_ROOT=/Users/mac/Documents/work/joy-admin-backend-deploy
# Docker公共工作根目录
DOCKER_ROOT=/app/work/joy-admin-backend-deploy

# JVM. Adjust these percentages to the server capacity.
JAVA_TOOL_OPTIONS=-XX:MaxRAMPercentage=75.0 -XX:InitialRAMPercentage=25.0 -XX:+ExitOnOutOfMemoryError -Djava.io.tmpdir=${DOCKER_ROOT}/tmp

# Business calendar. JVM/database timestamps remain UTC; business dates use this zone.
BUSINESS_TIME_ZONE=Asia/Kolkata

# Remote PostgreSQL. Use a private IP or internal DNS name.
# For TLS, use sslmode=require or preferably verify-full with the required certificates.
DB_URL=jdbc:postgresql://192.168.1.114:5432/onevone?sslmode=disable&connectTimeout=10&socketTimeout=120&tcpKeepAlive=true
DB_USER=onevone
DB_PASSWORD=onevone
DB_POOL_INITIAL_SIZE=5
DB_POOL_MIN_IDLE=10
DB_POOL_MAX_ACTIVE=20

# Remote Redis. Never expose Redis directly to the public internet.
REDIS_HOST=host.docker.internal
REDIS_PORT=6379
REDIS_DATABASE=3
REDIS_USERNAME=
REDIS_PASSWORD=
REDIS_SSL=false
REDIS_TIMEOUT=10s

# Quartz uses the PostgreSQL connection above.
QUARTZ_INSTANCE_NAME=QuartzScheduler-admin-production
QUARTZ_CLUSTERED=true
QUARTZ_THREAD_COUNT=10
QUARTZ_DB_MAX_CONNECTIONS=10

# Application security. Generate a long random value for production.
TOKEN_SECRET=replace_with_a_long_random_secret
TOKEN_EXPIRE_MINUTES=43200

# Upstream service called by joy-admin.
UPSTREAM_SERVICE_URL=http://localhost:9080
UPSTREAM_SERVICE_SIGNATURE=replace_me

# Optional external integrations. Leave blank only when the feature is unused.
OSS_PREFIX_CDN=
OSS_PREFIX_OSS=
OSS_PREFIX_HTTP=
OSS_BUCKET_NAME=
OSS_ACCESS_KEY_ID=
OSS_ACCESS_KEY_SECRET=
OSS_ENDPOINT=
FEISHU_WEBHOOK_URL=

# Production switches
SWAGGER_ENABLED=false
DRUID_CONSOLE_ENABLED=false
DRUID_CONSOLE_USERNAME=
DRUID_CONSOLE_PASSWORD=

# 开放域名CORS跨域
CORS_ALLOWED_ORIGINS=https://xxx.com

# Docker宿主机持久化目录
# JOY_ADMIN_LOG_DIR:Docker宿主机路径
JOY_ADMIN_DATA_DIR=${HOST_MACHINE_ROOT}/data
JOY_ADMIN_LOG_DIR=${HOST_MACHINE_ROOT}/logs

# Docker持久化目录
# DOCKER_LOG_DIR:Docker路径
DOCKER_DATA_DIR=${DOCKER_ROOT}/data
DOCKER_LOG_DIR=${DOCKER_ROOT}/logs

# Docker容器内部日志路径
# APP_LOG_FILE:容器内部Linux路径
APP_LOG_FILE=${DOCKER_LOG_DIR}/joy-admin.log
APP_LOG_FILE_PATTERN=${DOCKER_LOG_DIR}/archive/joy-admin.%d{yyyy-MM-dd}.%i.log.gz
APP_LOG_LEVEL=info
APP_LOG_MAX_FILE_SIZE=100MB
APP_LOG_MAX_HISTORY=30
APP_LOG_TOTAL_SIZE_CAP=3GB

如果数据库或 Redis 运行在 Docker 宿主机,容器内地址使用:

host.docker.internal

创建持久化目录:

mkdir -p /Users/mac/Documents/work/joy-admin-backend-deploy/data

.env 上传到 Jenkins:

Kind:Secret file
File:选择准备好的.env
ID:joy-admin-backend-env
Description:Joy Admin后端运行配置

.env本地文件路径只在上传时使用,Jenkins 保存的是文件内容,流水线不会依赖上传路径。

六、创建后端 Pipeline

创建任务:

New Item
→ joy-admin-backend
→ Pipeline

Pipeline Script:

pipeline {
    agent any

    parameters {
        choice(
            name: 'ACTION',
            choices: ['DEPLOY', 'ROLLBACK'],
            description: '发布新版本或回滚旧版本'
        )
        string(
            name: 'GIT_BRANCH',
            defaultValue: 'main',
            description: '构建分支'
        )
        string(
            name: 'ROLLBACK_TAG',
            defaultValue: '',
            description: '回滚标签,例如15-a8c37f21'
        )
    }

    options {
        timestamps()
        timeout(time: 60, unit: 'MINUTES')
        disableConcurrentBuilds()
        skipDefaultCheckout(true)
        buildDiscarder(logRotator(numToKeepStr: '30'))
    }

    environment {
        IMAGE_NAME = 'joy-admin-backend'
        DOCKER_BUILDKIT = '1'
        TZ = 'UTC'
    }

    stages {
        stage('拉取代码') {
            steps {
                deleteDir()

                sshagent(credentials: ['codeup-ssh']) {
                    sh '''
                        set -eu
                        export GIT_SSH_COMMAND="ssh \
                          -o StrictHostKeyChecking=yes \
                          -o UserKnownHostsFile=/root/.ssh/known_hosts"

                        git clone \
                          --depth 1 \
                          --branch "$GIT_BRANCH" \
                          git@codeup.aliyun.com:xxxxx/xxxxx.git \
                          backend
                    '''
                }

                script {
                    env.GIT_SHORT = sh(
                        script: 'git -C backend rev-parse --short=8 HEAD',
                        returnStdout: true
                    ).trim()

                    env.NEW_TAG = "${env.BUILD_NUMBER}-${env.GIT_SHORT}"
                }
            }
        }

        stage('准备环境配置') {
            steps {
                withCredentials([
                    file(
                        credentialsId: 'joy-admin-backend-env',
                        variable: 'BACKEND_ENV_FILE'
                    )
                ]) {
                    sh '''
                        set -eu
                        install -m 600 "$BACKEND_ENV_FILE" backend/.env
                    '''
                }
            }
        }

        stage('执行发布或回滚') {
            steps {
                dir('backend') {
                    script {
                        if (params.ACTION == 'ROLLBACK') {
                            if (!params.ROLLBACK_TAG.trim()) {
                                error('回滚必须填写ROLLBACK_TAG')
                            }

                            env.TARGET_TAG = params.ROLLBACK_TAG.trim()

                            sh '''
                                set -eu
                                export JOY_ADMIN_IMAGE="$IMAGE_NAME"
                                export JOY_ADMIN_IMAGE_TAG="$TARGET_TAG"

                                docker image inspect \
                                  "$IMAGE_NAME:$TARGET_TAG" >/dev/null

                                docker compose up \
                                  -d --no-build --force-recreate \
                                  --wait --wait-timeout 300 \
                                  joy-admin

                                CONTAINER_ID="$(docker compose ps -q joy-admin)"

                                docker exec "$CONTAINER_ID" \
                                  curl --fail --silent \
                                  http://127.0.0.1:9080/ >/dev/null

                                echo "回滚成功:$IMAGE_NAME:$TARGET_TAG"
                            '''
                        } else {
                            env.TARGET_TAG = env.NEW_TAG

                            sh '''
                                set -u
                                export JOY_ADMIN_IMAGE="$IMAGE_NAME"
                                export JOY_ADMIN_IMAGE_TAG="$TARGET_TAG"

                                CURRENT_ID="$(
                                  docker compose ps -q joy-admin 2>/dev/null || true
                                )"

                                PREVIOUS_IMAGE=""
                                if [ -n "$CURRENT_ID" ]; then
                                    PREVIOUS_IMAGE="$(
                                      docker inspect \
                                        --format '{{.Config.Image}}' \
                                        "$CURRENT_ID"
                                    )"
                                fi

                                docker compose config >/dev/null || exit 1
                                docker compose build --pull joy-admin || exit 1
                                docker image inspect \
                                  "$IMAGE_NAME:$TARGET_TAG" >/dev/null || exit 1

                                DEPLOY_OK=false

                                if docker compose up \
                                  -d --no-build \
                                  --wait --wait-timeout 300 \
                                  joy-admin
                                then
                                    CONTAINER_ID="$(
                                      docker compose ps -q joy-admin
                                    )"

                                    if docker exec "$CONTAINER_ID" \
                                      curl --fail --silent \
                                      http://127.0.0.1:9080/ >/dev/null
                                    then
                                        DEPLOY_OK=true
                                    fi
                                fi

                                if [ "$DEPLOY_OK" = "true" ]; then
                                    echo "发布成功:$IMAGE_NAME:$TARGET_TAG"
                                    docker inspect \
                                      --format='镜像={{.Config.Image}} 健康={{.State.Health.Status}}' \
                                      "$CONTAINER_ID"
                                    exit 0
                                fi

                                echo "新版本启动失败"
                                docker compose logs --tail=200 joy-admin || true

                                if [ -z "$PREVIOUS_IMAGE" ]; then
                                    echo "首次发布,没有旧版本可回滚"
                                    exit 1
                                fi

                                if ! docker image inspect \
                                  "$PREVIOUS_IMAGE" >/dev/null 2>&1
                                then
                                    echo "旧镜像不存在:$PREVIOUS_IMAGE"
                                    exit 1
                                fi

                                PREVIOUS_TAG="${PREVIOUS_IMAGE##*:}"
                                export JOY_ADMIN_IMAGE_TAG="$PREVIOUS_TAG"

                                if docker compose up \
                                  -d --no-build --force-recreate \
                                  --wait --wait-timeout 300 \
                                  joy-admin
                                then
                                    echo "已自动回滚:$PREVIOUS_IMAGE"
                                else
                                    echo "自动回滚失败,需要人工处理"
                                fi

                                exit 1
                            '''
                        }
                    }
                }
            }
        }
    }

    post {
        always {
            sh 'rm -f backend/.env 2>/dev/null || true'
            deleteDir()
        }
    }
}

七、执行第一次发布

选择:

Build with Parameters

填写:

ACTION=DEPLOY
GIT_BRANCH=main
ROLLBACK_TAG=留空

每次发布生成唯一镜像:

joy-admin-backend:构建号-Git短Commit

例如:

joy-admin-backend:7-9c0226cf
joy-admin-backend:8-a321bc42

八、验证发布

docker ps --filter name=joy-admin-backend
docker images joy-admin-backend
curl http://127.0.0.1:9080/

查看当前运行镜像:

docker inspect \
  --format '{{.Config.Image}}' \
  "$(docker ps -q --filter name=joy-admin-backend)"

查看日志:

docker logs \
  --tail 200 \
  "$(docker ps -q --filter name=joy-admin-backend)"

九、执行回滚

查看历史镜像:

docker images joy-admin-backend

比如返回所有镜像:
joy-admin-backend   15-a8c37f21
joy-admin-backend   16-d529bf10

登陆Jenkins,再次选择Build with Parameters,参数界面填入:

ACTION=ROLLBACK
GIT_BRANCH=main
ROLLBACK_TAG=需要恢复的镜像标签,如 15-a8c37f21

回滚使用已有镜像,不重新编译。

发布新版本健康检查失败时,流水线会自动恢复发布前正在运行的镜像。

十、常见问题

1. ssh-keyscan提示不是公钥文件

错误:

(stdin) is not a public key file

原因是 Codeup 没有提供 ED25519 主机密钥,只提供 RSA:

ssh-keyscan -T 10 -t rsa codeup.aliyun.com

2. Jenkins拉取代码报libcrypto错误

错误:

Load key: error in libcrypto
Permission denied (publickey)

检查是否错误上传了 .pub 公钥。Jenkins需要不带.pub后缀的私钥。

3. Debian下载返回502

错误:

502 Bad Gateway
Unable to fetch some archives

Jenkins Dockerfile中配置APT重试和HTTPS源;重新执行构建即可。

4. BuildKit不可用

错误:

Docker Compose requires buildx plugin
the --mount option requires BuildKit

Jenkins镜像必须安装:

docker-buildx-plugin

验证:

docker exec joy-jenkins docker buildx version

5. 容器无法连接宿主机数据库或Redis

容器中的127.0.0.1表示容器自己。Mac和Docker Desktop使用:

host.docker.internal

Linux通过现有Compose配置:

extra_hosts:
  - "host.docker.internal:host-gateway"

6. 测试失败导致构建失败

目前我的后端Dockerfile使用:

-Dmaven.test.skip=true

生产镜像构建不会运行测试。测试应作为独立质量阶段,修复后再决定是否阻断发布。

十一、迁移到另一台机器

新机器需要:

  1. 安装Docker和Docker Compose。
  2. 创建同样的joy-admin-deploy目录。
  3. 构建并启动Jenkins。
  4. 配置同样的known_hosts
  5. 配置凭据codeup-ssh
  6. 上传新机器对应环境的.env,凭据ID仍为joy-admin-backend-env
  7. 创建同样的Pipeline任务。
  8. 创建JOY_ADMIN_DATA_DIR目录。
  9. 执行ACTION=DEPLOY

流水线不依赖本地项目目录,所有代码均从Codeup获取。

十二、安全和维护建议

  • .env禁止提交Git。
  • Jenkins不要直接暴露公网。
  • Jenkins挂载Docker Socket后拥有宿主机Docker管理权限。
  • 定期备份joy_jenkins_home卷。
  • 至少保留最近5至10个后端镜像。
  • 不要随意执行docker system prune -a(用于彻底清理 Docker 系统中未使用的资源,包括未被任何容器引用的镜像、停止的容器)。
  • Docker镜像回滚不会回滚数据库。
  • SQL变更应保持新旧应用版本兼容。
  • 跨机器保留历史镜像时,需要增加Docker Registry。

查看Docker磁盘占用:

docker system df

官方参考:

更多推荐