본문 바로가기

Tech/Infra&Devops

[Docker] 도커 교과서 3장 - 도커 이미지 만들기

 

Dockerfile

Dockerfile은 애플리케이션을 패키징하기 위한 간단한 스크립트

일련의 인스트럭션으로 구성되어 있는데, 인스트럭션을 실행한 결과로 도커 이미지가 만들어진다.

 

인스트럭션은 다음과 같다. 

 

- FROM : 이미지의 시작 지점을 선언 (모든 이미지는 다른 이미지로부터 출발함)

- ENV : 환경 변수 값을 지정하기 위한 인스트럭션. [key]="[value]" 형식을 따른다.

- WORKDIR : 컨테이너 이미지 파일 시스템에 디렉터리를 만들고, 해당 디렉터리를 작업 디렉터리로 지정하는 인스트럭션

- COPY : 로컬 파일 시스템의 파일 혹은 디렉터리를 컨테이너 이미지로 복사하는 인스트럭션. [원본 경로] [복사 경로] 형식을 따른다. 

- CMD : 도커가 이미지로부터 컨테이너를 실행했을 떄 실행할 명령을 지정하는 인스트럭션

 

컨테이너 이미지 빌드하기

docker image build --tag {이미지명} {path}

 

path는 도커가 필요한 빌드 컨텍스트 정보를 찾는 위치로, 자리에 . 을 입력하면 '현재 작업 디렉터리'에서 찾도록 함. Dockerfile이 없는 경로를 입력하면 "ERROR: failed to solve: failed to read dockerfile: open Dockerfile: no such file or directory" 에러가 발생함

 

해당 명령을 입력하면 Dockerfile 스크립트에 포함된 인스트럭션이 차례로 실행되며 그 결과가 출력됨

 

아래 명령을 통해 이미지가 잘 생성된 것을 확인할 수 있다.

docker image ls

 

 

도커 이미지와 이미지 레이어 이해하기

- 도커 이미지는 이미지 레이어가 모인 논리적 대상이다.

- 레이어는 도커 엔진의 캐시에 물리적으로 저장된 파일이다.

- 이미지 레이어는 여러 이미지와 컨테이너에서 공유된다.

 

이미지의 히스토리를 다음과 같이 확인할 수 있는데 이 명령을 입력하면 한 줄마다 한 레이어에 대한 정보가 출력된다.

docker image history {이미지명}

 

이미지 레이어가 여러 이미지와 컨테이너에서 공유된다는 말은 말 그대로 디스크 용량을 공유하는 것과 같다.

'docker system df'로 SIZE를 확인해보면 실제 docker image ls 로 명시된 전체 이미지 용량보다 작은 것을 알 수 있다.

 

이미지 레이어를 여러 이미지가 공유한다면, 공유되는 레이어는 수정할 수 없다. 해당 레이어를 공유하는 다른 이미지에 영향을 미치기 때문

도커는 이미지 레이어를 읽기 전용으로 만들어 이 문제를 방지한다.

 

 

이미지 레이어 캐시를 이용한 Dockerfile 스크립트 최적화

Dockerfile 스크립트의 인스트럭션은 각각 하나의 이미지 레이어와 1:1로 연결된다. 그러나 인스트럭션의 결과가 이전 빌드와 같다면, 이전에 캐시된 레이어를 재사용한다. 똑같은 인스트럭션을 다시 실행하는 낭비를 줄일 수 있다. 

 

도커는 캐시에 일치하는 레이어가 있는지 확인하기 위해 해시값을 이용한다.

기존 이미지 레이어에 해시값이 일치하는 것이 없다면 캐시 미스가 발생하고 해당 인스트럭션이 실행된다.

한번 인스트럭션이 실행되면 그 다음에 오는 인스트럭션은 수정된 것이 없더라도 모두 실행된다.

> 때문에 Dockerfile 스크립트의 인스트럭션은 잘 수정하지 않는 인스트럭션이 앞으로 오고 자주 수정되는 인스트럭션이 뒤에 오도록 배치하는 것이 좋다. (이미지 공유 과정 시간 및 디스크 용량, 네트워크 대역폭 절약)

 

// 최적화 전
FROM diamol/node

ENV TARGET="blog.sixeyed.com"
ENV METHOD="HEAD"
ENV INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .

CMD ["node", "/web-ping/app.js"]%


// 최적화 후 
FROM diamol/node

CMD ["node", "/web-ping/app.js"]  // CMD가 마지막에 올 필요는 없음

ENV TARGET="blog.sixeyed.com" \   // ENV를 하나로 묶어 하나의 인스트럭션으로 관리할 수 있음
    METHOD="HEAD" \
    INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .%

 

상대적으로 자주 수정될 여지가 있는 app.js를 맨 뒤로 보냄으로써 마지막 단계를 제외한 모든 레이어를 캐시에서 재사용할 수 있다.

반응형

'Tech > Infra&Devops' 카테고리의 다른 글

[Docker] 자주 사용하는 Docker 명령어 모음집  (0) 2024.03.17