더 간소화된 컨테이너 빌드

이 페이지에서는 더 간소화된 Docker 이미지 빌드 방법을 설명합니다.

간소화된 컨테이너 빌드

애플리케이션을 컨테이너화할 때 런타임에 필요하지 않은 파일(예: 빌드타임 종속 항목 및 중간 파일)이 실수로 컨테이너 이미지에 포함될 수 있습니다. 이러한 불필요한 파일로 인해 컨테이너 이미지 크기가 커져 이미지가 Docker 레지스트리와 컨테이너 런타임 사이를 이동할 때 시간과 비용이 추가로 발생할 수 있습니다.

컨테이너 이미지 크기를 줄이려면 애플리케이션 빌드 단계를 애플리케이션을 빌드하는 데 사용되는 도구와 함께 런타임 컨테이너 어셈블리 단계에서 분리하세요.

Cloud Build는 일련의 Docker 컨테이너에 Git, Docker, Google Cloud CLI와 같은 일반적인 개발자 도구를 제공합니다. 이러한 도구를 사용하여 애플리케이션을 빌드하는 단계와 최종 런타임 환경을 어셈블하는 단계를 구분하여 빌드 구성 파일을 정의하세요.

예를 들어 소스 코드, 애플리케이션 라이브러리, 빌드 시스템, 빌드 시스템 종속 항목, JDK와 같은 파일이 필요한 자바 애플리케이션을 빌드하는 경우 다음과 같은 Dockerfile이 있을 수 있습니다.

FROM java:8

COPY . workdir/

WORKDIR workdir

RUN GRADLE_USER_HOME=cache ./gradlew buildDeb -x test

RUN dpkg -i ./gate-web/build/distributions/*.deb

CMD ["/opt/gate/bin/gate"]

위의 예시에서 패키지를 만드는 데 사용되는 Gradle은 작동에 필요한 여러 라이브러리를 다운로드합니다. 이러한 라이브러리는 패키지 빌드에 필수적이지만 런타임에는 필요하지 않습니다. 모든 런타임 종속 항목은 패키지에 번들로 제공됩니다.

Dockerfile의 각 명령어는 컨테이너에 새 레이어를 만듭니다. 데이터가 해당 레이어에서 생성되고 동일한 명령어에서 삭제되지 않으면 해당 공간을 복구할 수 없습니다. 여기에서 Gradle은 빌드를 수행하기 위해 수백 MB의 라이브러리를 cache 디렉터리에 다운로드하지만 라이브러리가 삭제되지 않습니다.

빌드를 수행하는 보다 효율적인 방법은 Cloud Build를 사용하여 애플리케이션 빌드와 런타임 레이어 빌드를 구분하는 것입니다.

다음 예에서는 자바 애플리케이션을 빌드하는 단계와 런타임 컨테이너를 어셈블하는 단계를 구분합니다.

YAML

  1. 애플리케이션 빌드: cloudbuild.yaml에서 애플리케이션 빌드 단계를 추가합니다.

    다음 코드는 자바 코드가 포함된 java:8 이미지 빌드 단계를 추가합니다.

    steps:
    
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    
    
  2. 런타임 컨테이너 어셈블: cloudbuild.yaml에서 런타임 컨테이너를 어셈블하는 단계를 추가합니다.

    다음 코드는 런타임 컨테이너를 어셈블하는 gcr.io/cloud-builders/docker라는 단계를 추가합니다. Dockerfile.slim이라는 별도의 파일에 런타임 컨테이너를 정의합니다.

    이 예시에서는 매우 간소화된 openjdk:8u111-jre-alpine이라는 Alpine Linux 기본 레이어를 사용합니다. 또한 애플리케이션을 빌드하는 데 필요했던 대규모의 JDK 대신 JRE가 포함되어 있습니다.

    cloudbuild.yaml
    
    steps:
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c',
             './gradlew gate-web:installDist -x test']
    
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest',
             '-f', 'Dockerfile.slim',
             '.'
      ]
    
    
    Dockerfile.slim
    
    FROM openjdk:8-jre-alpine
    
    COPY ./gate-web/build/install/gate /opt/gate
    
    CMD ["/opt/gate/bin/gate"]
    
  3. Docker 이미지 만들기: cloudbuild.yaml에서 이미지 생성을 위한 단계를 추가합니다.
    steps:
    - name: 'java:8'
      env: ['GRADLE_USER_HOME=cache']
      entrypoint: 'bash'
      args: ['-c', './gradlew gate-web:installDist -x test']
    - name: 'gcr.io/cloud-builders/docker'
      args: ['build',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA',
             '-t', 'gcr.io/$PROJECT_ID/$REPO_NAME:latest',
             '-f', 'Dockerfile.slim', '.']
    images:
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA'
    - 'gcr.io/$PROJECT_ID/$REPO_NAME:latest'
    

JSON

  1. 애플리케이션 빌드: cloudbuild.json에서 애플리케이션 빌드 단계를 추가합니다.

    다음 코드는 자바 코드 빌드를 위해 java:8이라는 단계를 추가합니다.

    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
    }
    
  2. 런타임 컨테이너 어셈블: cloudbuild.json에서 런타임 컨테이너를 어셈블하는 단계를 추가합니다.

    다음 코드는 런타임 컨테이너를 어셈블하는 gcr.io/cloud-builders/docker라는 단계를 추가합니다. Dockerfile.slim이라는 별도의 파일에 런타임 컨테이너를 정의합니다.

    이 예시에서는 매우 간소화된 openjdk:8u111-jre-alpine이라는 Alpine Linux 기본 레이어를 사용합니다. 또한 애플리케이션을 빌드하는 데 필요했던 대규모의 JDK 대신 JRE가 포함되어 있습니다.

    cloudbuild.json:
    
    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
                "build",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:latest",
                "-f",
                "Dockerfile.slim",
                "."
            ]
        }
        ],
    }
    
    Dockerfile.slim:
    
    FROM openjdk:8u111-jre-alpine
    
    COPY ./gate-web/build/install/gate /opt/gate
    
    CMD ["/opt/gate/bin/gate"]
    
  3. Docker 이미지 만들기: cloudbuild.json에서 이미지 생성을 위한 단계를 추가합니다.
    {
        "steps": [
        {
            "name": "java:8",
            "env": [
                "GRADLE_USER_HOME=cache"
            ],
            "entrypoint": "bash",
            "args": [
                "-c",
                "./gradlew gate-web:installDist -x test"
            ]
        },
        {
            "name": "gcr.io/cloud-builders/docker",
            "args": [
                "build",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
                "-t",
                "gcr.io/$PROJECT_ID/$REPO_NAME:latest",
                "-f",
                "Dockerfile.slim",
                "."
            ]
        }
        ],
        "images": [
            "gcr.io/$PROJECT_ID/$REPO_NAME:$COMMIT_SHA",
            "gcr.io/$PROJECT_ID/$REPO_NAME:latest"
        ]
    }