본문 바로가기
Server

[Docker] Docker compose 명령어와 레이어 캐싱

by 모모_모 2024. 7. 11.

 

컨테이너와 가상 머신의 차이는, 주로 아키텍처와 자원 관리 방식의 차이에서 비롯된다.
컨테이너는 호스트 운영체제의 커널을 공유하고 자체 OS 부팅이 필요없으며, 앱과 필요한 라이브러리-종속성만 포함하는 가벼운 단위이다.
가상 머신은 각각 자체 커널과 운영체제를 포함한 완전한 독립적 환경을 제공한다. 더 높은 격리 수준을 제공하지만, 자원 사용량이 많고 부팅 시간이 길어진다. 하이퍼바이저를 통해 하드웨어를 가상화하고, vm간 자원 분배과정의 오버헤드가 발생한다.

컨테이너 오픈소스 도커 컨테이너를 관리하는 도구인 도커 컴포즈에 대해 알아보자.

 

Docker compose

  • 여러 도커 컨테이너를 하나의 애플리케이션으로 정의하고 관리하기 위한 도구
  • 멀티 컨테이너 애플리케이션 정의
  • docker-compose.yml 파일을 통해 여러 컨테이너를 정의
    • 각 컨테이너의 이미지, 볼륨, 네트워크 설정 등 포함
  • 서비스 간 의존성 관리
    • 여러 컨테이너 간의 의존성을 정의하고, 필요한 순서에 따라 컨테이너 시작할 수 있음
  • 일관된 개발 환경 제공
    • docker-compose.yml 파일 사용해 로컬 개발 환경과 프로덕션 환경을 일관되게 설정할 수 있음
    • 개발과 운영 간 환경차이를 줄여준다.
  • 간편한 실행 및 종료
    • docker-compose up 명령을 통해 정의된 모든 컨테이너를 한번에 시작
    • docker-compose down 통해 모든 컨테이너 한 번에 종료
    • docker-compose ps로 현재 실행 중인 서비스 목록화
    • docker-compose logs 실행중 서비스 로그 출력

기능(명령어)

  • build
    • context : Dockerfile 있는 디렉토리 지정
    • dockerfile : 사용할 Dockerfile의 경로를 지정
    build:
    	context: ./app
    	dockerfile: Dockerfile
    
  • image
    • 사용할 Docker 이미지를 지정
    • 이미지 빌드x, 이미 존재하는 이미지 사용할 때 사용
    image: mysql:5.7
    
  • ports
    • 호스트와 컨테이너간 포트 매핑을 지정
    ports:
    - "5000:5000"
    
  • envirionment
    • 컨테이너 내에서 사용활 환경 변수를 지정
  • volumes
    • 호스트와 컨테이너 간의 파일 시스템 마운트를 지정
    • 네트워크 정의 - 서비스에서 네트워크 사용하기 전 전역 설정에 정의
  • depends_on
    • 컨테이너간 의존성을 지정합니다. 예를 들어, web 서비스는 db 서비스가 시작된 후에 시작
  • networks
    • 서비스가 연결될 네트워크를 지정 - 서비스에서 네트워크 사용하기 전 전역 설정에 정의
    • 사설 ip로 고정했는데, 서비스 재시작시 ip가 재할당 되는 문제가 있음.
      • 그걸 docker network가 먹어버릴 가능성이 있다?
  • restart
    • 컨테이너 재시작 정책을 지정합니다
    • always, on-failure, unless-stopped

예제

#도커허브에서 풀
Docker pull wooseook/dockercompose

#백그라운드에서 영원히 실행
docker run -d wooseook/dockercompose sleep infinity

#도커 실행 이미지 확인
docker ps -a

docker exec happy_einstein /bin/ls /

#ls한 결과에서 복사할 파일을 선택하고, 복사될 목적 경로 지정
docker cp happy_einstein:/docker-compose.yaml .
docker cp happy_einstein:/app .

docker compose ps
docker compose down
docker compose up
docker compose -f docker-compose-arm.yaml up

 

레이어 캐싱이란?

  • Docker가 이미지 빌드 프로세스에서 각 명령어 (RUN, COPY, ADD등)가 실행될 때마다 생성되는 중간 이미지 레이어를 저장하는 메커니즘. 그래서 이미 빌드된 중간 이미지를 재사용 함으로써 빌드 시간을 단축하고 효율성을 높일 수 있다.
  • Docker 이미지는 읽기 전용(read-only) 레이어들의 스택으로 구성된다. 각 레이어는 이미지의 이전 레이어에 대한 변경 사항을 나타내고, 최종적으로 하나의 컨테이너 파일 시스템을 형성한다.

작동 원리

  1. 빌드 캐시 사용
    • 각 명령어 실행시 생성된 중간 이미지(레이어)를 캐싱하고, 동일 명령어 호출시 캐싱된 이미지(레이어)를 재사용한다.
  2. 변경 감지
    • 도커는 각 레이어가 생성된 명령어와 컨텍스트를 기반으로 캐시된 레이어를 재사용할지 여부를 결정한다.
    • 만약 명령어 또는 컨텍스트가 변경되면, 해당 명령어 이후 모든 레이어는 다시 생성된다.
    # Dockerfile 예시
    FROM ubuntu:latest
    
    # 캐시 사용: 패키지 리스트 업데이트는 변경되지 않았으므로 캐시된 레이어 사용
    RUN apt-get update
    
    # 캐시 사용: 'curl' 패키지 설치는 변경되지 않았으므로 캐시된 레이어 사용
    RUN apt-get install -y curl
    
    # 새로운 레이어: 'COPY' 명령어는 새로운 파일을 복사하므로 캐시 사용 불가
    COPY . /app
    
    # 새로운 레이어: 이전 명령어 이후의 모든 명령어는 다시 실행
    RUN make /app
    

장점

  • 빠른 빌드 시간
  • 효율적 리소스 사용
  • 컨테이너 배포 속도 향상

단점

  • 디스크 사용량 증가 : 캐싱된 레이어 수가 많을수록 디스크 사용량이 증가한다
  • 빌드 프로세스 복잡성 : 도커파일 작성시 레이어 캐싱 최적화를 위해 명령어 순서와 레이어 독립성을 고려해야 한다

캐시 무효화

  • —no-cache 옵션을 사용하여 캐시사용하지 않고 모든 명령어를 새로 실행하여 이미지 빌드 가능

 

 

멀티 스테이지 빌드 vs 싱글 스테이지 빌드

멀티 스테이지 빌드란, 여러 단계로 나누어 이미지를 빌드하는 방법이다.

각 단계는 독립적으로 실행되며, 필요한 경우 이전 단계의 결과를 참조할 수 있다.

# 멀티 스테이지 빌드
# 빌드 단계
FROM node:14 AS builder

WORKDIR /app

COPY package.json ./
RUN npm install

COPY . .

RUN npm run build

# 실행 단계
FROM node:14

WORKDIR /app

COPY --from=builder /app/dist ./dist

CMD ["node", "dist/app.js"]
  • 여러 단계로 나누어 빌드가 진행됩니다. 각 단계는 독립적으로 실행되며, 필요에 따라 이전 단계의 결과물을 참조합니다
  • 레이어 캐싱: 각 단계의 명령어는 독립적으로 캐싱됩니다. 단계별로 레이어가 캐싱되기 때문에, 한 단계의 명령어가 변경되어도 다른 단계는 캐시된 레이어를 재사용할 수 있습니다.
  • 장점: 최종 이미지에 불필요한 빌드 종속성을 포함하지 않음, 이미지 크기가 작아짐, 빌드 단계별로 최적화 가능.
  • 단점: Dockerfile이 복잡해질 수 있음, 설정이 다소 까다로울 수 있음.

 

 

싱글 스테이지 빌드란, 모든 명령어가 순차적으로 실행되며 하나의 레벨에서 모든 레이어를 하나씩 추가하며 이미지를 빌드하는 방법이다.

중간 레이어에 빌드 도구, 종속성이 포함되어 최종 이미지의 크기가 커질 수 있다.

레이어 캐싱 활용이 가능하나, 빌드 단계가 많아질수록 변경시 전체 이미지 재빌드 시간이 길어진다.

 

 

도커를 이해하고, 컨테이너에 대한 이해를 높여 쿠버네티스에 대한 이해를 높이자.