컨테이너와 가상 머신의 차이는, 주로 아키텍처와 자원 관리 방식의 차이에서 비롯된다.
컨테이너는 호스트 운영체제의 커널을 공유하고 자체 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) 레이어들의 스택으로 구성된다. 각 레이어는 이미지의 이전 레이어에 대한 변경 사항을 나타내고, 최종적으로 하나의 컨테이너 파일 시스템을 형성한다.
작동 원리
- 빌드 캐시 사용
- 각 명령어 실행시 생성된 중간 이미지(레이어)를 캐싱하고, 동일 명령어 호출시 캐싱된 이미지(레이어)를 재사용한다.
- 변경 감지
- 도커는 각 레이어가 생성된 명령어와 컨텍스트를 기반으로 캐시된 레이어를 재사용할지 여부를 결정한다.
- 만약 명령어 또는 컨텍스트가 변경되면, 해당 명령어 이후 모든 레이어는 다시 생성된다.
# 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이 복잡해질 수 있음, 설정이 다소 까다로울 수 있음.
싱글 스테이지 빌드란, 모든 명령어가 순차적으로 실행되며 하나의 레벨에서 모든 레이어를 하나씩 추가하며 이미지를 빌드하는 방법이다.
중간 레이어에 빌드 도구, 종속성이 포함되어 최종 이미지의 크기가 커질 수 있다.
레이어 캐싱 활용이 가능하나, 빌드 단계가 많아질수록 변경시 전체 이미지 재빌드 시간이 길어진다.
도커를 이해하고, 컨테이너에 대한 이해를 높여 쿠버네티스에 대한 이해를 높이자.
'Server' 카테고리의 다른 글
[GCP] 기본 설정 및 VM, Object Storage, DB service 생성 및 탐색 (0) | 2024.07.02 |
---|