Search
Duplicate
📒

빌드방법

수업
Docker Container
주제
5 more properties
참고

Kaniko

NOTE
kaniko는 Dockerfile을 사용하여 이미지를 빌드하고 이를 레지스트리에 푸시하는 도구입니다.
Kaniko는 Docker와 동일하게 동작하지만 Docker Daemon이 필요없어 Docker에 대한 의존을 없애고, Docker로 인한 보안 이슈를 해결할 수 있습니다.
Kaniko 흐름도
1.
Dockerfile의 FROM 이미지(기본 이미지)의 파일 시스템을 추출합니다.
2.
Dockerfile의 명령을 순차적으로 실행하며 각 명령 후에 파일 시스템을 스냅샷 찍습니다.
3.
각 명령 후에 변경된 파일을 레이어로 추가하고 이미지 메타데이터를 업데이트합니다.
간단하게 정의하면 container image를 build(Dockerfile 활용)하는 도구.
그럼 기존 docker build 와 동일하지 않은가? 동일함. 차이점은?
Docker daemon이 필요없음 (docker 설치 불필요) 즉, docker 의존을 없애고, docker로 인한 보안이슈를 해결 가능
빌드 컨텍스트는 Docker daemon에 보내는 빌드 컨텍스트와 유사합니다. 이는 Dockerfile이 포함된 디렉토리로, Kaniko가 이미지를 빌드하는데 사용합니다.
ex) COPY 명령어는 빌드 컨텍스트 내의 파일을 참조해야 합니다.
빌드 컨텍스트를 Kaniko가 접근할 수 있는 위치에 저장해야 합니다.

Kaniko 기본 사용법

NOTE
Kaniko를 사용하기 위해서는 빌드 컨텍스트를 지정하고, 실행중인 Kaniko 인스턴스가 필요합니다.
빌드 컨텍스트는 Dockerfile이 포함된 디렉토리로 COPY 명령어가 빌드 컨텍스트 내 파일을 참조하는 것을 생각하면 됩니다. Kaniko가 이미지를 빌드하는데 사용합니다.
Kaniko는 빌드 컨텍스트를 위해 다양한 솔루션을 제공하고 있으며 사용하는 솔루션마다 접두사를 다르게 사용해야 합니다.
소스
접두사
예시
로컬 디렉토리
dir://
dir:///workspace
로컬 Tar Gz
tar://
tar:///path/to/context.tar.gz
표준 입력
tar://[stdin]
tar://stdin
GCS 버킷
gs://
gs://kaniko-bucket/path/to/context.tar.gz
S3 버킷
s3://
s3://kaniko-bucket/path/to/context.tar.gz
Azure Blob Storage
https://
Git 저장소
git://
git://github.com/acme/myproject.git#refs/heads/mybranch#<desired-commit-id>
빌드 컨텍스트를 독립적으로 관리하는 이유는 빌드 환경을 일관된게 유지할 수 있으며, 이는 동일한 Dockerfile을 사용하더라도 빌드 컨텍스트가 다르면 다른 이미지가 생성될 수 있습니다.
원격 저장소를 사용하는 만큼 데이터 전송을 최적화하고, 빌드 과정에서 필요한 파일만 포함함으로써 불필요한 데이터 전송을 줄이는데 도움을 줄 수 있습니다.
Kaniko를 실행하는 방법은 K8s에서도 가능하고, Docker를 사용할수도 있습니다.
docker run --rm -v $(pwd):/workspace \ gcr.io/kaniko-project/executor:latest \ --context /workspace \ # Kaniko Context --dockerfile /workspace/Dockerfile \ # Dockerfile 위치 --destination scofe/test:123\ # 푸시 위치 --build-arg MY_ARG=value \ # 인수지정 --cache=true \ # 캐시 여부 --cache-dir=/cache \ # 캐시 경로 --insecure \ # TLS를 사용하지 않고 이미지 푸시 --skip-tls-verify \ # TLS인증서를 검증하지 않고 이미지 푸시 --log-format=json \ # 로그 출력형식
Bash
복사
Context 사용예시
-context: 빌드 컨텍스트 경로를 지정합니다. 이 경로는 Dockerfile과 소스 코드가 있는 디렉토리입니다.
-dockerfile: 사용할 Dockerfile의 경로를 지정합니다.
-destination: 빌드한 이미지를 푸시할 Docker 레지스트리 경로를 지정합니다.
docker run \ -v $(pwd)/.docker/config.json:/kaniko/.docker/config.json:ro \ gcr.io/kaniko-project/executor:latest \ --dockerfile jenkins/spring_cicd/Dockerfile \ --destination "scofe/test:123" \ --context git://github.com/scofe97/infra_study.git#main \ --cache=true \ --cache-dir=/cache
Bash
복사
docker run \ -v $(pwd)/.docker/config.json:/kaniko/.docker/config.json:ro \ gcr.io/kaniko-project/executor:v1.21.0-debug \ --dockerfile workflow-api/Dockerfile \ --destination "scofe/test:1244" \ --context git://SimBoHyeon:ATBBn465CruZGqSGZxSAEcNsKf6j79F69F8D@bitbucket.org/okestrolab/tps.git#develop \ --insecure \ --skip-tls-verify
Bash
복사
U2ltQm9IeWVvbjpBVEJCbjQ2NUNydVpHcVNHWnhTQUVjTnNLZjZqNzlGNjlGOEQ=
docker run --rm -v $(pwd):/workspace \ -v $(pwd)/cache:/cache \ -v ~/.docker/config.json:/kaniko/.docker/config.json \ gcr.io/kaniko-project/executor:latest \ --context dir:///workspace/ \ --dockerfile /workspace/Dockerfile \ --destination your-dockerhub-repo/your-image:tag \ --cache=true \ --cache-dir=/cache \ --skip-tls-verify
Bash
복사

1. 목차

NOTE

목차

NOTE
스프링 빌드 방법 Docker를 사용하여 마이크로 서비스의 배포, 이동성, 및 확장성 처리하기 Docker 이미지 생성은 마이크로서비스의 배포, 이식성, 확장성과 관련된 도전을 극복하는 데 도움이 됩니다. 강사는 이 과정에서 세 가지 일반적인 접근 방식을 소개하며, 각각의 장단점을 논의하고 마이크로서비스를 컨테이너화하는 과정을 직접 시연합니다. 1. Docker 파일 사용: 이 방식은 Docker 이미지를 생성하기 위한 가장 기본적이고 전통적인 접근 방식입니다. Docker 파일에 일련의 명령을 작성하고, Docker 서버가 이러한 명령에 따라 Docker 이미지를 생성합니다. 이 접근 방식은 Docker 구문과 모범 사례를 배우는 학습 곡선을 포함합니다. 2. 빌드팩(Buildpacks) 사용: 빌드팩을 사용하면 Docker 파일을 작성하거나 Docker 서버에 직접 명령을 제공할 필요 없이 웹 애플리케이션을 컨테이너화할 수 있습니다. 단일 Maven 명령으로 Docker 이미지를 생성할 수 있으며, 이 과정에서 빌드팩의 개념을 활용합니다. 빌드팩은 Heroku와 Pivotal에 의해 개발되었으며, 웹 애플리케이션의 컨테이너화를 간소화하는 것을 목표로 합니다. 3. Google Jib 사용: Google Jib은 Google에 의해 개발되고 오픈소스화된 Java 도구입니다. Maven 플러그인 명령을 사용하여 Docker 파일을 작성하지 않고도 Java 애플리케이션의 Docker 이미지를 쉽게 생성할 수 있습니다. Docker 컨테이너 실행 절차: 1. Docker 컨테이너 실행: docker run -p 8080:8080 -d <이미지 이름>:<태그> 명령어를 사용하여 Docker 컨테이너를 실행합니다. p 옵션은 포트 매핑을 설정하고, d 옵션은 컨테이너를 분리 모드(백그라운드)에서 실행합니다. 2. 포트 매핑: Docker 컨테이너는 기본적으로 격리된 네트워크에서 실행되기 때문에 외부 네트워크에서 접근하기 위해서는 포트를 명시적으로 공개해야 합니다. p 옵션을 사용해 호스트 시스템의 포트와 컨테이너의 포트를 매핑합니다. 3. 컨테이너 확인 및 관리: docker ps 명령어로 실행 중인 컨테이너를 확인할 수 있습니다. Docker Desktop 애플리케이션을 사용하면 GUI를 통해 컨테이너를 관리할 수 있습니다. 주요 포인트: • Docker 컨테이너는 이미지를 기반으로 생성되며, 하나의 이미지에서 여러 컨테이너를 실행할 수 있습니다. • 컨테이너는 각각 격리된 환경을 가지며, 동일한 포트를 내부적으로 사용할 수 있지만, 외부에 공개할 때는 서로 다른 포트를 사용해야 합니다. • 분리 모드에서 컨테이너를 실행하면 터미널이 바로 반환되고, 컨테이너 로그와 상태는 Docker Desktop이나 docker logs <컨테이너 ID> 명령어를 통해 확인할 수 있습니다. • Docker는 개발, 배포 및 운영을 간소화하고 표준화하여 마이크로서비스 아키텍처의 이점을 극대화할 수 있게 합니다.
이 강의에서는 Docker를 사용하여 마이크로서비스를 컨테이너화하고, 외부에서 접근 가능하게 만드는 과정을 배웠습니다. Docker 컨테이너를 사용함으로써 애플리케이션의 배포, 이식성 및 확장성을 효과적으로 관리할 수 있습니다. Docker 파일을 사용하는 것은 기본적이고 직접적인 방법이지만, 다음과 같은 여러 단점이 있습니다: 1. 학습 곡선: Docker 파일을 작성하려면 Docker 개념에 대한 깊은 이해가 필요합니다. 개발자가 모든 Docker 개념을 마스터하는 것은 시간이 많이 걸리고 항상 가능한 것은 아닙니다. 2. 최적화와 보안: Docker 이미지를 가능한 한 작게 유지하고 캐싱과 압축을 사용하여 빌드 과정을 최적화하는 것이 중요합니다. 또한, 보안 취약점이 없도록 주의 깊게 관리해야 합니다. 이러한 최적화와 보안 관리는 추가적인 노력과 전문 지식을 요구합니다. 3. 유지 관리의 어려움: 여러 마이크로서비스에 대해 별도의 Docker 파일을 관리해야 하는 경우, 이는 상당한 유지 관리 부담을 초래할 수 있습니다. 각 마이크로서비스마다 Docker 파일을 업데이트하고 관리해야 하며, 이는 시간이 많이 소요될 수 있습니다. 이러한 단점으로 인해 개발자들은 Docker 파일 없이 Docker 이미지를 자동으로 생성할 수 있는 새로운 접근 방식을 찾고 있습니다. BuildpacksGoogle Jib은 이러한 요구를 충족시키는 두 가지 솔루션입니다. 이들은 Docker 이미지 생성 과정을 단순화하고 자동화하여 개발자가 보다 쉽게 Docker 이미지를 생성하고 관리할 수 있도록 돕습니다.
Buildpacks와 Google Jib의 장점:간소화된 이미지 생성: Docker 파일을 직접 작성할 필요 없이 명령어 한 줄로 Docker 이미지를 생성할 수 있습니다. • 최적화와 보안: Buildpacks와 Google Jib는 이미지 최적화와 보안을 자동으로 처리합니다. 이를 통해 개발자는 성능과 보안에 대해 걱정할 필요 없이 이미지를 생성할 수 있습니다. • 유지 관리 용이: 모든 마이크로서비스에 대해 일관된 방식으로 이미지를 생성하고 관리할 수 있으며, 복잡한 설정이나 관리 없이도 최신 상태를 유지할 수 있습니다. 이 강의에서는 Docker 파일을 사용하는 전통적인 방식의 한계를 이해하고, Buildpacks와 Google Jib과 같은 현대적인 도구를 사용하여 이러한 단점을 극복하는 방법을 배우게 됩니다. 이러한 도구를 통해 마이크로서비스의 Docker 이미지 생성 과정을 간소화하고 개선할 수 있습니다. Buildpacks는 Heroku와 Pivotal에서 수년간의 경험을 바탕으로 구축된 프레임워크로, 개발자가 Docker 이미지를 쉽게 생성할 수 있도록 돕습니다. 이 방식은 Docker 파일을 직접 작성하는 데 따른 학습 곡선, 최적화 및 보안 문제, 유지 관리의 어려움 등을 해결해줍니다.
Buildpacks를 사용하여 Docker 이미지를 생성하는 방법은 다음과 같습니다: 1. pom.xml 파일에 **packaging**을 **jar**로 설정하고 Spring Boot Maven 플러그인이 포함되어 있는지 확인합니다. 2. Docker 이미지 이름을 **pom.xml**의 spring-boot-maven-plugin 설정에 image 태그 내 **name**으로 추가합니다. 이 때, Docker 사용자 이름, 애플리케이션 이름(artifactId를 사용하여 자동으로 가져올 수 있음), 태그(버전)를 포함합니다. 3. Maven 명령어 **mvn spring-boot:build-image**를 실행하여 Buildpacks를 사용해 Docker 이미지를 자동으로 생성합니다. 이 과정에서 필요한 Buildpacks 관련 라이브러리와 이미지가 다운로드됩니다. 4. 생성된 Docker 이미지를 docker run -d -p <외부포트>:<내부포트> <이미지이름> 명령어를 사용해 컨테이너로 실행합니다. 여기서 외부 포트는 로컬 시스템에서 컨테이너에 접근하기 위해 사용되는 포트이며, 내부 포트는 컨테이너 내에서 애플리케이션이 실행되는 포트입니다. Buildpacks를 사용하는 장점은 다음과 같습니다: • Docker 파일 없이도 Docker 이미지를 생성할 수 있습니다. • 보안, 캐싱, 성능 최적화 등의 최선의 관행을 자동으로 적용합니다. • Docker 이미지 크기를 줄일 수 있으며, 유지 관리와 버전 관리가 간편해집니다. Buildpack 개발 가이드 | PaaS-TA-5.5.0 컨테이너 빌드 도구 선택을 위한 특성 및 성능 비교 (Kaniko, Buildah, Buildkit)
Jib Jib은 Java 애플리케이션 전용 도구로, 개발자가 Docker 파일을 작성하지 않고도 Docker 이미지를 쉽게 생성할 수 있게 해줍니다. 이는 Buildpacks와 유사한 접근 방식이지만, Jib은 Java 애플리케이션에 특화되어 있으며, Buildpacks보다 빠르게 작동합니다. Jib을 사용하여 Docker 이미지를 생성하는 단계는 다음과 같습니다: 1. pom.xml 파일에 Jib Maven 플러그인을 추가합니다. 플러그인 설정에서는 Docker 이미지의 이름을 지정해야 합니다. 2. Maven 명령어 **mvn compile jib:dockerBuild**를 실행하여 로컬 Docker 서버를 사용해 Docker 이미지를 생성합니다. 3. 생성된 Docker 이미지는 docker images 명령어로 확인할 수 있으며, docker run -d -p <외부포트>:<내부포트> <이미지이름> 명령어로 컨테이너를 실행할 수 있습니다. Jib의 장점은 다음과 같습니다: • Docker 파일을 작성할 필요가 없으므로 개발자가 Docker에 대한 깊은 지식이 없어도 Docker 이미지를 쉽게 생성할 수 있습니다. • Buildpacks와 비교하여 이미지 생성 속도가 빠릅니다. • Jib은 Docker가 설치되지 않은 환경에서도 Docker 이미지를 생성하고 원격 저장소에 푸시할 수 있는 기능을 제공합니다. 이는 CI/CD 파이프라인에서 유용하게 사용될 수 있습니다. Jib의 단점은 Java 애플리케이션에만 사용할 수 있다는 점입니다. 이는 Buildpacks가 지원하는 여러 언어에 비해 제한적입니다. 하지만, Java 기반 마이크로서비스를 개발하는 경우, Jib은 효율적인 Docker 이미지 생성 도구로서 매우 유용할 수 있습니다. GitHub - GoogleContainerTools/jib: Build container images for your Java applications.

Kaniko를 Kubernetes에서 사용

Kaniko는 Kubernetes 환경에서 Pod로 실행되어 빌드를 수행할 수도 있습니다. 예를 들어, 다음은 Kaniko를 Kubernetes Job으로 실행하는 YAML 파일입니다.
yaml코드 복사 apiVersion: batch/v1 kind: Job metadata: name: kaniko-job spec: template: spec: containers: - name: kaniko image: gcr.io/kaniko-project/executor:latest args: - --context=git://github.com/your/repo.git#refs/heads/main - --dockerfile=Dockerfile - --destination=your-dockerhub-repo/your-image:tag volumeMounts: - name: docker-config mountPath: /kaniko/.docker restartPolicy: Never volumes: - name: docker-config configMap: name: docker-config --- apiVersion: v1 kind: ConfigMap metadata: name: docker-config data: config.json: | { "auths": { "https://index.docker.io/v1/": { "auth": "your-auth-token" } } }
YAML
복사
이 예제는 Git 리포지토리에서 소스를 가져와 Kaniko로 빌드하고 DockerHub에 푸시하는 Kubernetes Job입니다. ConfigMap을 사용하여 DockerHub 인증 정보를 제공합니다.
이와 같이 다양한 Kaniko 옵션과 Kubernetes 환경에서의 사용법을 통해 더 많은 빌드 시나리오를 지원할 수 있습니다.

Kaniko 캐시의 의미와 활용

1.
의존성 다운로드 단계:
./gradlew build 명령어를 실행하면 모든 의존성을 다운로드하고 컴파일 및 테스트 단계를 거칩니다.
의존성 다운로드는 시간이 많이 걸릴 수 있습니다. 이 단계는 build.gradle이나 settings.gradle 파일이 변경되지 않는 한 캐시를 활용하여 빌드 시간을 단축할 수 있습니다.
2.
빌드 단계:
소스 코드가 변경될 때마다 ./gradlew build 명령어는 전체 프로젝트를 다시 빌드합니다.
그러나, 소스 코드 변경이 없는 경우 이전 빌드 결과를 캐시에서 가져올 수 있습니다.

실질적인 예제

다음은 Kaniko와 Gradle을 사용하여 캐시를 효과적으로 활용하는 예제입니다.

Dockerfile

Dockerfile코드 복사 # First stage: Build the application FROM openjdk:21-jdk-slim AS build # Set the working directory WORKDIR /app # Copy the Gradle wrapper and build files COPY gradlew . COPY build.gradle . COPY settings.gradle . # Download the dependencies RUN ./gradlew dependencies --no-daemon # Copy the source code COPY src src # Build the application RUN ./gradlew build -x test --no-daemon # Second stage: Create the final image FROM openjdk:21-jdk-slim # Set the working directory WORKDIR /app # Copy the JAR file from the build stage COPY --from=build /app/build/libs/*.jar app.jar # Expose the port the application runs on EXPOSE 8080 # Run the JAR file ENTRYPOINT ["java", "-jar", "app.jar"]
Plain Text
복사

Kaniko 빌드 명령어

sh코드 복사 docker run --rm -v $(pwd):/workspace \ -v $(pwd)/cache:/cache \ -v ~/.docker/config.json:/kaniko/.docker/config.json \ gcr.io/kaniko-project/executor:latest \ --context dir:///workspace/ \ --dockerfile /workspace/Dockerfile \ --destination your-dockerhub-repo/your-image:tag \ --cache=true \ --cache-dir=/cache \ --skip-tls-verify
Plain Text
복사

캐시를 활용한 단계별 이점

1.
의존성 다운로드 캐시:
RUN ./gradlew dependencies --no-daemon 단계는 의존성을 다운로드합니다.
build.gradle이나 settings.gradle 파일이 변경되지 않으면 이 단계는 캐시를 활용하여 재실행 시간을 줄일 수 있습니다.
2.
소스 코드 복사와 빌드:
COPY src src 단계는 소스 코드를 복사합니다. 소스 코드가 변경되지 않으면 이 단계 이후의 빌드는 캐시를 사용할 수 있습니다.
RUN ./gradlew build -x test --no-daemon 단계는 애플리케이션을 빌드합니다. 이 단계는 소스 코드가 변경되면 다시 실행됩니다.

실전 시나리오

1.
첫 번째 빌드:
모든 의존성을 다운로드하고 소스 코드를 빌드합니다. 모든 단계가 캐시에 저장됩니다.
2.
두 번째 빌드 (변경 없음):
의존성과 빌드 단계 모두 캐시를 사용하여 빠르게 빌드가 완료됩니다.
3.
소스 코드 변경 후 빌드:
소스 코드가 변경된 경우, 소스 코드 복사 및 빌드 단계가 다시 실행되지만, 의존성 다운로드 단계는 캐시를 사용하여 시간을 절약할 수 있습니다.

결론

./gradlew build 명령어를 사용할 때, Kaniko 캐시는 특히 의존성 다운로드와 같은 변경되지 않는 단계에서 빌드 시간을 크게 단축할 수 있습니다. 소스 코드가 변경되면 빌드가 다시 실행되지만, 의존성 단계는 캐시를 통해 최적화됩니다. 따라서, Kaniko의 캐시는 전체 빌드 프로세스를 효율적으로 유지하는 데 여전히 유용합니다.
4o

How Kaniko Works

Kaniko is designed to build container images inside a container or Kubernetes cluster without requiring a Docker daemon. This is particularly useful for security-conscious environments like Kubernetes where privileged access is not desired. Kaniko executes each Dockerfile command and snapshots the filesystem in userspace after each command, creating image layers and updating metadata accordingly (GitHub) (GitLab Documentation).

Kaniko Caching

Kaniko provides two main caching capabilities to enhance image building:
1.
Base Image Caching:
Base images can be downloaded and stored in a local, shared volume. This allows the Kaniko executor to reuse these images without downloading them again for subsequent builds, thus saving time.
2.
Layer Caching:
Intermediate layers created during the execution of Dockerfile commands (like RUN, COPY, etc.) can be cached. These layers are stored in a remote container registry repository. Before executing a command, Kaniko checks if an equivalent layer is already available in the cache and reuses it if found, thus avoiding redundant execution of commands (Giant Swarm).

Using Kaniko with GitLab CI/CD

Kaniko can be integrated with GitLab CI/CD to build and push Docker images. The recommended setup involves using the Kaniko debug image and overriding the entrypoint to ensure compatibility with GitLab CI/CD pipelines. Credentials for the container registry are managed via CI/CD variables, which Kaniko reads to authenticate and push the built images (GitLab Documentation).

Practical Example

Here's an example of using Kaniko in a Kubernetes environment to build and push a Docker image:
1.
Kubernetes Job Definition:
yaml코드 복사 apiVersion: batch/v1 kind: Job metadata: name: kaniko-job spec: template: spec: containers: - name: kaniko image: gcr.io/kaniko-project/executor:latest args: [ "--context=git://github.com/your/repo.git#refs/heads/main", "--dockerfile=Dockerfile", "--destination=your-dockerhub-repo/your-image:tag", "--cache=true", "--cache-repo=your-dockerhub-repo/cache" ] restartPolicy: Never
YAML
복사
2.
Executing Kaniko Locally:
sh코드 복사 ./executor --context dir:///path/to/your/project \ --dockerfile /path/to/your/project/Dockerfile \ --destination your-dockerhub-repo/your-image:tag \ --cache=true \ --cache-dir=/cache
Plain Text
복사
These steps ensure that Kaniko builds the image efficiently by leveraging cached layers, reducing build times for subsequent builds.
For more detailed information, you can refer to the Kaniko GitHub repository and GitLab documentation on using Kaniko. Additionally, Giant Swarm's article provides a comprehensive overview of Kaniko's caching mechanisms.