Java 어플리케이션 컨테이너화(봄 시작) 카트 가이드

"스크립트"언어를 바탕으로 응용 프로그램을 용기화하는 것은 매우 간단하다.원본 코드를 추가하고 의존항을 다운로드하면 시작할 수 있습니다.그들이 보고 얻은 것이라고 말할 수 있다.
FROM python:3

ADD requirements.txt .            # 1
RUN pip install                   # 2

ADD script.py .                   # 3

CMD ["python", "./script.py"]     # 4
  • 복제 의존 항목에 대한 설명
  • 다운로드 종속성
  • 기본 스크립트 복사
  • 스크립트 실행
  • 컴파일 언어, 특히 Java는 상황이 좀 다르다.이 문장에서 나는 이 목표를 실현하는 대체 방안을 열거하고 싶다.

    예제 응용 프로그램


    이러한 대체 방안을 설명하기 위해서, 우리는 예시 응용 프로그램이 필요하다.Spring Boot을 사용하여 REST 노드를 제공하고 데이터를 Hazelcast에 저장합니다.그것은 Maven을 사용하여 구축된 것으로 기존wrapper이 있다.

    REST 끝점은 다음과 같이 작동합니다.
    curl -X PUT http://localhost:8080/John
    
    {"who":"John","when":64244336297226}
    
    curl http://localhost:8080/
    
    [{"who":"John","when":64244336297226}]
    
    스크립트 언어에 비해 Java 응용 프로그램은 두 가지 주요 차이점이 있습니다.
  • Java 소스 코드를 바이트 코드로 변환하려면 추가 컴파일 절차가 필요합니다.
  • 배포 유닛은 일반적으로 자체 실행 JAR
  • 천진난만한 방법


    첫 번째 단계는 Docker 외부에서 응용 프로그램을 구축한 다음 JAR을 이미지에 추가할 수 있습니다.
    ./mvnw clean package -DskipTests
    
    # docker build -t spring-in-docker:0.5 .
    
    FROM adoptopenjdk/openjdk11:alpine-jre
    
    COPY target/spring-in-docker-0.5.jar spring-in-docker.jar
    
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "spring-in-docker.jar"]
    
    다음 논리적 단계는 Dockerfile 에서 응용 프로그램을 구축하는 것입니다.
    # docker build -t spring-in-docker:1.0 .
    
    FROM adoptopenjdk/openjdk11:alpine-slim
    
    COPY .mvn .mvn
    COPY mvnw .
    COPY pom.xml .
    COPY src src
    RUN ./mvnw package -DskipTests
    
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "target/spring-in-docker-1.0.jar"]
    
    이런 방식은 몇 가지 단점이 있다.
  • 최종 이미지에는 JDK가 포함되어 있습니다.우선 JRE에 비해 최종 이미지의 크기가 증가합니다.더 중요한 것은 Java 코드를 이미지로 컴파일할 수 있다는 것이다. 이것은 생산 중의 심각한 안전 결함일 수도 있다.
  • Maven의 POM 버전은 이미지의 버전과 수동으로 동기화해야 합니다.
  • JAR에는 OCI 레이어가 하나만 있습니다.
  • dive 실행 가능한 파일은 마지막 점을 강조합니다.
    Layers ├─────────────────────────────────────────────────────────────────────────────
    Size     Command
    5.6 MB   FROM 31609b718dd2bed
     14 MB   apk add --no-cache tzdata --virtual .build-deps curl binutils zstd     && GL
     17 kB   #(nop) COPY multi:5542ba69976bc682acd7b679c22d8a0277609ba9f5b611fd518f87f209
    235 MB   set -eux;     apk add --no-cache --virtual .fetch-deps curl;     ARCH="$(apk
     56 kB   #(nop) COPY dir:20c328136da94aa01b2b6fd62c88ef506a15b545aefeb1a1e13473572aee
     10 kB   #(nop) COPY file:08c603013feae81d794c29c4c1f489cc58a32bd593154cc5e40c6afa522
    1.8 kB   #(nop) COPY file:1bb01c4e5b60aae391d2efc563ead23a959701863adcf408540f33b7e40
     54 kB   #(nop) COPY dir:d2bd6e2521e5d990b16efb81ae8823e23ed2de826e833b331718b2211d6a
    108 MB   ./mvnw package -DskipTests
    
    
    │ ● Current Layer Contents ├─────────────────────────────────────────────────────────
    Permission     UID:GID     Size  Filetree
    drwx------       0:0      80 MB  ├─⊕ root
    drwxr-xr-x       0:0      28 MB  └── target
    drwxr-xr-x       0:0     5.8 kB      ├─⊕ classes
    drwxr-xr-x       0:0        0 B      ├─⊕ generated-sources
    drwxr-xr-x       0:0       64 B      ├─⊕ maven-archiver
    drwxr-xr-x       0:0      364 B      ├─⊕ maven-status
    -rw-r--r--       0:0      28 MB      ├── spring-in-docker-1.0.jar
    -rw-r--r--       0:0     5.4 kB      └── spring-in-docker-1.0.jar.original
    
    처음에는 단층이 큰 문제가 아닌 것처럼 보였지만, 그것은 커다란 결과를 가져왔다.소스 코드의 모든 변경 사항은 OCI 레이어 전체를 교체해야 합니다.

    다단계 구조


    Docker 다중 레벨 구축은 여러 구축 단계를 연결할 수 있으며, 체인의 다음 단계는 초기 단계에서 만들어진 부품을 다시 사용합니다.이렇게 하면 JDK를 사용하여 컴파일하고 JRE를 사용하여 수행할 수 있습니다.
    # docker build -t spring-in-docker:1.1 .
    
    FROM adoptopenjdk/openjdk11:alpine-slim as build                         # 1
    
    COPY .mvn .mvn
    COPY mvnw .
    COPY pom.xml .
    COPY src src
    RUN ./mvnw package -DskipTests
    
    FROM adoptopenjdk/openjdk11:alpine-jre                                   # 2
    
    COPY --from=build target/spring-in-docker-1.1.jar spring-in-docker.jar   # 3
    
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "spring-in-docker.jar"]
    
  • 구축 단계에서 JDK 사용
  • JRE 사용 단계 실행
  • 이전 단계build에서 작성한 JAR 복사
    여러 단계로 각 단계를 구성하여 이미지를 생성합니다.최신 이미지를 제외하고는 모든 이미지가 표시되지 않습니다.
    층을 나누기 위해 의존항의 다운로드와 컴파일, 패키지 결합을 개선할 수 있다.
    # docker build -t spring-in-docker:1.2 .
    
    FROM adoptopenjdk/openjdk11:alpine-slim as build
    
    COPY .mvn .mvn                                                           # 1
    COPY mvnw .                                                              # 1
    COPY pom.xml .                                                           # 1
    RUN ./mvnw dependency:go-offline                                          # 2
    
    COPY src src                                                             # 3
    RUN ./mvnw package -DskipTests
    
    FROM adoptopenjdk/openjdk11:alpine-jre
    
    COPY --from=build target/spring-in-docker-1.2.jar spring-in-docker.jar
    
    EXPOSE 8080
    ENTRYPOINT ["java", "-jar", "spring-in-docker.jar"]
    
  • 모든 필수 파일을 복사하여 종속성 다운로드
  • 다운로드 의존 항목 - 전용 계층의 일부가 됩니다
  • 현재 원본 복제;그러면 다른 레이어가 추가됩니다
  • .dive 이미지로 이동합니다.
    Layers ├────────────────────────────────────────────────────────────────────────────
      Size  Command
    5.6 MB  FROM 31609b718dd2bed
     14 MB  apk add --no-cache tzdata --virtual .build-deps curl binutils zstd     && GL
     17 kB  #(nop) COPY multi:5542ba69976bc682acd7b679c22d8a0277609ba9f5b611fd518f87f209
    235 MB  set -eux;     apk add --no-cache --virtual .fetch-deps curl;     ARCH="$(apk
     56 kB  #(nop) COPY dir:20c328136da94aa01b2b6fd62c88ef506a15b545aefeb1a1e13473572aee
     10 kB  #(nop) COPY file:08c603013feae81d794c29c4c1f489cc58a32bd593154cc5e40c6afa522
    1.8 kB  #(nop) COPY file:f191db2f3a7fe2e434025c321ad8106112373b1aa0fa99f1a76c884bf61
    100 MB  ./mvnw dependency:go-offline
     54 kB  #(nop) COPY dir:d2bd6e2521e5d990b16efb81ae8823e23ed2de826e833b331718b2211d6a # 1
     28 MB  ./mvnw package -DskipTests
    
  • 의존층
  • 마지막 build에 대해 우리는 두 가지 문제를 해결하려고 했다. 그것이 바로 JDK의 안전 문제와 층별 문제이다.단, 이미지를 구축할 때, 우리는 수동으로 버전을 설정해야 한다.POM과 이미지 사이에 동기화가 없습니다.
    이 밖에 다단계 구축은 skaffold 과 호환되지 않는다.원본 코드를 변경할 때 자동으로 Kubernetes 그룹에 대한 배치를 터치하는 데 익숙해지면 잊어버리십시오.

    기중팔


    Jib는 구글이 제공하는 Maven 플러그인(Gradle에서도 사용할 수 있음)으로 이 같은 문제를 우아하게 해결했다.
    Jib의 배후 개념은 간단하지만 똑똑하다.Java는 JAR을 실행할 수 있지만 표준 Java 클래스도 실행할 수 있습니다.용기 외에 JAR은 매우 좋은 배치 단원이다.그러나 용기 세계에서 JAR은 별도의 포장기일 뿐이다. 용기는 배치 단원이기 때문이다.
    Jib 플러그인은 구축 시스템에서 Java 소스 코드를 컴파일하고 충분한 자원을 층별로 복사하며 응용 프로그램을 분해 형식으로 실행하는 이미지를 만듭니다.
    <plugin>
      <groupId>com.google.cloud.tools</groupId>
      <artifactId>jib-maven-plugin</artifactId>
      <version>2.5.2</version>
      <configuration>
        <to>
          <image>${project.artifactId}:${project.version}</image> <!-- 1 -->
        </to>
      </configuration>
    </plugin>
    
  • POM
  • 과 이미지 버전 자동 동기화
    Jib는 Docker 저장소에 이미지를 업로드하고 Docker 수호 프로세스를 구축하는 두 가지 목표를 제공합니다.로컬에서 이미지를 만듭니다.
    mvn compile com.google.cloud.tools:jib-maven-plugin:2.6.0
    
    Dockerfile 출력은 다음과 같습니다.
    Layers ├────────────────────────────────────────────────────────────────────────────
      Size  Command
    1.8 MB  FROM 7cfeac17984f4f4
     15 MB  bazel build ...
    1.9 MB  bazel build ...
    8.4 MB  bazel build ...
    170 MB  bazel build ...
     16 MB  jib-maven-plugin:2.5.2
     12 MB  jib-maven-plugin:2.5.2
       1 B  jib-maven-plugin:2.5.2
    5.8 kB  jib-maven-plugin:2.5.2
    
    Jib는 4 개의 레이어를 만들었습니다.
  • 종속성
  • 스냅샷 종속성
  • 리소스
  • 코드 컴파일
  • 2층 처리build 의존항의 경우: 버전 번호가 같지만 이러한 의존항의 내용은 변경할 수 있습니다.개발 과정에서 이런 상황이 발생할 수 있다.스냅샷 의존 항목을 생산 환경에 배치해서는 안 됩니다.
    Docker 컨테이너의 명령줄은 다음과 같습니다.
    java -cp /app/resources:/app/classes:/app/libs/* ch.frankel.blog.springindocker.SpringInDockerApplication
    
    또한 생성된 이미지의 부모 이미지를 변경하는 것은 매우 간단합니다.
    <plugin>
      <groupId>com.google.cloud.tools</groupId>
      <artifactId>jib-maven-plugin</artifactId>
      <version>2.5.2</version>
      <configuration>
        <from>
          <image>adoptopenjdk/openjdk11:alpine-jre</image> <!-- 1 -->
        </from>
        <to>
          <image>${project.artifactId}:${project.version}</image>
        </to>
      </configuration>
    </plugin>
    
  • 상위 이미지를 Alpine
  • 으로 변경
    삼각돛이 가장 좋은 선택인 것 같다.하지만 다른 선택을 계속 탐색합시다.

    스프링 부츠 분층 탱크


    2.3 버전에서는 Spring Boot을 사용하여 전용 폴더 구조를 가진 JAR을 작성할 수 있습니다.이 폴더를 dockerBuild 의 레이어에 매핑할 수 있습니다.기본적으로 다음과 같습니다.
  • 종속성
  • 스냅샷 종속성
  • Spring Boot runtime
  • 리소스 및 컴파일 코드
  • 특정 dive 파일 customize those folders 을 사용할 수 있습니다.
    다음은 기본 레이어가 있는 Spring 부트 응용 프로그램을 만드는 방법을 보여 주는 다단계 구축 파일입니다.
    FROM adoptopenjdk/openjdk11:alpine-slim as builder
    
    COPY .mvn .mvn
    COPY mvnw .
    COPY pom.xml .
    RUN ./mvnw dependency:go-offline
    
    COPY src src
    RUN ./mvnw package -DskipTests                                            # 1
    
    FROM adoptopenjdk/openjdk11:alpine-jre as layers
    
    COPY --from=builder target/spring-in-docker-3.0.jar spring-in-docker.jar
    RUN java -Djarmode=layertools -jar spring-in-docker.jar extract           # 2
    
    FROM adoptopenjdk/openjdk11:alpine-jre
    
    COPY --from=layers dependencies/ .                                        # 3
    COPY --from=layers snapshot-dependencies/ .                               # 3
    COPY --from=layers spring-boot-loader/ .                                  # 3
    COPY --from=layers application/ .                                         # 3
    
    ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher"]
    
  • 표준 자체 실행 JAR 작성
  • 폴더 구조 추출
  • 레이어의 각 폴더 복사
  • 이런 방법은 상기SNAPSHOT의 모든 단점을 가지고 있다. skaffold와 통합되지 않았고 POM 버전과 동기화되지 않았다.
    또한 정확한 순서로 층을 만드는 것을 조심해야 합니다.

    운본 기구 건설 패키지


    Cloud-Native BuildpacksHeroku의buildpacks에서 유래했습니다.Heroku는 초기의 클라우드 관리 플랫폼 중의 하나이다.Git 저장소도 제공합니다.Heroku에 배치하려면 원본 코드를 원격 Heroku 저장소로 전송하기만 하면 됩니다.
    이 플랫폼은 원본 코드에서 실행 가능한 파일을 구축하는 방법을 이해합니다.그것은 알림으로 파일이 있는지 확인합니다.예를 들어 repo가 루트 디렉터리에 Dockerfile 파일을 포함하면 Mavenbuildpack을 활성화합니다.layers.xml가 있으면 노드가 활성화됩니다.js1;기다리다
    CNB는 OCI 용기를 위한 Heroku의 BuildPack 개선입니다.Heroku와 VMWare Tanzu(Spring Boot 배후 회사)가 이 프로젝트의 선봉이다.그것은 CNCF가 주최한다.
    buildpack을 사용하려면 Dockerfile 명령과builder 인용, 그리고 구축할 이미지 표시만 호출해야 합니다.응용 프로그램을 구축하고 기본 상위 이미지에서 상속합니다.예를 들어, 예제 응용 프로그램을 구성하는 명령줄은 다음과 같습니다.
    pack build --builder gcr.io/paketo-buildpacks/builder:base-platform-api-0.3 spring-in-docker:4.0
    
    프로젝트에 사용할 구성 패키지를 트리거합니다.
    ===> DETECTING
    [detector] 6 of 17 buildpacks participating
    [detector] paketo-buildpacks/bellsoft-liberica 4.0.0
    [detector] paketo-buildpacks/maven             3.1.1
    [detector] paketo-buildpacks/executable-jar    3.1.1
    [detector] paketo-buildpacks/apache-tomcat     2.3.0
    [detector] paketo-buildpacks/dist-zip          2.2.0
    [detector] paketo-buildpacks/spring-boot       3.2.1
    
    [builder] Paketo BellSoft Liberica Buildpack 4.0.0
    [builder]   https://github.com/paketo-buildpacks/bellsoft-liberica
    [builder]   Build Configuration:
    [builder]     $BP_JVM_VERSION              11.*            the Java version             # 1
    [builder]   Launch Configuration:
    [builder]     $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    [builder]     $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    [builder]     $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    [builder]     $JAVA_TOOL_OPTIONS                           the JVM launch flags
    
  • 에서 JVM 버전을 테스트합니다.buildpack에서 정확한 JDK를 다운로드합니다.
  • 나는 몇 가지 결점을 겪었다.
  • pom.xml는 변하지 않는 것이 아니다.이 구축은 이전에 일한 적이 있다.이 문서를 작성할 때 Go bug 때문에 실패했습니다.
  • JDK의 다운로드는 이전의 실행에서 이미 다운로드되었음에도 불구하고 실행될 때마다 발생합니다.
  • 부모 이미지를 변경하는 것이 쉽지 않다는 것을 발견했습니다.
  • 또한 package.json 과 마찬가지로 버전을 수동으로 표시해야 합니다.

    Spring 부트 플러그인


    Spring Boot을 사용하여 외부 명령을 호출할 필요가 없습니다.이 플러그인은 pack와 같은 base-platform-api-0.3 목표를 제공하고, 관련된buildpack을 호출합니다.
    다음을 실행합니다.
    ./mvnw spring-boot:build-image
    
    [INFO]  > Running creator
    [INFO]     [creator]     ===> DETECTING
    [INFO]     [creator]     5 of 17 buildpacks participating
    [INFO]     [creator]     paketo-buildpacks/bellsoft-liberica 4.0.0
    [INFO]     [creator]     paketo-buildpacks/executable-jar    3.1.1
    [INFO]     [creator]     paketo-buildpacks/apache-tomcat     2.3.0
    [INFO]     [creator]     paketo-buildpacks/dist-zip          2.2.0
    [INFO]     [creator]     paketo-buildpacks/spring-boot       3.2.1
    
    이 옵션의 이점은 다음과 같습니다.
  • POM 버전에서 이미지 버전을 자동으로 읽습니다.
  • 변경되지 않은 재구축 속도가 빠릅니다.
  • 구성 매개변수를 구성하여 최종 이미지에 위의 4개의 Spring 부트 레이어가 있습니다.
  • 그 밖에 일부 구축 패키지는 맞춤형 구축 과정을 쉽게 한다.예를 들어, 최종 가공소재를 네이티브 실행 파일로 만들려면 필요한 환경 변수를 추가해야 합니다.
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <configuration>
        <layers>
          <enabled>true</enabled>
        </layers>
        <image>
          <name>${project.artifactId}:${project.version}</name>
          <env>
            <BP_BOOT_NATIVE_IMAGE>true</BP_BOOT_NATIVE_IMAGE>
          </env>
        </image>
      </configuration>
    </plugin>
    
    가장 큰 문제는 부모 이미지를 바꾸는 것이 쉽지 않다는 것이다.

    요점을 요약하여 다시 말하다.


    다음은 최종 이미지와 각각의 크기입니다.나는 다단계 구축에 사용되는 이미지도 표시했다.
    REPOSITORY                TAG          IMAGE ID       CREATED         SIZE
    spring-in-docker          0.5          ca380d4677f9   3 days ago      177MB
    spring-in-docker          1.0          f16667a974f4   3 days ago      363MB
    spring-in-docker/build    1.1          2f2a59f49486   3 days ago      363MB
    spring-in-docker          1.1          45ae57fab5ae   3 days ago      177MB
    spring-in-docker/build    1.2          b94b6a80a437   3 days ago      383MB
    spring-in-docker          1.2          cbddb2300b1a   3 days ago      177MB
    spring-in-docker          2.0          fb7d8501623a   50 years ago    225MB
    spring-in-docker          2.1          c3b60a214da2   50 years ago    177MB
    spring-in-docker/build    3.0-b        1eea78545af2   2 days ago      206MB
    spring-in-docker/build    3.0-a        52c180e9f3d1   2 days ago      383MB
    spring-in-docker          3.0          9e2240a4fc00   2 days ago      177MB
    spring-in-docker          5.0          4cbda769276f   40 years ago    264MB
    spring-in-docker          5.5          4ac2d37253ee   40 years ago    184MB
    
    건축하다
    버전 동기화
    계층화
    평론
    다급
    아니오
    수첩
    기중팔
    프로비저닝
    맞다
    구성 패키지
    아니오
    맞다
    유모차
    Spring Boot Maven 플러그인
    맞다
    프로비저닝
  • 보다 다단계 구축
  • 이 유연하지 않음
  • 강력한 매개 변수화는 패키지 구축에 달려 있다
  • 더 나아가서:
  • Use multi-stage builds
  • Getting Started with Cloud Native Buildpacks
  • Jib Quick start
  • Packagin OCI images with Spring Boot
  • 2020년 10월 11일 기준A Java Geek

    좋은 웹페이지 즐겨찾기