SpringBoot Dockerfile
https://spring.io/guides/topicals/spring-boot-docker/
run.sh for The Entry Point
#Java 프로세스가 KILL컨테이너로 전송 된 신호에 응답합니다. FROM openjdk:8-jdk-alpine VOLUME /tmp COPY run.sh . COPY target/*.jar app.jar ENTRYPOINT ["run.sh"]
run.sh
#!/bin/sh exec java ${JAVA_OPTS} -jar /app.jar ${@}
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-jre-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
Kubernetes Deployment Security-Context
https://v1-18.docs.kubernetes.io/blog/2016/08/security-best-practices-kubernetes-deployment/
Security Context Setting | Description |
---|---|
SecurityContext->runAsNonRoot | Indicates that containers should run as non-root user |
SecurityContext->Capabilities | Controls the Linux capabilities assigned to the container. |
SecurityContext->readOnlyRootFilesystem | Controls whether a container will be able to write into the root filesystem. |
PodSecurityContext->runAsNonRoot | Prevents running a container with 'root' user as part of the pod |
apiVersion: v1 kind: Pod metadata: name: hello-world spec: containers: # specification of the pod’s containers # ... securityContext: readOnlyRootFilesystem: true runAsNonRoot: true
Pod Security-Context
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"