Overview
오늘은 Dockerfile과 Layer에 대해서 알아보려고 한다.
2023.04.24 - [IaC/Container] - Dockerfile이란?
Dockerfile 빌드 원칙 & Layer
Dockerfile은 Docker 이미지를 빌드하는 방법에 대한 일련의 지침을 포함하는 스크립트이다. Docker 이미지는 일련의 Layer로 구성되며, 각각은 Dockerfile의 지침을 나타낸다. 빌드 원리와 Layer를 이해하는 것은 효율적이고 관리하기 쉬운 Docker 이미지를 만드는 데 중요하다.
Dockerfile 빌드원칙
1. 기본 이미지: 도커 파일은 일반적으로 FROM 명령을 사용하여 지정된 기본 이미지로 시작합니다. 이 기본 이미지는 운영 체제(예: ubuntu) 또는 언어 런타임(예: node)과 같은 시작 지점이다.
FROM ubuntu:latest
2. Instruction: Dockerfile에는 Docker가 이미지를 빌드하기 위해 실행하는 Instruction이 있다.
- `RUN`: 셸에서 명령을 실행
- `COPY` 또는 `ADD`: 호스트 머신의 파일을 Docker 이미지로 복사
- `WORKDIR` : 후속 지침에 대한 작업 디렉토리를 설정
- `ENV` : 환경 변수를 설정
- `EXPOSE`: 컨테이너가 런타임에 지정된 네트워크 포트에서 수신 대기한다는 것을 Docker에 알림
- `CMD` 또는 `ENTRYPOINT`: 컨테이너가 시작될 때 실행할 명령을 지정
RUN apt-get update && apt-get install -y nginx
COPY index.html /var/www/html/
3. Layer: Dockerfile의 각 명령어는 Docker 이미지에 새 Layer를 만든다. Layer는 서로 위에 쌓여 최종 이미지를 형성한다. Docker는 유니온 파일 시스템을 사용하여 이러한 Layer를 단일의 통합된 뷰로 결합한다.
4. Caching: Docker는 빌드 프로세스를 최적화하기 위해 Layer를 Caching 한다. Layer 가 변경되지 않은 경우 Docker는 캐시된 Layer를 다시 빌드하는 대신 재사용한다. 이렇게 하면 후속 빌드 속도가 빨라진다.
5. 최종 이미지: 최종 Docker 이미지는 Dockerfile 명령어로 구성된 누적 Layer의 결과이다.
Docker Layer
Docker 이미지는 일련의 읽기 전용 Layer로 구성된다. 각 Layer는 이미지의 Dockerfile에 있는 명령을 나타낸다. Docker가 이미지를 빌드할 때 Dockerfile에 있는 명령을 따르고 파일 시스템을 수정하는 각 명령에 대해 새 Layer를 만든다.
Layer의 작동 방식
- 기본 Layer : 도커 파일의 `FROM` 지시문은 기본 이미지를 지정한다. 이 기본 이미지 자체는 여러 Layer로 구성되며, 이는 도커 파일의 지시문의 결과이다. 이 기본 이미지의 각 Layer은 파일, 디렉터리 및 기타 파일 시스템 개체 집합을 이미지에 추가한다.
- Layer 추가 : 파일 시스템을 수정하는 각 후속 Dockerfile 명령은 이전 Layer 위에 새 Layer을 만든다.
- `RUN` : 명령을 실행하면 파일 시스템의 변경 사항이 새 Layer에 저장된다.
- `COPY` 및 `ADD`: 로컬 머신이나 URL에서 파일을 각각 이미지로 복사하여 새 Layer를 만든다.
- `ENV` : 환경 변수를 설정한다. `ENV` 파일을 추가하지는 않지만, 이 환경적 변화를 캡슐화하는 Layer를 만든다.
- Layer 스토리지 : 각 Layer는 별도로 저장되고, Docker 레지스트리에서 이미지를 끌어올 때 Docker는 시스템에 아직 없는 Layer만 다운로드한다. 이는 이미지가 시스템 간에 공유되거나 유사한 기본 이미지에 기반하여 구축될 때 전송해야 하는 데이터 양을 크게 줄여준다.
Layer의 이점
- 재사용성(Reusability): Layer는 여러 이미지에서 재사용될 수 있어 디스크 공간을 절약하고 이미지 다운로드 속도를 높인다. 예를 들어, 여러 이미지가 동일한 기본 이미지에서 파생된 경우 해당 기본 Layer는 서버 또는 로컬 머신에 한 번만 저장하면 된다.
- 효율성(Efficiency): 빌드 프로세스 중에 Docker가 명령어가 변경되지 않았고 컨텍스트(the combination of its contents and the effects of previous layers)가 동일하다고 판단하면 캐시된 Layer를 다시 만드는 대신 재사용한다. 이렇게 하면 빌드가 훨씬 더 빨라진다.
- 불변성(Immutability): Layer가 생성되면 변경할 수 없다. 이 불변성 측면은 이미지를 끌어와 다른 이미지의 기반으로 사용하더라도 기본 이미지가 변경되지 않아 안정적이고 일관된 기반을 제공한다는 것을 보장한다.
Layer Caching
Caching은 Docker Layer의 핵심 기능이다. 이미지를 다시 빌드할 때 Docker는 Dockerfile의 각 명령어를 이전에 빌드된 Layer의 캐시와 비교한다.
- 명령어와 해당 컨텍스트가 변경되지 않으면 Docker는 캐시의 기존 Layer를 사용하여 빌드 프로세스를 가속화한다.
- 변경 사항이 있으면 Docker는 해당 Layer와 그 이후의 모든 Layer를 다시 빌드한다. 변경 사항이 이후 명령의 결과에 영향을 미칠 수 있기 때문이다.
Example to Visualize Layers
1. Standard
FROM ubuntu:18.04
RUN apt-get update && apt-get install -y python3
COPY . /app
WORKDIR /app
RUN pip3 install -r requirements.txt
CMD ["python3", "app.py"]
- `FROM` 문은 Ubuntu 18.04 이미지의 Layer로 시작한다.
- `RUN apt-get update...` 는 Python이 설치된 새 Layer를 만든다.
- `COPY . /app` 는 응용 프로그램의 소스 코드를 포함하는 새 Layer를 추가한다.
- `WORKDIR` 은 작업 디렉토리를 변경하여 중요한 변경 사항을 추가하지는 않지만 계층의 메타데이터를 변경할 수 있다.
- 다른 `RUN` 은 종속성을 설치하여 다른 Layer를 만든다.
- `CMD` 는 파일 시스템을 변경하지 않으므로 일반적으로 새로운 Layer를 추가하지 않고 컨테이너가 시작될 때 실행할 명령을 설정한다.
2. Multi Stage
Multi Stage 빌드 방식은 빌드 환경과 프로덕션 환경을 분리하여 최종 이미지를 더 작고 효율적으로 만든다.
# Build stage
FROM node:12 as build
WORKDIR /app
COPY . .
RUN npm install && npm run build
# Production stage
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
- Build Stage
- `FROM node:12 as build` : Node.js 12 이미지로 시작하여 첫 번째 Layer를 만든다.
- `WORKDIR /app` : 작업 디렉토리를 /app으로 설정한다. 이는 중요한 변경 사항을 추가하지 않지만 계층의 메타데이터를 변경한다.
- `COPY . .` : 현재 디렉토리의 모든 파일을 컨테이너의 /app 디렉토리에 복사하여 새 Layer를 추가한다.
- `RUN npm install && npm run build` : 종속성을 설치하고 애플리케이션을 빌드하여 새 Layer를 만든다. 이 Layer는 Node.js 모듈과 빌드된 애플리케이션 파일을 포함한다.
- Production Stage
- `FROM nginx:alpine` : Nginx Alpine 이미지로 시작하여 새로운 초기 Layer를 만든다. 이는 매우 경량의 Nginx 웹 서버를 포함한다.
- `COPY --from=build /app/build /usr/share/nginx/html` : 이전 빌드 단계에서 생성된 /app/build 디렉토리의 내용을 Nginx의 기본 HTML 디렉토리에 복사하여 새 Layer를 추가한다. 이 Layer는 정적 웹 사이트 파일을 포함한다.
Reference
'IaC > Container' 카테고리의 다른 글
Docker Compose: 컨테이너화된 애플리케이션 구성 및 실행 가이드 (0) | 2024.05.02 |
---|---|
Dockerfile 보안 설정(Hadolint) (0) | 2024.02.25 |
Dockerfile이란? (0) | 2023.04.28 |
Docker(CentOS 7.9) (0) | 2022.03.21 |
docker(Ubuntu 20.04) / Portainer (0) | 2022.02.04 |