[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-sovremennaya-razrabotka-web-kak-konteynerizirovat-i-deploit-java-prilozhenie":3},{"id":4,"slug":5,"topicId":6,"topicSlug":7,"topicName":8,"topicEmoji":9,"question":10,"answer":11,"codeLang":12,"codeSrc":12,"important":12,"commonMistakes":12,"modernUsage":12,"difficulty":13,"tags":14,"related":20,"progress":21,"seo":22},1199,"kak-konteynerizirovat-i-deploit-java-prilozhenie",37,"sovremennaya-razrabotka-web","Современная разработка WEB","🌐","Как контейнеризировать и деплоить Java-приложение?","Контейнеризация Java-приложения строится на multi-stage Docker build с layered JAR, а деплой в production выполняется через Kubernetes с Helm\u002FKustomize.\n\n### Multi-stage Dockerfile\n\n\u003Cdetails>\n\u003Csummary>Dockerfile\u003C\u002Fsummary>\n\n```dockerfile\n# Stage 1: Build\nFROM eclipse-temurin:21-jdk-alpine AS builder\nWORKDIR \u002Fapp\nCOPY build.gradle.kts settings.gradle.kts gradlew .\u002F\nCOPY gradle\u002F gradle\u002F\nRUN .\u002Fgradlew dependencies --no-daemon\n\nCOPY src\u002F src\u002F\nRUN .\u002Fgradlew bootJar --no-daemon -x test\n\n# Stage 2: Extract layers\nFROM eclipse-temurin:21-jdk-alpine AS extractor\nWORKDIR \u002Fapp\nCOPY --from=builder \u002Fapp\u002Fbuild\u002Flibs\u002F*.jar app.jar\nRUN java -Djarmode=tools -jar app.jar extract --layers --launcher --destination extracted\n\n# Stage 3: Runtime\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR \u002Fapp\nRUN addgroup -S appgroup && adduser -S appuser -G appgroup\n\nCOPY --from=extractor \u002Fapp\u002Fextracted\u002Fdependencies\u002F .\u002F\nCOPY --from=extractor \u002Fapp\u002Fextracted\u002Fspring-boot-loader\u002F .\u002F\nCOPY --from=extractor \u002Fapp\u002Fextracted\u002Fsnapshot-dependencies\u002F .\u002F\nCOPY --from=extractor \u002Fapp\u002Fextracted\u002Fapplication\u002F .\u002F\n\nUSER appuser\nEXPOSE 8080\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \\\n  CMD wget -qO- http:\u002F\u002Flocalhost:8080\u002Factuator\u002Fhealth\u002Fliveness || exit 1\n\nENTRYPOINT [\"java\", \"-XX:+UseZGC\", \"-XX:MaxRAMPercentage=75.0\", \\\n  \"org.springframework.boot.loader.launch.JarLauncher\"]\n```\n\n\u003C\u002Fdetails>\n\n### Kubernetes Deployment\n\n\u003Cdetails>\n\u003Csummary>deployment.yml\u003C\u002Fsummary>\n\n```yaml\napiVersion: apps\u002Fv1\nkind: Deployment\nmetadata:\n  name: order-service\nspec:\n  replicas: 3\n  template:\n    spec:\n      containers:\n        - name: order-service\n          image: ghcr.io\u002Fexample\u002Forder-service:latest\n          ports:\n            - containerPort: 8080\n          resources:\n            requests:\n              cpu: 250m\n              memory: 512Mi\n            limits:\n              cpu: 1000m\n              memory: 1Gi\n          livenessProbe:\n            httpGet:\n              path: \u002Factuator\u002Fhealth\u002Fliveness\n              port: 8080\n            initialDelaySeconds: 30\n            periodSeconds: 10\n          readinessProbe:\n            httpGet:\n              path: \u002Factuator\u002Fhealth\u002Freadiness\n              port: 8080\n            initialDelaySeconds: 15\n          startupProbe:\n            httpGet:\n              path: \u002Factuator\u002Fhealth\u002Fliveness\n              port: 8080\n            failureThreshold: 30\n          lifecycle:\n            preStop:\n              exec:\n                command: [\"sh\", \"-c\", \"sleep 10\"]\n      terminationGracePeriodSeconds: 60\n```\n\n\u003C\u002Fdetails>\n\n### Graceful shutdown\n\n```yaml\nspring:\n  lifecycle:\n    timeout-per-shutdown-phase: 30s\nserver:\n  shutdown: graceful\n```\n\nПоследовательность: SIGTERM -> preStop (sleep 10) -> readiness DOWN -> ожидание завершения запросов -> закрытие контекста.\n\n### GraalVM Native Image\n\n| Критерий | JVM | Native Image |\n|----------|-----|-------------|\n| Старт | 2-10 секунд | Менее 100 мс |\n| Память | Средняя-высокая | Низкая |\n| Peak performance | Выше (JIT) | Ниже (AOT) |\n| Подходит для | Long-running сервисы | Serverless, CLI, FaaS |\n\n### Частые ошибки\n\n- Запуск контейнера от root — уязвимость\n- Отсутствие resource limits: pod занимает весь node\n- latest тег в production — неизвестно, какая версия запущена\n- Отсутствие startup probe: liveness probe убивает pod, который ещё не стартовал\n- MaxRAMPercentage=100% — не остаётся места для off-heap памяти, используйте 75%\n\n> **На собеседовании:** обязательные знания: multi-stage build (зачем три этапа), layered JAR (кэширование Docker-слоёв), non-root user, три типа probe (startup, liveness, readiness) и их назначение. Вопрос \"Почему не latest?\" — ответ: невозможно откатить и понять, что запущено. Используйте SHA или semver.","","middle",[15,16,17,18,19],"multi-stage-build","kubernetes","spring-boot","layered-jar","docker",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":38,"featuredSnippetReady":39},"Как контейнеризировать и деплоить Java-приложение — Gymterview","Контейнеризация Java: multi-stage Dockerfile, layered JAR, Kubernetes Deployment с probes, Graceful shutdown, GraalVM Native Image. Non-root, ZGC, MaxRAMPercentage.","Контейнеризация и деплой Java-приложения: Docker + Kubernetes — Gymterview","Multi-stage Dockerfile, layered JAR, Kubernetes probes, Graceful shutdown, GraalVM Native Image. Production best practices.",[28,29,30,31,32,33,34,35,36,37],"Docker Java","multi-stage build","layered JAR","Kubernetes","liveness probe","readiness probe","GraalVM Native Image","Graceful shutdown","ZGC","собеседование","Multi-stage Docker build: build (JDK), extract layers, runtime (JRE). Layered JAR для кэширования Docker-слоёв. Non-root user обязателен. Kubernetes: три типа probe (startup, liveness, readiness), resource limits, Graceful shutdown (SIGTERM -> preStop sleep -> завершение запросов). ZGC + MaxRAMPercentage=75%. GraalVM Native Image для serverless (\u003C100ms старт).",true]