Programming-[Infra]/Docker

도커 교과서(엘튼 스톤맨, 심효섭) - 2. 도커 이미지 만들기

컴퓨터 탐험가 찰리 2023. 1. 5. 10:22
728x90
반응형

 

1. 도커 허브의 이미지 다운받기

 

docker image pull {이미지 파일 이름}

 

레지스트리(registry)

위 명령어로 도커 허브에 공유되어있는 이미지 파일을 받을 수 있다. 이미지 파일들이 저장된 저장소를 레지스트리라고 하는데, 도커 허브는 무료로 제공되는 공개 레지스트리이다.

 

이미지 파일 구성

이미지 파일은 논리적으로는 하나의 파일처럼 다뤄진다. 그러나 실제로 명령어 입력 시 아래 사진처럼 여러 파일들이 다운로드되는 것을 볼 수 있다. 각각의 파일을 이미지 레이어라고 부른다. 도커는 이미지 레이어들을 조합하여 컨테이너 내부의 파일 시스템을 구성한다.

 

 

2. 컨테이너의 환경 변수 수정하기 : 유연한 방식의 컨테이너 실행

 

docker container run -d -name web-ping diamol/ch03-web-ping

 

-d: detach의 축약형. 따라서 이 앱은 백그라운드로 동작할 것이다. 그리고 애플리케이션의 출력 내용이 콘솔에 나타나지 않는다.

--name: 컨테이너 실행 시 ID값과 name값이 랜덤하게 생성되는데, 이 플래그로 컨테이너의 이름을 직접 지정하여 구분 및 호출이 편하게 만들 수 있다.

 

docker container logs web-ping

 

web-ping이라는 지정한 이름으로 호출했다. 그리고 로그를 보면 web-ping은 특정 웹사이트로 head 요청을 받고 응답값을 출력하는 것을 확인할 수 있다.

 

환경 변수 수정

컨테이너를 실행할 때 환경변수 값을 수정할 수 있다. 즉 이 애플리케이션에서 참조하고 있는 변수값을 수정해서 다르게 동작하게 하는 것이다.

docker rm -f web-ping
docker container run --env TARGET=whitepro.tistory.com diamol/ch03-web-ping

 

기존 web-ping 컨테이너를 -f 옵션으로 강제로 중지 및 삭제한다. --env 플래그로 TARGET이라는 key값을 갖는 환경 변수의 value를 whitepro.tistory.com으로 수정하였다. 또한 -d 플래그가 없으므로 애플리케이션의 실행 결과 콘솔 출력 내용들이 터미널에 출력된다. Ctrl + C로 빠져나올 수 있다.

 

이것은 --env 태그를 통해 컨테이너 실행 시마다 환경변수를 수정하여 다르게 동작하게 할 수 있다는 것이다. 위 예제와 같은 컨테이너를 여러 개 만들어서 여러 사이트에 ping을 요청해볼 수 있을 것이다.

 

 

 

3. Dockerfile로 이미지 만들기

 

교재에 주어진 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 라는 이미지를 기반으로 하는데 여기에는 애플리케이션을 실행하는데 필요한 Node.js를 설치해뒀다고 한다.
  • ENV: 환경 변수들을 지정한다.
  • WORKDIR: 컨테이너의 이미지 파일 시스템에 디렉터리를 만들고 이 디렉터리를 작업 디렉터리로 설정한다.
  • COPY: 로컬 파일이나 디렉터리를 컨테이너의 디렉터리로 복사하는 명령어이다.
  • CMD: 컨테이너를 실행했을 때 실행할 명령어들을 지정한다. 위 코드에서는 Node.js가 app.js라는 파일을 실행하도록 했다.

 

이미지 빌드

교재에서 제공하는 Dockerfile이 포함된 디렉터리 경로에서 다음 명령어를 실행하여 image를 생성한다.

docker image build --tag web-ping .

 

  • --tag: 이미지의 태그를 지정한다.
  • . : 현재 디렉토리 위치를 의마한다.

 

생성된 이미지는 도커 이미지 캐시에 보관된다. 조회는 다음 명령어로 할 수 있다.

docker image ls 'w*'
  • 'w*' : w로 시작하는 태그를 갖는 이미지를 조회

 

확인을 위해 다음 명령어로 image를 실행할 수 있다. 알 수 있겠지만, -e는 --env의 축약어다.

docker container run -e TARGET=whitepro.tistory.com -e INTERVAL=1000 web-ping

 

 

 

4. 이미지와 이미지 레이어

 

이미지 레이어

도커 엔진의 캐시에 저장된 물리적 저장 파일. 이미지는 이런 이미지 레이어들을 기반으로 구성된다. 또한 이미지 레이어는 여러 이미지에 공유될 수 있다. 만약 이미지 레이어가 수정되면 모든 이미지에 영향이 가기 때문에 이미지 레이어는 읽기 전용으로만 관리된다.

 

이미지 생성 이력과 용량

docker image history web-ping

CREATED BY 컬럼을 보면 생성된 각 이미지 레이어들을 확인할 수 있다.

 

SIZE값은 논리적인 용량이다. 앞서 배웠듯 이미지 레이어는 여러 이미지에 공유될 수 있기 때문에 실제로 어떤 이미지가 차지하는 물리적인 메모리 공간은 표현된 SIZE값들의 합보다 작다.

 

docker system df

실제로 이미지가 시스템에서 차지하는 용량을 확인할 수 있다. 

 

 

5. 이미지 레이어 캐시

 

이미지 레이어 캐시 원리

Dockerfile의 인스트럭션(명령어)은 이미지 레이어와 1:1 관계를 갖는다. 확인을 위해 예제의 app.js 파일의 맨 마지막에 빈 줄을 추가해볼 수 있다.

 

vim으로 app.js 파일을 수정하고, 다시 v2로 web-ping 이미지를 빌드해본다.

docker image -t web-ping:v2 .

"CACHED [2/3] WORKDIR /web-ping" 이라는 구문이 보인다. 즉 변경되지 않은 이미지 레이어는 캐시된 곳에서 들고와서 불필요하게 자원을 사용하여 인스트럭션이 실행되지 않도록 해준다.

 

이 검증과정은 (Dockerfile 스크립트의 인스트럭션 + 인스트럭션에 의해 복사되는 파일의 내용)으로부터 계산되는 해시로 비교된다. 다시 말해 인스트럭션과 파일의 내용이 동일하다면 캐시에서 참조한다는 뜻이다.

 

 

이미지 레이어 캐시 주의사항 : Dockerfile 최적화

여러 이미지 레이어를 만드는 단계 중, 특정 단계에서 이미지 레이어가 변경되어 캐시 미스가 발생하면, 도커 엔진은 그 이후의 모든 이미지 레이어는 다시 실행한다. 따라서 Dockerfile의 스크립트는 자주 수정될 인스트럭션은 뒤에 가도록 작성해야한다. 그래야 시간, 디스크 용량, 네트워크 대역폭을 모두 절약할 수 있다.

 

따라서 이 프로젝트의 Dockerfile을 최적화하면 아래와 같이 할 수 있다.

FROM diamol/node

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

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

WORKDIR /web-ping
COPY app.js .

FROM과 CMD문은 잘 변경되지 않을 구문이므로 앞으로 뺀다. 그리고 ENV 인스트럭션은 한 번만 실행해도 여러 값을 넣어줄 수 있으므로 한 번만 작성한다.

 

이렇게 설정하면 app.js 파일의 변경사항이 생기더라도 맨 마지막 인스트럭션만 다시 실행함을 알 수 있다.

 

 

6. 기존 컨테이너에서 이미지 복사

 

교재의 연습문제를 푼 내용이다.

 

Dockerfile을 이용하지 않고 기존 컨테이너의 내용을 바꾸면서 image를 생성할 수 있다.

1. 기존 이미지를 활용하여 container를 실행한다.

2. docker container ls --all로 실행 중이지는 않으나 남아있는 container image를 확인한다.

3. 2에서 확인한 container image를 docker container run -it {container image ID} 명령어로 실행 후, 변경하고자하는 내용을 바꾼다.

4. 

docker container commit 

명령어를 이용하여 기존 container image를 복사한다. 아무런 옵션없이 복사 시, 생성된 image는 Repository와 Tag가 none 상태임을 알 수 있다.

 

docker container --help로 다양한 명령어를 찾아가면서 해결책을 찾자~

728x90
반응형