[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"question-bezopasnost-konteynerov-kak-ispolzovat-multistage-builds-dlya-povysheniya-bezopasnosti":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},314,"kak-ispolzovat-multistage-builds-dlya-povysheniya-bezopasnosti",9,"bezopasnost-konteynerov","Безопасность контейнеров","🛡️","Как использовать multistage builds для повышения безопасности?","Multistage build -- это техника построения Docker-образов, при которой Dockerfile содержит несколько стадий сборки, и в финальный образ копируются только необходимые артефакты, исключая компилятор, исходный код, тесты и build-утилиты.\n\nАналогия: multistage build -- как кухня ресторана. Гостю (production) подают только готовое блюдо, а все ножи, разделочные доски и отходы (JDK, Maven, исходники) остаются на кухне и не попадают в зал.\n\n### Проблема без multistage build\n\n```dockerfile\n# ПЛОХО: всё в одном образе\nFROM eclipse-temurin:21-jdk\nWORKDIR \u002Fapp\nCOPY . .\nRUN .\u002Fmvnw clean package\nENTRYPOINT [\"java\", \"-jar\", \"target\u002Fapp.jar\"]\n# Результат: образ ~800 MB, содержит JDK, Maven, исходники, тесты, .git\n```\n\nЭтот образ содержит JDK с компилятором, Maven wrapper, все исходные файлы, тестовые зависимости, `.git` директорию -- всё это увеличивает поверхность атаки и даёт атакующему инструменты для дальнейшего проникновения.\n\n### Правильный multistage build для Java\n\n\u003Cdetails>\n\u003Csummary>Multistage build с layered Spring Boot jar\u003C\u002Fsummary>\n\n```dockerfile\n# ============ Этап 1: Сборка ============\nFROM eclipse-temurin:21-jdk-alpine AS builder\n\nWORKDIR \u002Fbuild\n\n# Кэширование зависимостей Maven\nCOPY pom.xml .\nCOPY .mvn .mvn\nCOPY mvnw .\nRUN .\u002Fmvnw dependency:go-offline -B\n\n# Копирование исходного кода и сборка\nCOPY src .\u002Fsrc\nRUN .\u002Fmvnw clean package -DskipTests -B && \\\n    # Извлечение Spring Boot layered jar для лучшего кэширования\n    java -Djarmode=layertools -jar target\u002F*.jar extract --destination \u002Fextracted\n\n# ============ Этап 2: Финальный образ ============\nFROM eclipse-temurin:21-jre-alpine\n\nRUN addgroup -S banking && adduser -S banking -G banking\n\nWORKDIR \u002Fapp\n\n# Копирование только скомпилированного приложения (layered)\nCOPY --from=builder --chown=banking:banking \u002Fextracted\u002Fdependencies\u002F .\u002F\nCOPY --from=builder --chown=banking:banking \u002Fextracted\u002Fspring-boot-loader\u002F .\u002F\nCOPY --from=builder --chown=banking:banking \u002Fextracted\u002Fsnapshot-dependencies\u002F .\u002F\nCOPY --from=builder --chown=banking:banking \u002Fextracted\u002Fapplication\u002F .\u002F\n\nUSER banking\n\nEXPOSE 8080\n\nHEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \\\n    CMD wget --no-verbose --tries=1 --spider http:\u002F\u002Flocalhost:8080\u002Factuator\u002Fhealth || exit 1\n\nENTRYPOINT [\"java\", \"org.springframework.boot.loader.launch.JarLauncher\"]\n```\n\n\u003C\u002Fdetails>\n\n### Multistage build с кастомным JRE (jlink)\n\n\u003Cdetails>\n\u003Csummary>Трёхстадийная сборка с jlink\u003C\u002Fsummary>\n\n```dockerfile\n# Этап 1: Сборка приложения\nFROM eclipse-temurin:21-jdk-alpine AS builder\nWORKDIR \u002Fbuild\nCOPY . .\nRUN .\u002Fmvnw clean package -DskipTests\n\n# Этап 2: Определение нужных Java-модулей и создание кастомного JRE\nFROM eclipse-temurin:21-jdk-alpine AS jre-builder\nCOPY --from=builder \u002Fbuild\u002Ftarget\u002F*.jar \u002Fapp\u002Fapp.jar\nRUN jar xf \u002Fapp\u002Fapp.jar && \\\n    jdeps \\\n        --ignore-missing-deps \\\n        --print-module-deps \\\n        --multi-release 21 \\\n        --class-path 'BOOT-INF\u002Flib\u002F*' \\\n        \u002Fapp\u002Fapp.jar > \u002Fmodules.txt && \\\n    jlink \\\n        --add-modules $(cat \u002Fmodules.txt) \\\n        --strip-debug \\\n        --no-man-pages \\\n        --no-header-files \\\n        --compress=zip-9 \\\n        --output \u002Fcustom-jre\n\n# Этап 3: Минимальный финальный образ\nFROM alpine:3.20\nCOPY --from=jre-builder \u002Fcustom-jre \u002Fopt\u002Fjava\nCOPY --from=builder \u002Fbuild\u002Ftarget\u002F*.jar \u002Fapp\u002Fapp.jar\n\nRUN addgroup -S app && adduser -S app -G app\nUSER app\n\nENV JAVA_HOME=\u002Fopt\u002Fjava\nENV PATH=\"${JAVA_HOME}\u002Fbin:${PATH}\"\n\nENTRYPOINT [\"java\", \"-jar\", \"\u002Fapp\u002Fapp.jar\"]\n```\n\n\u003C\u002Fdetails>\n\n### Что удаляется из финального образа\n\n| Компонент | Угроза | Удалён в multistage? |\n|-----------|--------|---------------------|\n| JDK (javac, jdb) | Компиляция вредоносного кода на месте | Да |\n| Maven\u002FGradle | Скачивание вредоносных зависимостей извне | Да |\n| Исходный код | Реверс-инжиниринг бизнес-логики | Да |\n| Тестовый код и данные | Утечка тестовых учётных данных | Да |\n| Build-утилиты (git, curl) | Инструменты для развития атаки | Да |\n| `.git` директория | История изменений, возможные секреты в коммитах | Да |\n\n### Файл .dockerignore\n\nНе забывайте о `.dockerignore` -- он предотвращает копирование ненужных файлов в контекст сборки:\n\n```\n.git\n.gitignore\n*.md\ndocker-compose*.yml\n.env\n.idea\n*.iml\ntarget\n!target\u002F*.jar\n```\n\n### Вывод\n\nMultistage build -- обязательная практика для production-образов. Она уменьшает размер образа в 5-10 раз, удаляет из финального образа все build-инструменты и исходный код, что радикально сокращает поверхность атаки.\n\n> **На собеседовании:** покажите понимание двух- или трёхстадийной сборки, объясните, почему каждый удалённый компонент -- это закрытая дверь для атакующего. Бонус -- упомяните layered jars Spring Boot и jlink для создания кастомного JRE.","","middle",[15,16,17,18,19],"multistage-build","dockerfile","container-security","jlink","docker",[],null,{"title":23,"description":24,"ogTitle":25,"ogDescription":26,"keywords":27,"schemaAnswer":33,"featuredSnippetReady":34},"Multistage builds для безопасности Docker — Java-примеры — Gymterview","Multistage build исключает из финального образа JDK, Maven, исходники и build-утилиты. Примеры для Java: layered Spring Boot jar, jlink, .dockerignore.","Multistage builds для безопасности Docker — уменьшение attack surface","Multistage build удаляет из финального образа JDK, Maven, исходники, .git и тесты. Результат: образ ~60 MB вместо ~800 MB, минимальная поверхность атаки.",[28,29,30,31,32],"multistage build Docker","multistage build безопасность","Docker multistage Java","layered jar Spring Boot","dockerignore","Multistage build — Dockerfile с несколькими этапами, где в финальный образ копируются только необходимые артефакты. Из финального образа исключаются: JDK с компилятором, Maven\u002FGradle, исходный код, тесты, .git. Для Java рекомендуется layered Spring Boot jar и jlink для кастомного JRE. Результат: образ ~60 MB вместо ~800 MB.",true]