Chapter 5. Packaging OCI Images

플러그인은 Cloud Native Buildpacks(CNB)를 사용하여 jar 또는 war 파일에서 OCI 이미지를 생성할 수 있다. bootBuildImage 태스크를 사용하여 이미지를 빌드할 수 있다.

보안상의 이유로 이미지는 루트가 아닌 사용자로 빌드 및 실행된다. 자세한 내용은 CNB 사양을 참조해보자.

태스크는 java 또는 war 플러그인이 적용될 때 자동으로 생성되며 BootBuildImage의 인스턴스이다.

5.1. Docker Daemon

bootBuildImage 태스크에는 도커 데몬에 대한 액세스 권한이 필요하다. 기본적으로, 로컬 연결을 통해 도커 데몬과 통신한다. 이는 구성 없이 지원되는 모든 플랫폼에서 도커 엔진과 함께 작동한다.

환경 변수를 설정하여 bootBuildImage 태스크를 대체 로컬(alternative local) 또는 원격 연결을 사용하도록 구성할 수 있다. 다음 표는 환경 변수와 해당 값을 보여준다:

Environment variableDescription
DOCKER_HOST도커 데몬의 호스트 및 포트를 포함하는 URL - 예를들어 tcp://192.168.99.100:2376
DOCKER_TLS_VERIFY1로 설정된 경우 보안 HTTPS 프로토콜 활성화(선택 사항)
DOCKER_CERT_PATHHTTPS용 인증서 및 키 파일의 경로(DOCKER_TLS_VERIFY=1인 경우 필수, 그렇지 않은 경우 무시됨)

플러그인 구성에서 docker 프로퍼티를 사용하여 도커 데몬 연결 정보를 제공할 수도 있다. 다음 표에는 사용 가능한 프로퍼티가 요약되어 있다:

PropertyDescription
host도커 데몬의 호스트 및 포트를 포함하는 URL - 예를들어 tcp://192.168.99.100:2376
tlsVerifytrue로 설정된 경우 보안 HTTPS 프로토콜 활성화(선택 사항)
certPathHTTPS용 인증서 및 키 파일의 경로(tlsVerifytrue인 경우 필요, 그렇지 않은 경우 무시됨)
bindHostToBuilderWhen true, the value of the host property will be provided to the container that is created for the CNB builder (optional)

자세한 내용은 예제를 참조해보자.

5.2. Docker Registry

builder 또는 runImage 프로퍼티에 지정된 도커 이미지가 인증이 필요한 프라이빗(private) 도커 이미지 레지스트리에 저장되는 경우, docker.builderRegistry 프로퍼티를 사용하여 인증 크리덴셜(credentials)를 제공할 수 있다.

프로퍼티는 사용자 인증 또는 ID 토큰 인증을 위해 제공된다. 지원되는 인증 메소드에 대한 자세한 내용은 이미지를 저장하는 데 사용되는 도커 레지스트리에 대한 설명서를 참조하자.

다음 표는 docker.builderRegistrydocker.publishRegistry에 사용 가능한 프로퍼티가 요약되어 있다.

PropertyDescription
username도커 이미지 레지스트리 사용자의 이름. 사용자 인증에 필수.
password도커 이미지 레지스트리 사용자의 비밀번호. 사용자 인증에 필수.
url도커 이미지 레지스트리의 주소. 사용자 인증을 위한 선택 사항.
email도커 이미지 레지스트리 사용자의 이메일 주소. 사용자 인증을 위한 선택 사항.
token도커 이미지 레지스트리 사용자의 ID 토큰. 토큰 인증에 필수.

자세한 내용은 예제를 참조해보자.

5.3. Image Customizations

플러그인은 빌더를 호출하여 이미지 생성을 조율(orchestrate)한다. 빌더에는 애플리케이션을 검사하여, 생성된 이미지에 영향을 줄 수 있는 여러 빌드팩(Buildpack)이 포함되어 있다. 기본적으로, 플러그인은 빌더 이미지를 선택한다. 생성된 이미지 이름은 프로젝트 프로퍼티에서 유추된다.

태스크 프로퍼티를 사용하여 빌더가 프로젝트에서 작동하는 방식을 구성할 수 있다. 다음 표에는 사용 가능한 프로퍼티와 기본값이 요약되어 있다:

PropertyCommand-line optionDescriptionDefault value
builder--builder사용할 빌더 이미지 이름.paketobuildpacks/builder:base
runImage--runImage사용할 실행 이미지 이름.빌더 메타데이터에 지정된 실행 이미지 기본값 없음.
imageName--imageName생성된 이미지 이름.docker.io/library/${project.name}:${project.version}
pullPolicy--pullPolicy빌더를 끌어오고 레지스트리에서 이미지를 실행할 시기를 결정하는 데 사용되는 정책이다. 허용값은 ALWAYS, NEVER, IF_NOT_PRESENT 이다.ALWAYS
environment 빌더에 전달해야 하는 환경 변수이다. 
buildpacks 빌더가 이미지를 빌드할 때 사용해야 하는 빌드팩이다. 빌더에 포함된 기본 빌드팩을 오버라이드(overriding)하여 지정된 빌드팩만 사용된다. 빌드팩 레퍼런스는 다음 형식 중 하나여야 한다.:

• 빌더의 빌드팩 - [urn:cnb:builder:]<buildpackID>[@<version>]

• 파일 시스템의 디렉토리에 있는 빌드팩 - [file://]<path>

• 파일 시스템의 gzip으로 압축된 tar(.tgz) 파일의 빌드팩 - [file://]<path>/<file name>

• OCI 이미지의 빌드팩 - [docker://]<host>/<repo>[:<tag>][@<digest>]
기본값 없음, 빌더가 빌더에 포함된 빌드팩을 사용해야 함을 나타낸다.
bindings 이미지 빌드할 때 빌더 컨테이너에 마운트해야 하는 볼륨 바인드 마운트. 바인딩은 빌더 컨테이너를 생성할 때 구문 분석 및 검증되지 않은 상태로 도커에 전달된다. 바인딩은 다음 형식 중 하나여야 한다:

<host source path>:<container destination path>[:<options>]

<host volume name>:<container destination path>[:<options>]

<options>에는 다음과 같은 내용이 포함될 수 있다.:

• 컨테이너에서 볼륨을 읽기-전용으로 마운트하기 위해 ro 옵션을 사용한다.

• 컨테이너에서 볼륨을 읽기 및 쓰기가 가능하도록 마운트하기 위해 rw 옵션을 사용한다.

• 옵션 이름과 해당 값을 포함하는 키-값 쌍을 지정하기 위해 volume-opt=key=value 형식을 사용한다.
 
network--network빌더 컨테이너가 구성될 때 사용할 네트워크 드라이버이다. 제공된 값은 빌더 컨테이너를 생성할 때 도커에게 유효성을 검증받지 않고 전달된다. 
cleanCache--cleanCache빌드하기 전에 캐시를 정리할지 여부이다.false
verboseLogging 빌더 작업에 대한 자세한 로깅을 활성화한다.false
publish--publishImage생성된 이미지를 도커 레지스트리에 게시할지 여부이다.false
tags 생성된 이미지에 적용할 하나 이상의 추가 태그 목록입니다. 태그 옵션에 제공하는 값은 [image name]:[tag] or [repository]/[image name]:[tag] 형식의 완전한 이미지 레퍼런스여야 한다. 
buildCache 빌드팩에서 생성되고 이미지 빌드 프로세스에서 사용되는 레이어가 포함된 캐시.이미지 이름에서 파생된 이름을 가진, 도커 데몬의 명명된 볼륨이다.
launchCache 빌드팩에서 생성되고 이미지 시작 프로세스에서 사용되는 레이어가 포함된 캐시.이미지 이름에서 파생된 이름을 가진, 도커 데몬의 명명된 볼륨이다.

플러그인은 JavaPlugin의 targetCompatibility 프로퍼티을 사용하여 프로젝트의 대상 자바 호환성(compatibility)을 감지한다. 기본 Paketo 빌더 및 빌드팩을 사용하는 경우, 플러그인은 동일한 자바 버전을 설치하도록 빌드팩에 지시한다. 빌더 구성 예제에 표시된 대로 이 동작작을 오버라이드할 수 있다.

5.4. Examples

5.4.1. Custom Image Builder and Run Image

이미지를 생성하는 데 사용되는 빌더(builder) 또는 빌드된 이미지를 시작하는 데 사용되는 실행 이미지(run image)를 사용자 지정해야 하는 경우, 다음 예와 같이 작업을 구성한다:

Groovy

  tasks.named("bootBuildImage") {
    builder = "mine/java-cnb-builder"
    runImage = "mine/java-cnb-run"
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    builder = "mine/java-cnb-builder"
    runImage = "mine/java-cnb-run"
  }

위 구성은 이름이 mine/java-cnb-builder이고 태그가 latest인 빌더 이미지와 이름이 mine/java-cnb-run이고 태그가 latest인 실행 이미지를 사용한다. 빌더 및 실행 이미지는, 이 예제와 같이 명령줄에서도 지정할 수 있다:

  $ gradle bootBuildImage --builder=mine/java-cnb-builder --runImage=mine/java-cnb-run

5.4.2. Builder Configuration

만약 빌더가 구성 옵션을 노출시킨다면, environment 프로퍼티를 사용하여 설정할 수 있다. 다음은 빌드 시 Paketo 자바 빌드팩에서 사용하는 JVM 버전 구성 예시이다:

Groovy

  tasks.named("bootBuildImage") {
    environment = ["BP_JVM_VERSION" : "8.*"]
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    environment = mapOf("BP_JVM_VERSION" to "8.*")
  }

빌더가 실행되는 도커 데몬과 빌드팩이 아티팩트(artifacts)를 다운로드하는 네트워크 위치 사이에 네트워크 프록시가 있는 경우, 프록시를 사용하도록 빌더를 구성해야 한다. Paketo 빌더를 사용하는 경우 다음 예제와 같이 HTTPS_PROXY 및/또는 HTTP_PROXY 환경 변수를 설정하여 이를 수행할 수 있다.

Groovy

  tasks.named("bootBuildImage") {
    environment = [
      "HTTP_PROXY" : "http://proxy.example.com",
      "HTTPS_PROXY": "https://proxy.example.com"
    ] 
  }

Kotlin

tasks.named<BootBuildImage>("bootBuildImage") {
      environment = mapOf(
        "HTTP_PROXY" to "http://proxy.example.com",
        "HTTPS_PROXY" to "https://proxy.example.com"
      )
}

5.4.3. Runtime JVM Configuration

Paketo 자바 빌드팩은 JAVA_TOOL_OPTIONS 환경 변수를 설정하여 JVM 런타임 환경을 구성한다. 제공된-빌드팩 JAVA_TOOL_OPTIONS 값을 수정하여 애플리케이션 이미지가 컨테이너에서 실행될 때 JVM 런타임 동작을 사용자 정의할 수 있다. 이미지에 저장되며 모든 배포에 적용해야 하는 환경 변수 수정 사항은 Paketo 문서에 설명된 대로 설정할 수 있으며 다음 예제에 표시된다:

Groovy

  tasks.named("bootBuildImage") {
    environment = [
      "BPE_DELIM_JAVA_TOOL_OPTIONS" : " ",
      "BPE_APPEND_JAVA_TOOL_OPTIONS" : "-XX:+HeapDumpOnOutOfMemoryError"
    ] 
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    environment = mapOf(
      "BPE_DELIM_JAVA_TOOL_OPTIONS" to " ",
      "BPE_APPEND_JAVA_TOOL_OPTIONS" to "-XX:+HeapDumpOnOutOfMemoryError"
    )
  }

5.4.4. Custom Image Name

기본적으로, 이미지 이름은 docker.io/library/${project.name}:${project.version}과 같이, 프로젝트 nameversion에서 유추된다. 다음 예제와 같이, 태스크 프로퍼티을 설정하여 이름을 제어할 수 있다:

Groovy

  tasks.named("bootBuildImage") {
    imageName = "example.com/library/${project.name}"
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    imageName = "example.com/library/${project.name}"
  }

위 구성은 명시적으로 태그를 제공하지 않으므로 latest가 사용된다. ${project.version}을 사용하여, 빌드에서 사용 가능한 프로퍼티 또는 하드코딩으로 태그를 지정할 수도 있다.

아래 예제처럼, 이미지 이름은 명령줄에서도 지정할 수 있다:

  $ gradle bootBuildImage --imageName=example.com/library/my-app:v1

5.4.5. Buildpacks

기본적으로, 빌더는 빌더 이미지에 포함된 빌드팩을 사용하고 미리 정의된 순서대로 적용한다. 빌더에 포함되지 않은 빌드팩을 적용하거나 포함된 빌드팩의 순서를 변경하기 위해 대체 빌드팩 세트를 제공할 수 있다. 하나 이상의 빌드팩이 제공되면, 지정된 빌드팩만 적용된다.

다음 예제에서는 빌더가 .tgz 파일에 패키징된 사용자 정의 빌드팩을 사용하고, 빌더에 포함된 빌드팩을 사용하도록 지시한다.

Groovy

  tasks.named("bootBuildImage") {
    buildpacks = ["file:///path/to/example-buildpack.tgz", "urn:cnb:builder:paketo-buildpacks/java"]
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    buildpacks = listOf("file:///path/to/example-buildpack.tgz", "urn:cnb:builder:paketo-buildpacks/java")
  }

빌드팩은 아래 표시된 양식 중 하나로 지정할 수 있다.

CNB 빌더에 있는 빌드팩 (빌더에 buildpack-id와 일치하는 빌드팩이 하나만 있는 경우 버전을 생략할 수 있다.):

  • urn:cnb:builder:buildpack-id
  • urn:cnb:builder:buildpack-id@0.0.1
  • buildpack-id
  • buildpack-id@0.0.1

빌드팩 콘텐츠가 포함된 디렉토리 경로 (윈도우는 지원하지 않음):

  • file:///path/to/buildpack/
  • /path/to/buildpack/

빌드팩 콘텐츠가 포함된 gzip으로 압축된 tar 파일의 경로:

  • file:///path/to/buildpack.tgz
  • /path/to/buildpack.tgz

패키지 빌드팩을 포함하는 OCI 이미지:

  • docker://example/buildpack
  • docker:///example/buildpack:latest
  • docker:///example/buildpack@sha256:45b23dee08...
  • example/buildpack
  • example/buildpack:latest
  • example/buildpack@sha256:45b23dee08...

5.4.6. Image Publishing

생성된 이미지는 publish 옵션을 활성화하여 도커 레지스트리에 게시할 수 있다.

도커 레지스트리에 인증이 필요한 경우, docker.publishRegistry 프로퍼티을 사용하여 크리덴셜(credentials)을 구성할 수 있다. 도커 레지스트리에 인증이 필요하지 않은 경우, docker.publishRegistry 구성을 생략할 수 있다.

이미지가 게시될 레지스트리는 이미지 이름(아래 예제에서는 docker.example.com)의 레지스트리 파트(part)에 의해 결정된다. docker.publishRegistry 크리덴셜을 구성하고 url 프로퍼티를 포함하는 경우, 이 값은 레지스트리로 전달되지만 게시되는 레지스트리 위치를 결정하는 데 사용되지 않는다.

Groovy

  tasks.named("bootBuildImage") {
    imageName = "docker.example.com/library/${project.name}"
    publish = true
    docker {
      publishRegistry {
        username = "user"
        password = "secret"
      } 
    }
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    imageName = "docker.example.com/library/${project.name}"
    isPublish = true
    docker {
      publishRegistry {
        username = "user"
        password = "secret"
      } 
    }
  }

publish 옵션은 아래 예제와 같이, 명령줄에서도 지정할 수 있다.

  $ gradle bootBuildImage --imageName=docker.example.com/library/my-app:v1 --publishImage

5.4.7. Builder Cache Configuration

CNB 빌더는 이미지를 빌드하고 시작할 때 사용되는 레이어를 캐시(cache)한다. 기본적으로, 이러한 캐시는 도커 데몬의 명명된 볼륨으로 저장되며 이 볼륨의 명칭은 대상 이미지의 전체 이름에서 파생된다. 이미지 이름이 자주 변경되는 경우(예: 프로젝트 버전이 이미지 이름의 태그로 사용되는 경우) 캐시가 자주 무효화될 수 있다.

다음 예와 같이 대체 이름을 사용하여 캐시 생명 주기를 더 많이 제어할 수 있도록 캐시 볼륨을 구성할 수 있다:

Groovy

  tasks.named("bootBuildImage") {
    buildCache {
      volume {
        name = "cache-${rootProject.name}.build"
      } 
    }
    launchCache {
      volume {
        name = "cache-${rootProject.name}.launch"
      }
    } 
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    buildCache {
      volume {
        name = "cache-${rootProject.name}.build"
      } 
    }
    launchCache {
      volume {
        name = "cache-${rootProject.name}.launch"
      }
    } 
  }

5.4.8. Docker Configuration Docker Configuration for minikube

플러그인은 기본 로컬 연결 대신 미니큐브(minikube)에서 제공하는 도커 데몬과 통신할 수 있다.

리눅스 및 맥OS에서는, 미니큐브가 시작된 후 eval $(minikube docker-env) 명령을 사용하여 환경 변수를 설정할 수 있다.

다음 예제에 표시된 것처럼 연결의 세부 정보를 제공하여 미니큐브 데몬을 사용하도록 플러그인을 구성할 수도 있다:

Groovy

  tasks.named("bootBuildImage") {
    docker {
      host = "tcp://192.168.99.100:2376"
      tlsVerify = true
      certPath = "/home/user/.minikube/certs"
    } 
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    docker {
      host = "tcp://192.168.99.100:2376"
      isTlsVerify = true
      certPath = "/home/user/.minikube/certs"
    } 
  }

Docker Configuration for podman

플러그인은 파드맨(podman) 컨테이너 엔진과 통신할 수 있다.

다음 예에 표시된 것처럼 연결의 세부 정보를 제공하여 파드맨 로컬 연결을 사용하도록 플러그인을 구성할 수 있다:

Groovy

  tasks.named("bootBuildImage") {
    docker {
      host = "unix:///run/user/1000/podman/podman.sock"
      bindHostToBuilder = true
    }
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    docker {
      host = "unix:///run/user/1000/podman/podman.sock"
      isBindHostToBuilder = true
    }
  }

파드맨 CLI가 설치된 상태에서 podman info --format='' 명령을 사용하여 위 예제에 표시된 docker.host 구성 프로퍼티의 값을 가져올 수 있다.

Docker Configuration for Authentication

빌더 또는 실행 이미지가 사용자 인증을 지원하는 프라이빗(private) 도커 레지스트리에 저장되어 있는 경우, 다음 예제와 같이 docker.builderRegistry 프로퍼티를 사용하여 인증 세부 정보를 제공할 수 있다:

Groovy

  tasks.named("bootBuildImage") {
    docker {
      builderRegistry {
        username = "user"
        password = "secret"
        url = "https://docker.example.com/v1/"
        email = "user@example.com"  
      } 
    }
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    docker {
      builderRegistry {
        username = "user"
        password = "secret"
        url = "https://docker.example.com/v1/"
        email = "user@example.com"
      } 
    }
  }

빌더 또는 실행 이미지가 토큰 인증을 지원하는 프라이빗 도커 레지스트리에 저장되어 있는 경우 다음 예제와 같이 docker.builderRegistry를 사용하여 토큰 값을 제공할 수 있다:

Groovy

  tasks.named("bootBuildImage") {
      docker {
        builderRegistry {
          token = "9cbaf023786cd7..."
      }     
    }
  }

Kotlin

  tasks.named<BootBuildImage>("bootBuildImage") {
    docker {
      builderRegistry {
        token = "9cbaf023786cd7..."
      } 
    }
  }