pipeline { agent any environment { DOCKER_REGISTRY = 'your-registry' IMAGE_NAME = 'family-accounting' IMAGE_TAG = "${BUILD_NUMBER}" CONTAINER_NAME = 'family_accounting_backend' DEPLOY_DIR = '/opt/family-accounting' } stages { stage('Checkout') { steps { checkout scm } } stage('Build Docker Image') { steps { script { docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}", "-f backend/Dockerfile backend/") } } } stage('Push to Registry') { steps { script { docker.withRegistry("https://${DOCKER_REGISTRY}", 'docker-registry-credentials') { docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push() docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push('latest') } } } } stage('Deploy via SSH') { steps { sshagent(['deploy-server-key']) { sh """ ssh -o StrictHostKeyChecking=no deploy@your-server << 'EOF' cd ${DEPLOY_DIR} export TAG=${IMAGE_TAG} export REGISTRY=${DOCKER_REGISTRY} docker compose pull backend docker compose up -d backend docker image prune -f EOF """ } } } stage('Health Check') { steps { script { sleep(10) sh "curl -f http://your-server:3000/api/hello || exit 1" } } } stage('Cleanup') { steps { script { sh """ docker image prune -f --filter "until=24h" # 保留最近5个镜像 docker images ${DOCKER_REGISTRY}/${IMAGE_NAME} --format '{{.ID}}' | tail -n +6 | xargs -r docker rmi """ } } } } post { success { echo 'Deployment successful!' } failure { echo 'Deployment failed!' } } }