https://spring.io/guides/topicals/spring-boot-docker/
run.sh for The Entry Point
FROM openjdk:8-jdk-alpine VOLUME /tmp COPY run.sh . COPY target/*.jar app.jar ENTRYPOINT ["run.sh"]
Smaller Images
OPENJDK:8-JDK-ALPINE
alpine
이미지는 표준보다 작습니다.
목표가 반드시 항상 가능한 가장 작은 이미지를 빌드하는 것은 아닙니다.
일반적으로 작은 이미지는 업로드 및 다운로드에 시간이 덜 걸리지 만 이미지에 이미 캐시 된 레이어가없는 경우에만 적합합니다.
요즘 이미지 레지스트리는 매우 정교하며 이미지 구성을 영리하게 시도하면 이러한 기능의 이점을 쉽게 잃을 수 있습니다.
공통 기본 레이어를 사용하는 경우 이미지의 전체 크기는 문제가되지 않으며 레지스트리와 플랫폼이 발전함에 따라 더 작아 질 것입니다.
그럼에도 불구하고 애플리케이션 이미지의 레이어를 최적화하는 것이 여전히 중요하고 유용하지만 목표는 항상 가장 빠르게 변화하는 항목을 가장 높은 레이어에 배치하는 것이어야합니다.
A Better Dockerfile
## Jar로 압축되지 않은, 압축이 풀린 상태로 서비스를 제공하는 것이 좋습니다. ## 또한 Image Layer를 세분할 수 있습니다. ## 따라서, 첫 번째 레이어 ( BOOT-INF/lib)가 변경되지 않으므로 빌드가 더 빨라지고 기본 레이어가 이미 캐시 된 한 런타임에 컨테이너가 시작됩니다. FROM openjdk:8-jdk-alpine VOLUME /tmp ARG DEPENDENCY=target/dependency COPY ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY ${DEPENDENCY}/META-INF /app/META-INF COPY ${DEPENDENCY}/BOOT-INF/classes /app ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
Multi-Stage Build
FROM openjdk:8-jdk-alpine as build WORKDIR /workspace/app COPY mvnw . COPY .mvn .mvn COPY pom.xml . COPY src src RUN ./mvnw install -DskipTests RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar) FROM openjdk:8-jdk-alpine VOLUME /tmp ARG DEPENDENCY=/workspace/app/target/dependency COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app ENTRYPOINT ["java","-cp","app:app/lib/*","hello.Application"]
Security Aspects
Ubuntu
FROM openjdk:8-jdk-alpine RUN groupadd appgroup && useradd -G appgroup appuser USER appuser
https://v1-18.docs.kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/
apiVersion: v1 kind: Pod metadata: name: hello-world spec: containers: # specification of the pod’s containers # ... securityContext: readOnlyRootFilesystem: true runAsNonRoot: true
https://v1-18.docs.kubernetes.io/docs/tasks/configure-pod-container/security-context/
포드에 대한 보안 컨텍스트 설정
apiVersion: v1 kind: Pod metadata: name: security-context-demo spec: securityContext: runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 volumes: - name: sec-ctx-vol emptyDir: {} containers: - name: sec-ctx-demo image: busybox command: [ "sh", "-c", "sleep 1h" ] volumeMounts: - name: sec-ctx-vol mountPath: /data/demo securityContext: allowPrivilegeEscalation: false
포드에 대한 볼륨 권한 및 소유권 변경 정책 구성
securityContext: runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 fsGroupChangePolicy: "OnRootMismatch"
컨테이너에 대한 보안 컨텍스트 설정
apiVersion: v1 kind: Pod metadata: name: security-context-demo-2 spec: securityContext: runAsUser: 1000 containers: - name: sec-ctx-demo-2 image: gcr.io/google-samples/node-hello:1.0 securityContext: runAsUser: 2000 allowPrivilegeEscalation: false
컨테이너에 대한 기능 설정
apiVersion: v1 kind: Pod metadata: name: security-context-demo-4 spec: containers: - name: sec-ctx-4 image: gcr.io/google-samples/node-hello:1.0 securityContext: capabilities: add: ["NET_ADMIN", "SYS_TIME"]
컨테이너에 SELinux 레이블 할당
... securityContext: seLinuxOptions: level: "s0:c123,c456"