스프링부트와 도커

dahye·2021년 10월 7일
0

docker

목록 보기
3/3

Spring Boot with Docker

  1. 이 가이드는 Spring Boot 애플리케이션을 실행하기 위한 Docker 이미지를 빌드하는 프로세스를 안내 합니다.
  2. 우리는 기본으로 시작 Dockerfile하여 몇 가지 조정을 합니다.
  3. 그런 다음 .NET 대신 빌드 플러그인(Maven 및 Gradle용)을 사용하는 몇 가지 옵션을 보여줍니다
  4. docker은 "시작하기" 가이드이므로 범위는 몇 가지 기본 요구 사항으로 제한됩니다. 프로덕션용 컨테이너 이미지를 빌드하는 경우 고려해야 할 사항이 많고 짧은 가이드에서 모든 것을 다룰 수는 없습니다.


1. What You Will Build

  • Docker 는 사용자가 컨테이너 이미지를 게시하고 다른 사람이 게시한 이미지를 사용(consume those published by others.)할 수 있도록 하는 "소셜" 측면이 있는 Linux 컨테이너 관리 도구(Linux container management toolkit)입니다.
  • Docker 이미지는 컨테이너화된 프로세스를 실행하기 위한 레시피입니다. 이 가이드에서는 간단한 Spring 부트 애플리케이션용으로 빌드합니다.


2. What You Will Need

필요 시간

  • About 15 minutes

필요 기술

  • A favorite text editor or IDE
  • JDK 1.8 or later
  • Gradle 4+ or Maven 3.2+
  • You can also import the code straight into your IDE:
    - Spring Tool Suite (STS)
    - IntelliJ IDEA

필요 작업

  • Linux 시스템을 사용하지 않는 경우 가상화된 서버가 필요합니다.
    ㄴ 1. VirtualBox를 설치하면 Mac과 같은 다른 도구에서 boot2docker원활하게 관리할 수 있습니다.
    ㄴ 2. VirtualBox의 다운로드 사이트를 방문 하여 컴퓨터의 버전을 선택하십시오. 다운로드하여 설치합니다.
    ㄴ 3. 실제로 실행하는 것에 대해 걱정하지 마십시오.

  • 64비트 머신에서만 실행되는 Docker 도 필요 합니다.
    ㄴ 1. 컴퓨터에 Docker를 설정하는 방법에 대한 자세한 내용은 https://docs.docker.com/installation/#installation 을 참조 하세요 .
    ㄴ 2. 계속 진행하기 전에 docker쉘에서 명령을 실행할 수 있는지 확인하십시오 .
    ㄴ 3. 프로세스를 사용하는 경우 먼저 boot2docker 실행해야 합니다



3. Starting with Spring Initializr

프로젝트를 초기화하려면:

  1. https://start.spring.io로 이동(Navigate to)합니다. 이 서비스는 애플리케이션에 필요한 모든 종속성(dependencies)을 가져오고 대부분의 설정을 자동으로 수행합니다.

  2. Gradle 또는 Maven과 사용하려는 언어를 선택합니다. 이 가이드에서는 Java를 선택했다고 가정합니다.

  3. 종속성(Dependencies)을 클릭 하고 Spring Web 을 선택하십시오.

  4. 생성(Generate) 을 클릭 합니다.

  5. 선택 사항으로 구성된(configured with your choices.) 웹 응용 프로그램의 아카이브인 결과 ZIP 파일을 다운로드합니다.

If your IDE has the Spring Initializr integration, you can complete this process from your IDE.

You can also fork the project from Github and open it in your IDE or other editor.



4. Set up a Spring Boot Application

4.1. simple application

Now you can create a simple application:

src/main/java/hello/Application.java

package hello;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class Application {

  @RequestMapping("/")
  public String home() {
    return "Hello Docker World";
  }

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }

}
  • 코드 설명 :

    • by Spring MVC to handle web requests.
      The class is flagged as a @SpringBootApplication and as a @RestController, meaning that it is ready for use

    • @RequestMapping maps_ / to the _home() method, which sends a

    • Hello World response.

    • The main() method
      uses Spring Boot’s SpringApplication.run() method to launch an application.


4.2. run the application

  • 실행
    Now we can run the application without the Docker container (that is, in the host OS):
    이제 Docker 컨테이너 없이(즉, 호스트 OS에서) 애플리케이션을 실행할 수 있습니다.

    • If you use Gradle, run the following command:
      ./gradlew build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar
    • If you use Maven, run the following command:
      ./mvnw package && java -jar target/gs-spring-boot-docker-0.1.0.jar
  • 출력
    Then go to localhost:8080 to see your “Hello Docker World” message.



5. Containerize It (컨테이너화)

  • 컨테이너화

    • Docker에는 이미지의 "계층"을 지정( layers specify )하는 데 사용 하는 간단한 "Dockerfile" 파일 형식이 있습니다.
    • Spring Boot 프로젝트에서 다음 Dockerfile을 생성합니다.

Example 1. Dockerfile

  • Command Form
FROM openjdk:8-jdk-alpine
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
  • 속성
- 1. FROM :
 ㄴ 이 Dockerfile은 매우 간단하지만 Java와 JAR 파일만 있으면( just Java and a JAR file ) 아무 장식 없이 Spring Boot 앱을 실행하는 데 필요한 모든 것입니다
- 2. ARG :
ㄴ 빌드는 애플리케이션을 실행할 스프링 사용자와 스프링 그룹을 생성합니다. 
- 3. COPY :
ㄴ 그런 다음 app.jar로 실행되는 **컨테이너에 COPY 프로젝트에 JAR 파일을 복사 합니다.
- 4. ENTRYPOINT : 
ㄴ ENTRYPOINT Java 프로세스를 래핑하는 셸이 없도록 Dockerfile의 배열 형식을 사용합니다. 
Docker에 대한 주제 가이드 는 이 주제에 대해 더 자세히 설명합니다.
  • step1-1. 플러그인별 컨테이너화 명령

    • If you use Gradle, you can run it with the following command:
      docker build --build-arg JAR_FILE=build/libs/\*.jar -t springio/gs-spring-boot-docker
    • If you use Maven, you can run it with the following command:
      docker build -t springio/gs-spring-boot-docker .
  • step1-2. 이 명령은 이미지를 빌드하고 로 태그를 지정(tags builds)합니다
    springio/gs-spring-boot-docker.

To reduce Tomcat startup time, we used to add a system property pointing to /dev/urandom as a source of entropy. This is not necessary anymore with JDK 8 or later.

사용자 권한으로 애플리케이션을 실행하면 일부 위험을 완화하는 데 도움이 됩니다(see, for example,: StackExchange의 스레드 참조 ). 따라서 중요한 개선 사항 Dockerfile은 루트가 아닌 사용자로 응용 프로그램을 실행하는 것입니다.


Example 2. Dockerfile

FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
ARG JAR_FILE=target/*.jar
${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
  • step 2-1-1. 출력 확인
    애플리케이션을 빌드하고 실행할 때 애플리케이션 시작 로그에서 사용자 이름을 볼 수 있습니다.
    docker build -t springio/gs-spring-boot-docker .
    docker run -p 8080:8080 springio/gs-spring-boot-docker 
  • step 2-1-2. 출력 확인
    started by첫 번째 INFO로그 항목 에 유의하십시오 .
    :: Spring Boot ::        (v2.2.1.RELEASE)

    2020-04-23 07:29:41.729  INFO 1 --- [main] hello.Application                        : Starting Application on b94c86e91cf9 with PID 1 (/app started by spring in /)
    ...
  • 리팩토리 가능성 및 필요성
    ㄴ 1. 또한 Spring Boot fat JAR 파일에는 종속성과 애플리케이션 리소스가 명확하게 분리되어 있으며 이 사실을 사용하여 성능을 개선할 수 있습니다. 핵심은 컨테이너 파일 시스템에 레이어를 만드는 것입니다.
    ㄴ 2. 레이어는 빌드 시와 런타임(대부분의 런타임에서) 모두에 캐시되므로 가장 자주 변경되는 리소스(일반적으로 애플리케이션 자체의 클래스 및 정적 리소스 static resources)가 더 느리게 변경되는 리소스 다음 에 레이어되기를 원합니다 .
    ㄴ 3. 따라서 Dockerfile의 약간 다른 구현(static resources)을 사용합니다.

Example 3. Dockerfile

FROM openjdk:8-jdk-alpine
RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring
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"]
  • step 3-1. 저장위치 지정
    이 Dockerfile에는 DEPENDENCY지방 JAR의 압축을 푼 디렉토리를 가리키는 매개변수(pointing DEPENDENCY parameter)가 있습니다.
    • 부가 설명 1.
      1. If we get that right, it already contains a BOOT-INF/lib directory with the dependency JARs in it, and a BOOT-INF/classes directory with the application classes in it.
      2. Notice that we use the application’s own main class: hello.Application. (This is faster than using the indirection provided by the fat JAR launcher.)
        우리는 애플리케이션의 자체 메인 클래스를 사용합니다:
        . (이는 팻 JAR 런처에서 제공하는 간접 참조를 사용하는 것보다 빠릅니다.)
    • To use the DEPENDENCY parameter with Gradle, run the following command:
      mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
    • To use the DEPENDENCY parameter with Maven, run the following command:
      mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)

  • 의존성 주의사항
    1. Exploding the JAR file can result in the classpath order being different at runtime. A well-behaved and well-written application should not care about this, but you may see behavior changes if the dependencies are not carefully managed.
    2. If you use boot2docker, you need to run it first before you do anything with the Docker command line or with the build tools (it runs a daemon process that handles the work for you in a virtual machine).
  • step 3-2. 디렉토리 매개변수 지정
    • From a Gradle build, you need to add the explicit build arguments in the Docker command line:
      docker build --build-arg DEPENDENCY=build/dependency -t springio/gs-spring-boot-docker .
    • To build the image in Maven, you can use a simpler Docker command line:
      docker build -t springio/gs-spring-boot-docker .

Of course, if you use only Gradle, you could change the Dockerfile to make the default value of DEPENDENCY match the location of the unpacked archive.

  • Docker 명령줄을 사용하여 빌드하는 대신 빌드 플러그인을 사용할 수 있습니다.
    ㄴ Spring Boot는 자체 빌드 플러그인을 사용하여 Maven 또는 Gradle에서 컨테이너 빌드를 지원합니다.
  • Google 에는 Maven 및 Gradle 플러그인이 포함된 Jib 이라는 오픈 소스 도구도 있습니다.
    ㄴ 아마도 이 접근 방식에서 가장 흥미로운 점은 Dockerfile을 필요로 하지않습니다.
    docker build 에서 가져온 것과 동일한 표준 컨테이너 형식을 사용하여 이미지를 빌드할 수 있습니다
    ㄴ 또한 도커가 설치되지 않은 환경에서도 작동할 수 있습니다(빌드 서버에서는 일반적이지 않음).

By default, the images generated by the default buildpacks do not run your application as root. Check the configuration guide for Gradle or Maven for how to change the default settings.
기본적으로 기본 빌드팩에서 생성된 이미지는 애플리케이션을 루트로 실행하지 않습니다. 기본 설정을 변경하는 방법 은 Gradle 또는 Maven 의 구성 가이드를 확인하세요 .



6. Build a Docker Image with Gradle

  • step 6-1. Gradle로 Docker 이미지 빌드
    • You can build a tagged docker image with Gradle in one command:
      ./gradlew bootBuildImage --imageName=springio/gs-spring-boot-docker
    • Build a Docker Image with Maven
      빠르게 시작하려면 다음을 변경하지 않고 Spring Boot 이미지 생성기를 실행할 수 있습니다 pom.xml( Dockerfile, 여전히 있는 경우 무시됨).
      ./mvnw spring-boot:build-image -Dspring-boot.build-image.imageName=springio/gs-spring-boot-docker

  • step 6-2. To push to a Docker registry,
    ㄴ you need to have permission to push, which you do not have by default.
    Docker 레지스트리에 푸시하려면 기본적으로 없는 푸시 권한이 있어야 합니다.
    ㄴ. Change the image prefix to your own Dockerhub ID and docker login to make sure you are authenticated before you run Docker.
    이미지 접두사를 고유한 Dockerhub ID로 변경하고 docker loginDocker를 실행하기 전에 인증되었는지 확인하십시오.


7. After the Push

  • step 7-1. 도커 푸쉬
    이미지 접두사를 고유한 Dockerhub ID로 변경하고 docker loginDocker를 실행하기 전에 인증되었는지 확인하십시오.
    1. docker push 예제는 실패합니다 (Dockerhub의 "springio" 조직에 속하지 않는 한).
    2. 그러나 자신의 도커 ID와 일치하도록 구성을 변경하면 성공해야 합니다.
      그러면 새로운 태그가 지정되고 배포된 이미지가 생성됩니다.
    3. 로컬로 빌드된 도커 이미지를 실행하기 위해 도커에 등록하거나 아무 것도 게시할 필요가 없습니다.
    4. Docker로 빌드한 경우 (명령줄 또는 Spring Boot에서) 여전히 로컬로 태그가 지정된 이미지가 있으며 다음과 같이 실행할 수 있습니다.
       $ docker run -p 8080:8080 -t springio/gs-spring-boot-docker
       Container memory limit unset. Configuring JVM for 1G container.
       Calculated JVM Memory Configuration: -XX:MaxDirectMemorySize=10M -XX:MaxMetaspaceSize=86381K -XX:ReservedCodeCacheSize=240M -Xss1M -Xmx450194K (Head Room: 0%, Loaded Class Count: 12837, Thread Count: 250, Total Memory: 1073741824)
       ....
       2015-03-31 13:25:48.035  INFO 1 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
       2015-03-31 13:25:48.037  INFO 1 --- [           main] hello.Application                        : Started Application in 5.613 seconds (JVM running for 7.293)

The CF memory calculator is used at runtime to size the JVM to fit the container.
CF 메모리 계산기는 런타임에 컨테이너에 맞게 JVM의 크기를 조정하는 데 사용됩니다.

  • step 7-1. 출력 확인 :
    The application is then available on http://localhost:8080 (visit that and it says, “Hello Docker World”).
    그런 다음 애플리케이션은 http://localhost:8080 에서 사용할 수 있습니다 (방문하면 "Hello Docker World"라고 표시됨).
  • boot2docker가 있는 Mac을 사용하는 경우 > 출력 예시.
    boot2docker가 있는 Mac을 사용하는 경우, 일반적으로 시작 시 다음과 같이 표시됩니다 :
Docker client to the Docker daemon, please set:
    export DOCKER_CERT_PATH=/Users/gturnquist/.boot2docker/certs/boot2docker-vm
    export DOCKER_TLS_VERIFY=1
    export DOCKER_HOST=tcp://192.168.59.103:2376

애플리케이션을 보려면 localhost 대신 DOCKER_HOST의 IP 주소를 방문해야 합니다. 이 경우 VM의 공개 IP인 https://192.168.59.103:8080을 방문해야 합니다 .

  • 실행 중일 때, 출력 예시

    $ docker ps
    CONTAINER ID        IMAGE                                   COMMAND                  CREATED             STATUS              PORTS                    NAMES
    81c723d22865        springio/gs-spring-boot-docker:latest   "java -Djava.secur..."   34 seconds ago      Up 33 seconds       0.0.0.0:8080->8080/tcp   goofy_brown  ```
    
  • 컨테이너 ID로 종료 명령.

    docker stop goofy_brown 
    81c723d22865 
  • 컨테이너 삭제.
    (/var/lib/docker작업이 끝나면 컨테이너를 삭제할 수도 있습니다. 파일 시스템 어딘가에 유지됨).
    docker rm goofy_brown


8. Using Spring Profiles

  • step 8-1. 프로파일 환경설정 및 프로파일로 실행
    Spring 프로필로 새로 생성된 Docker 이미지를 실행하는 것은 환경 변수를 Docker 실행 명령( prod프로필용)에 전달하는 것만큼 쉽습니다 .
    • You can do the same for the prod profile:
      docker run -e "SPRING_PROFILES_ACTIVE=prod" -p 8080:8080 -t springio/gs-spring-boot-docker
    • You can do the same for the dev profile:
      docker run -e "SPRING_PROFILES_ACTIVE=dev" -p 8080:8080 -t springio/gs-spring-boot-docker


9. Debugging the Application in a Docker Container

  • 디버깅
    애플리케이션을 디버그하려면 JPDA Transport를 사용할 수 있습니다 . 컨테이너를 원격 서버처럼 취급(remote server treat)합니다.
    ㄴ 이 기능을 활성화하려면 JAVA_OPTS변수 에 Java 에이전트 설정을 전달 하고 컨테이너 실행 중에 에이전트의 포트를 localhost에 매핑합니다.
    ㄴ Mac용 Docker를 사용하면 블랙 매직 사용 없이 IP로 컨테이너에 액세스할 수 없기 때문에 제한이 있습니다.(lack magic usage)
    • docker run -e "JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=n" -p 8080:8080 -p 5005:5005 -t springio/gs-spring-boot-docker

10. Summary

Congratulations!

  • You have created a Docker container for a Spring Boot application!
  • By default, Spring Boot 애플리케이션은 컨테이너 내부의 포트 8080에서 실행되며
  • -p명령줄에서 를 사용하여 호스트의 동일한 포트에 매핑했습니다 .

See Also

다음 가이드도 도움이 될 수 있습니다.

  • Spring MVC로 웹 콘텐츠 제공

  • 스프링 부트로 애플리케이션 빌드

  • Docker를 사용한 Spring Boot에 대한 주제 가이드 (이 가이드보다 더 깊이 있음)

0개의 댓글