ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [docker] ARM 환경에서 docker compose up 실패 문제 트러블슈팅
    DevOps/Docker 2024. 12. 19. 02:46
    728x90

    새로운 프로젝트인 defee를 진행하면서, docker를 다시 사용해 보았다.
    이전에 정글에서 C프로젝트를 진행하면서 한 번 사용해본 적 있긴 했지만, 정확하게 어떤 역할을 하는지에 대해서 잘 모르고 하라는 대로만 했었던 기억이 있다.

    자세한 것들은 기억나지 않지만 한가지 명확하게 기억나는 것이 있다.

    "실리콘 기반의 mac은 뭔가 다르다..."

    는 것이었다.

    이번에도 백의 서버와 db를 직접 띄워보고 사용해보기 위해서 repository를 클론 받아 docker를 띄워보는데 역시나 간단히 되지 않았다.

    해결 과정과 docker에 대한 간단한 개념 학습을 기술해보겠다.

    [!WARNING]

    저의 실행 환경은 Silicon MacBook Air M2, Docker Desktop을 사용하였고 docker desktop 설정에서 Use Rosetta for x86_64/amd64 emulation on Apple Silicon의 옵션을 활성화한 상태였습니다.

    저의 해결 방법이 정답이 아닐 수 있습니다!


    About Docker

    Docker는 애플리케이션을 실행하는 데 필요한 모든 구성 요소를 하나의 컨테이너(Container) 로 묶어 배포하고 실행할 수 있게 해주는 컨테이너 기반 가상화 플랫폼이다.

    주요 특징

    1. 경량화된 가상화: Docker는 운영 체제(OS) 레벨에서 격리된 컨테이너를 사용해 애플리케이션을 실행하며, 기존 가상 머신(VM)보다 가볍고 빠르다.
    2. 이식성: 컨테이너는 어디서든 동일하게 동작하므로, 개발 환경과 운영 환경 간의 차이를 최소화할 수 있다.
    3. 효율성: 애플리케이션 실행에 필요한 최소한의 리소스만 사용한다.
    4. 확장성: 컨테이너 기반 구조는 애플리케이션을 쉽게 확장하거나 관리할 수 있도록 도와준다.

    주요 사용 사례

    • 애플리케이션 배포 자동화
    • 마이크로서비스 아키텍처 구현
    • 개발 환경 설정 간소화
    • 테스트 및 CI/CD 파이프라인 구축

    Docker는 이미지(Image) 를 기반으로 컨테이너를 생성하며, 이 이미지는 애플리케이션 실행에 필요한 코드, 라이브러리, 환경 설정 등을 포함하고 있다. Dockerfile을 작성하여 이미지를 빌드하고, 이를 바탕으로 컨테이너를 실행한다.

    1. Docker Image (이미지)

    개념

    • Docker 이미지는 애플리케이션을 실행하기 위한 모든 파일, 라이브러리, 설정을 포함하는 불변의 템플릿이다.
    • 실행 가능한 상태가 아닌, 컨테이너를 생성하기 위한 기반이 되는 "설정 파일"과 같다.

    특징

    1. 계층 구조:
      • 이미지는 여러 계층(layer)로 구성된다.
      • 각 계층은 변경 사항만 포함하며, 중복된 부분은 캐시되어 효율적이다.
    2. 불변성:
      • 한 번 빌드된 이미지는 변경되지 않는다. 수정하려면 새로운 이미지를 빌드해야 한다.
    3. Dockerfile 기반:
      • 이미지는 일반적으로 Dockerfile이라는 설정 파일을 기반으로 생성된다.

    사용 예

    1. 이미지 다운로드:
      • Ubuntu 20.04 기반 이미지를 Docker Hub에서 다운로드.
    2. docker pull ubuntu:20.04
    3. 이미지 확인:
      • 로컬에 저장된 Docker 이미지를 나열.
    4. docker images
    5. 이미지 빌드:
      • 현재 디렉토리의 Dockerfile을 기반으로 my-app이라는 이름의 이미지를 생성.
    6. docker build -t my-app .

    2. Docker Container (컨테이너)

    개념

    • 컨테이너는 이미지 기반으로 실행되는 독립된 애플리케이션 실행 환경이다.
    • 컨테이너는 이미지의 실행 가능한 인스턴스라고 볼 수 있다.

    특징

    1. 가상화된 환경:
      • 컨테이너는 독립된 파일 시스템과 네트워크를 가진다.
      • 그러나 호스트 OS의 커널을 공유하므로 가볍고 빠르다.
    2. 상태 유지 가능:
      • 컨테이너는 상태를 가질 수 있으며, 실행 중 데이터가 변경될 수 있다.
      • 하지만 컨테이너가 종료되거나 삭제되면 상태는 사라진다(영속적 데이터 저장은 볼륨 사용 필요).
    3. 멀티 인스턴스:
      • 동일한 이미지를 기반으로 여러 컨테이너를 실행할 수 있다.

    사용 예

    1. 컨테이너 실행:
      • Ubuntu 20.04 이미지를 기반으로 my-container라는 이름의 컨테이너를 실행.
    2. docker run -it --name my-container ubuntu:20.04
    3. 컨테이너 목록 확인:
      • 실행 중인 컨테이너 목록을 표시.
    4. docker ps
    5. 컨테이너 정지 및 삭제:
    6. docker stop my-container docker rm my-container
    7. 컨테이너에 명령 실행:
      • 실행 중인 컨테이너 내부에서 명령 실행.
    8. docker exec -it my-container bash

    3. Docker Compose

    개념

    • Docker Compose는 여러 컨테이너로 구성된 애플리케이션을 정의하고 관리하는 도구이다.
    • 컨테이너 간의 네트워크, 볼륨, 환경 변수를 자동으로 설정하고 실행한다.

    특징

    1. 구성 파일(docker-compose.yml) 사용:
      • YAML 형식의 파일로 애플리케이션의 컨테이너, 네트워크, 볼륨 등을 정의한다.
    2. 다중 컨테이너 관리:
      • 여러 서비스를 동시에 빌드, 실행, 정지, 삭제할 수 있다.
    3. 의존성 관리:
      • 컨테이너 간 의존성을 설정하여 실행 순서를 제어 가능.

    사용 예

    1. docker-compose.yml 예제:

      • web: 애플리케이션 컨테이너를 빌드하고 실행.
      • db: MySQL 데이터베이스 컨테이너를 실행.
    2. version: '3.9' services: web: build: context: . dockerfile: Dockerfile ports: - "8080:8080" volumes: - ./app:/app db: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: example

    3. Compose 명령어:

      • 빌드 및 실행:

        docker compose up --build
      • 정지:

        docker compose down
    4. 장점:

      • 다중 컨테이너 애플리케이션의 설정과 실행을 자동화.
      • 네트워크와 볼륨 설정을 간단하게 구성.

    요약

    항목 Docker Image Docker Container Docker Compose
    역할 애플리케이션 실행을 위한 불변의 템플릿. 이미지 기반 실행 가능한 애플리케이션 인스턴스. 여러 컨테이너를 관리하고 실행하는 도구.
    상태 불변 (Immutable). 변경 가능 (가상 환경 내에서 데이터 상태 변경 가능). 상태를 가지지 않음 (구성을 통해 실행/정지 컨테이너 관리).
    사용 방식 빌드: docker build / 다운로드: docker pull. 실행: docker run. 설정: docker-compose.yml / 실행: docker compose up.
    사용 목적 애플리케이션 템플릿 제공. 독립된 실행 환경 제공. 다중 컨테이너 환경의 설정 및 실행 자동화.
    의존성 관리 없음. 직접 컨테이너 간 연결 설정 필요. 네트워크, 볼륨, 환경 변수 등을 자동 관리.
    주요 사용 환경 배포 또는 컨테이너 생성 준비 단계. 컨테이너 실행 및 개별 관리. 다중 컨테이너 기반 애플리케이션 개발 및 실행 환경.

    Trouble Shooting

    문제상황

    윈도우 기반의 환경을 기준으로 만들어진 dockerfiledocker-compose.yml 파일들을 바탕으로 docker에 컨테이너를 띄우는 과정에서, 다음과 같은 오류가 발생함

    => ERROR [defee_springapp  8/15] RUN apt -y install ./google-chrome-stable-114.0.5735.106-1.deb 0.4s
    ------
    0.392 Some packages could not be installed. This may mean that you have
    0.392 requested an impossible situation or if you are using the unstable
    0.392 distribution that some required packages have not yet been created
    0.392 or been moved out of Incoming.
    0.392 The following information may help to resolve the situation:
    0.392 
    0.392 The following packages have unmet dependencies:
    0.426  google-chrome-stable:amd64 : Depends: libasound2:amd64 (>= 1.0.17) but it is not installable
    0.426                               Depends: libatk-bridge2.0-0:amd64 (>= 2.5.3) but it is not installable
    0.426                               Depends: libatk1.0-0:amd64 (>= 2.2.0) but it is not installable
    0.426                               Depends: libatspi2.0-0:amd64 (>= 2.9.90) but it is not installable
    0.426                               Depends: libc6:amd64 (>= 2.17) but it is not installable
    0.426                               Depends: libcairo2:amd64 (>= 1.6.0) but it is not installable
    0.426                               Depends: libcups2:amd64 (>= 1.6.0) but it is not installable
    0.426                               Depends: libcurl3-gnutls:amd64 but it is not installable or
    0.426                                        libcurl3-nss:amd64 but it is not installable or
    0.426                                        libcurl4:amd64 but it is not installable or
    0.426                                        libcurl3:amd64 but it is not installable
    0.426                               Depends: libdbus-1-3:amd64 (>= 1.9.14) but it is not installable
    0.426                               Depends: libdrm2:amd64 (>= 2.4.75) but it is not installable
    0.426                               Depends: libexpat1:amd64 (>= 2.0.1) but it is not installable
    0.426                               Depends: libgbm1:amd64 (>= 17.1.0~rc2) but it is not installable
    0.426                               Depends: libglib2.0-0:amd64 (>= 2.39.4) but it is not installable
    0.426                               Depends: libgtk-3-0:amd64 (>= 3.9.10) but it is not installable or
    0.426                                        libgtk-4-1:amd64 but it is not installable
    0.426                               Depends: libnspr4:amd64 (>= 2:4.9-2~) but it is not installable
    0.426                               Depends: libnss3:amd64 (>= 2:3.31) but it is not installable
    0.426                               Depends: libpango-1.0-0:amd64 (>= 1.14.0) but it is not installable
    0.426                               Depends: libvulkan1:amd64 but it is not installable
    0.426                               Depends: libx11-6:amd64 (>= 2:1.4.99.1) but it is not installable
    0.426                               Depends: libxcb1:amd64 (>= 1.9.2) but it is not installable
    0.426                               Depends: libxcomposite1:amd64 (>= 1:0.4.4-1) but it is not installable
    0.426                               Depends: libxdamage1:amd64 (>= 1:1.1) but it is not installable
    0.426                               Depends: libxext6:amd64 but it is not installable
    0.426                               Depends: libxfixes3:amd64 but it is not installable
    0.426                               Depends: libxkbcommon0:amd64 (>= 0.5.0) but it is not installable
    0.426                               Depends: libxrandr2:amd64 but it is not installable"

    크롬과 관련된 deps가 설치되지 않는 오류로 인식하고 여러 접근을 시도하였고 결국 다음과 같은 방법으로 해결하였다.

    해결방법

    1. 로컬에 자바 설치 후 환경변수 등록
    2. 환경변수 등록 후 vsCode, docker desktop 재시작
    3. dockerfileFROM openjdk:17.0.1-jdk-slimFROM —platform=linux/amd64 openjdk:17.0.1-jdk-slim으로 수정
    4. 로컬 터미널에서 직접 chmod +x ./gradlew 로 권한 설정
    5. 로컬에서 직접 ./gradlew clean bootJar 수행
    6. docker compose up —build 성공

    문제가 해결된 원인을 다시 분석하면 다음과 같다.

    1. 로컬에 자바 설치 후 환경변수 등록

    • Gradle은 실행 시 Java Runtime Environment(JRE)가 필요하다. 로컬에 Java가 설치되어 있지 않으면 Gradle이 실행되지 못하며, Docker에서도 Gradle 관련 빌드 작업이 실패한다.
    • JAVA_HOME 환경변수는 Java의 설치 경로를 Gradle과 같은 도구에 알려주기 위해 필요하다. Java를 설치하고 환경변수를 등록함으로써 Gradle이 Java를 올바르게 인식하도록 설정했기 때문에, 이 단계는 Gradle과의 호환성을 확보하는 데 중요한 역할을 했다.

    2. 환경변수 등록 후 VSCode, Docker Desktop 재시작

    • 환경변수 설정은 현재 터미널 세션에만 적용되기 때문에, 이미 실행 중이던 VSCode나 Docker Desktop에서는 새로 등록된 JAVA_HOME 값을 알지 못한다.
    • VSCode와 Docker Desktop을 재시작함으로써 새로운 환경변수를 읽어들일 수 있도록 하였다. 이를 통해 Docker가 Java 환경변수를 제대로 인식하고, Gradle 빌드 과정에서 Java를 사용할 수 있게 되었다.

    3. Dockerfile 수정: FROM openjdk:17.0.1-jdk-slimFROM —platform=linux/amd64 openjdk:17.0.1-jdk-slim

    • M1/M2 칩을 사용하는 Mac은 ARM 기반 아키텍처를 사용한다. 기본적으로 Docker는 호스트의 아키텍처(ARM)에 맞는 이미지를 선택하는데, 이로 인해 Gradle이나 다른 종속성이 호환되지 않는 문제가 발생할 수 있다.
    • --platform=linux/amd64 플래그를 추가함으로써 Docker가 x86_64(amd64) 아키텍처의 이미지를 사용하도록 강제하였다. 이를 통해 ARM 호환성 문제를 우회하고, Gradle 및 의존성이 정상적으로 동작하게 되었다.

    4. 로컬 터미널에서 직접 chmod +x ./gradlew 실행

    • gradlew는 프로젝트에서 사용하는 Gradle Wrapper 스크립트로, Gradle 빌드를 실행하기 위해 필요한 파일이다. 하지만 실행 권한이 없으면 Docker 컨테이너 내부에서 Gradle Wrapper가 실행되지 못해 빌드가 실패한다.
    • 로컬에서 chmod +x ./gradlew 명령을 통해 실행 권한을 부여함으로써, Docker 빌드 시 이 권한이 유지되어 Gradle Wrapper가 정상적으로 실행될 수 있었다.

    5. 로컬에서 직접 ./gradlew clean bootJar 수행

    • Docker 빌드 과정에서 Gradle이 정상적으로 작동하지 않을 가능성을 배제하기 위해, 로컬에서 먼저 Gradle 빌드(./gradlew clean bootJar)를 실행하였다.
    • 이 작업은 다음과 같은 두 가지 문제를 예방하였다:
      1. Gradle 의존성이 미리 다운로드되어, Docker 빌드 시 다운로드 과정에서 발생할 수 있는 네트워크 문제를 방지하였다.
      2. Gradle 빌드 스크립트(build.gradle)나 프로젝트 설정 오류를 사전에 확인할 수 있었다.
    • JAR 파일이 로컬에서 성공적으로 생성되었기 때문에, Docker 빌드가 실패하지 않고 진행될 수 있었다.

    6. docker compose up --build 성공

    • 앞선 단계에서 해결한 환경 문제(자바 환경변수, 실행 권한, Gradle 빌드 성공)가 모두 맞물려, Docker Compose가 성공적으로 동작할 수 있었다.
    • Gradle이 Docker 컨테이너 내부에서 제대로 실행되고, JAR 파일이 정상적으로 생성되었기 때문에 Docker Compose가 애플리케이션을 빌드하고 실행할 수 있었다.

    결론

    이후 docker desktop을 보면 container, image 그리고 volume에 관련없어 보이는 것들이 생성되어 있다.

    이들은 삭제해주었고, 이후 실행에는 문제가 없었다.

    드디어... 마참내 스웨거가 보인다 ㅠ

    이러한 해결 방법은 협업을 하는 데 좋은 방법은 아니다. 하지만 개인이 프로젝트를 수행하는거나 로컬에서 테스트하는데에는 문제 없어 보인다.

    도커에 대해 더 공부해보면 이 포스트도 얼마나 그지같이 해결했는지 알게될 것만 같다.

Designed by Tistory.