diff --git a/.dockerignore b/.dockerignore index 8311412..67721eb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,6 +2,13 @@ .git/ .gitignore .idea/ +.agents/ +.vscode/ +docs/ +output/ +tools/ +src/test/ +*.xlsx *.iml *.log README.md diff --git a/Dockerfile b/Dockerfile index 3d5a91e..a7a4d02 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,24 @@ # Build stage -FROM maven:3.9.8-eclipse-temurin-17 AS builder +ARG MAVEN_IMAGE=maven:3.9.16-eclipse-temurin-17-alpine +FROM ${MAVEN_IMAGE} AS builder WORKDIR /app COPY .mvn/settings.xml /root/.m2/settings.xml COPY pom.xml . +RUN mvn -B -ntp -Dmaven.test.skip=true dependency:go-offline COPY src ./src -RUN mvn -B -ntp -DskipTests clean package +RUN mvn -B -ntp -Dmaven.test.skip=true clean package # Runtime stage -FROM eclipse-temurin:17-jre +ARG RUNTIME_IMAGE=eclipse-temurin:17-jre-alpine +FROM ${RUNTIME_IMAGE} WORKDIR /app COPY --from=builder /app/target/agent-foundation-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8880 -# Runtime env defaults (override in Jenkins/Deploy env) -ENV JAVA_OPTS="" +# JAVA_TOOL_OPTIONS is read directly by the JVM, so no shell entrypoint is needed. +ENV JAVA_TOOL_OPTIONS="" ENV SPRING_PROFILES_ACTIVE=prod ENV SERVER_PORT=8880 -ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /app/app.jar"] +ENTRYPOINT ["java", "-jar", "/app/app.jar"] diff --git a/Jenkinsfile b/Jenkinsfile index ab4c87e..4b06097 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,12 +1,22 @@ pipeline { agent any + options { + timestamps() + disableConcurrentBuilds() + timeout(time: 45, unit: 'MINUTES') + } + environment { APP_NAME = 'agent-foundation' - IMAGE_NAME = 'your-registry/agent-foundation' + IMAGE_NAME = 'agent-foundation' IMAGE_TAG = "${env.BUILD_NUMBER}" CONTAINER_NAME = 'agent-foundation' - APP_PORT = '8080' + APP_PORT = '8880' + CONTAINER_PORT = '8880' + MAVEN_IMAGE = 'maven:3.9.16-eclipse-temurin-17-alpine' + RUNTIME_IMAGE = 'eclipse-temurin:17-jre-alpine' + DOCKER_BUILDKIT = '1' } stages { @@ -16,10 +26,32 @@ } } + stage('Pull Base Images') { + steps { + script { + [env.MAVEN_IMAGE, env.RUNTIME_IMAGE].each { image -> + retry(3) { + timeout(time: 10, unit: 'MINUTES') { + sh "docker pull ${image}" + } + } + } + } + } + } + stage('Build Image') { steps { script { - sh "docker build -t ${IMAGE_NAME}:${IMAGE_TAG} -t ${IMAGE_NAME}:latest ." + timeout(time: 20, unit: 'MINUTES') { + sh """ + docker build --progress=plain \ + --build-arg MAVEN_IMAGE=${MAVEN_IMAGE} \ + --build-arg RUNTIME_IMAGE=${RUNTIME_IMAGE} \ + -t ${IMAGE_NAME}:${IMAGE_TAG} \ + -t ${IMAGE_NAME}:latest . + """ + } } } } @@ -50,7 +82,8 @@ sh ''' docker run -d \ --name ${CONTAINER_NAME} \ - -p ${APP_PORT}:8080 \ + --restart unless-stopped \ + -p ${APP_PORT}:${CONTAINER_PORT} \ -e DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY} \ -e WECOM_CORP_ID=${WECOM_CORP_ID} \ -e WECOM_AGENT_ID=${WECOM_AGENT_ID} \ @@ -61,6 +94,24 @@ } } } + + stage('Verify') { + steps { + timeout(time: 3, unit: 'MINUTES') { + sh ''' + for attempt in $(seq 1 30); do + if docker exec ${CONTAINER_NAME} wget -qO- http://127.0.0.1:${CONTAINER_PORT}/actuator/health | grep -q '"status":"UP"'; then + echo "Health check passed" + exit 0 + fi + sleep 5 + done + docker logs --tail 200 ${CONTAINER_NAME} + exit 1 + ''' + } + } + } } post {