[도커] 3장 도커 이미지 만들기

공효은·2023년 5월 16일
0

도커

목록 보기
6/12
post-thumbnail

3.1 도커 허브에 공유된 이미지 사용하기

실습 예제에서는 web-ping이라는 간단한 애플리케이션을 다룬다. 이 애플리케이션은 지정한 웹 사이트가 노출되는지 확인하는 기능을 한다.
컨테이너에서 실행돼 지정된 URL에 HTTP 요청을 3초마다 보내는 동작을 컨테이너가 종료될 때까지 반복한다.

도커 CLI를 통해 명시적으로 원하는 이미지를 내려받을 수 있다.

docker image pull diamol/ch03-web-ping

docker image pull 명령을 실행해 출력된 내용중 흥미로운 부분은 이미지가 저장된 방식을 짐작할 수 있는 부분이다.

이미지를 내려받는 과정을 보면 여러 건의 파일을 동시에 내려받는다는 점에서 단일 파일을 내려받는 과정이 아니라는 것을 알 수 있다. 이들 각각의 파일을 이미지 레이어라고 부른다.

  1. 도커 이미지는 물리적으로는 여러 개의 작은 파일로 구성돼 있다.
  2. 도커가 이들 파일을 조립해 컨테이너의 내부 파일 시스템을 만든다.
  3. 모든 레이어를 내려받고 나면 전체 이미지를 사용할 수 있게된다.

내려받은 이미지로 컨테이너를 실행하고 실행된 애플리케이션의 기능을 확인하자.

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

-d: --detach의 축약형. 이 컨테이너는 백그라운드에서 동작한다. 애플리케이션 역시 인터페이스 없이 배치 잡 처럼 동작한다.
이 컨테이너는 네트워크를 통해 요청을 받지 않는다. 그러므로 포트를 외부로 공개할 필요도 없다.

--name: 컨테이너에 원하는 이름을 붙이고 이 이름으로 컨테이너를 지칭할 수 있다.

이 컨테이너로 실행된 어플리케이션은 저자의 블로그에 반복해서 요청을 보낼 것이다. 무한 루프를 돌며 실행되므로 로그를 확인해보장!

docker container logs web-ping

  • 웹 요청을 보내고 그에 대한 로그를 생성하는 애플리케이션은 요청에 대한 응답 시간을 파악할 수 있다는 점에서 유용하다.
  • 웹 사이트의 동작 여부를 확인하는 용도로도 활용할 수 있다.
  • 애플리케이션에서 대상 URL과 요청간격, 요청 타입 등을 설정할 수 있다. 시스템 환경 변수 값에서 설정값을 읽어온다.

환경 변수

  • 운영체제에서 제공하는 키-값 쌍이다.
  • 아주 적은 양의 데이터를 저장하는 데 유용하다.
  • 도커 컨테이너도 별도의 환경 변수를 가질 수 있다.
  • 이 환경 변수는 호스트 운영체제의 것을 가져오는 게 아니라 컨테이너의 호스트명이나 IP 주소처럼 도커가 부여해준다.
  • web-ping 이미지에도 환경 변수의 기본값이 포함돼있다. 컨테이너를 실행하면 도커가 이들 기본값을 컨테이너에 적용하고 이 값을 애플리케이션에서 사용한다.
  • 컨테이너를 생성할 때 기본값과 다른 값을 환경변수로 설정할 수도 있다. 환경 변수 값을 변경하면 애플리케이션의 동작 내용도 바뀐다.

실행 중인 컨테이너를 삭제하고 환경 변수 TARGET의 값을 다른 값으로 지정한 새로운 컨테이너를 실행한다.

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

새로 실행한 컨테이너의 동작은 아까와 다르다.
1. 이 컨테이너는 --detach 플래그를 적용하지 않았으므로 애플리케이션의 출력 내용이 콘솔에 나타난다. 애플리케이션을 종료할 때까지 출력이 계속될것이다.
2. HTTP 요청을 보내는 대상이 google.com으로 변경 됨

가장 중요한것!

도커 이미지는 설정값의 기본값을 포함해 패키징되지만, 컨테이너를 실행할 때 이 설정값을 바꿀 수 있어야한다.

이미지에는 환경 변수(TARGET)의 값이 blog/sizeyed.comd으로 설정되어있으나 --evn 플래그를 사용해 다른 값을 지정할 수 있다.

호스트 컴퓨터에도 고유한 환경 변수가 있다. 그러나 호스트 컴퓨터의 환경변수는 컨테이터와 별개다. 컨테이너는 도커가 부여한 환경 변수만을 갖는다.

같은 이미지로 띄운 컨테이너는 애플리케이션은 같은 이미지를 사용했고, 같은 바이너리를 실행중이지만, 설정값에 의해 애플리케이션의 동작이 달라진다.

3.2 Dockerfile 작성하기

Dockerfile은 애플리케이션을 패키징하기 위한 간단한 스크립트다. Dockerfile은 일련의 인스트럭션으로 구성돼 있다. 인스트럭션을 실행한 결과로 도커 이미지가 만들어진다.
자주 쓰이는 작업은 별도의 명령이 마련돼 있으며, 원하는 작업을 직접 작성할 수 있고, 표준 셸 문법도 사용가능하다.

*인스트럭션(instruction)은 컴퓨터에게 일을 시키는 단위로서, 컴퓨터가 알아들을 수 있는 기계어로 이루어져 있는 명령이다. 지시 또는 명령이라고 한다.

//web-ping 애플리케이션의 Dockerfile 스크립트
FROM diamol/node
ENV TARGET="blog.sizeyed.com"
ENV METHOD="HEAD"
ENV INTERVAL="3000"

WORKDIR /web-ping
COPY app.js .

CMD ["node", "/web-ping/app.js"]
  • FROM: 모든 이미지는 다른 이미지로부터 출발한다. 이 이미지는 diamol/node 이미지에는 web-ping 애플리케이션을 실행하는 데 필요한 런타임인 Node.js가 설치 돼 있다.
  • ENV: 환경 변수 값을 지정하기 위한 인스트럭션이다. 값을 지정하기 위해 [key]="[value]" 형식을 따른다. 이 스크립트에는 ENV 인스트럭션이 세 번 사용돼 세 개의 환경변수를 설정했다.
  • WORKDIR: 컨테이너 이미지 파일 시스템에 디렉터리를 만들고, 해당 디렉터리를 작업 디렉터리로 지정하는 인스트럭션이다. 리눅스와 윈도 컨테이너 모두 구분자로 슬래시를 사용한다.
    그러므로 스크립트에 나온 인스트럭션은 리눅스 컨테이너에서는 /web-ping 디렉터리를 만들고, 윈도 컨테이너에서는 C:\web-ping 디렉터리를 만든다.
  • COPY: 로컬 파일 시스템의 파일 혹은 디렉터리를 컨테이너 이미지로 복사하는 인스트럭션이다. [원본경로][복사경로] 형식으로 지정하면 된다. 이 스크립트에서는 로컬 파일 시스템에 있는 app.js 파일을 이미지의 작업 디렉터리로 복사했다.
  • CMD: 도커가 이미지로부터 컨테이너를 실행했을 때 실행할 명령을 지정하는 인스트럭션이다. 여기서는 Node.js 런타임이 애플리케이션을 시작하도록 app.js를 지정했다.
cd ch03/exercises/web-ping
ls

이 명령을 실행하면 세 개의 파일이 보일 것이다.

  • Dockerfile(확장자 없음): 스크립트가 담긴 파일이다.
  • app.js: web-ping 애플리케이션을 구현한 Node.js 코드가 담긴 파일이다.
  • README.md: 이 이미지에 대한 정보가 적힌 문서 파일이다.

이렇게 세 개 파일만 있으면 web-ping 애플리케이션의 이미지를 빌드 할 수 있다.

3.3 컨테이너 이미지 빌드하기

이미지를 빌드하려면 Dockerfile 스크립트 외에도 필요한 것이 몇 가지 더 있다. 이미지의 이름, 패키징에 필요한 파일의 경로를 추가로 지정해 주어야한다.

Dockerfile 스크립트로 이미지를 빌드하라!

docker image build --tag web-ping .

--tag의 인잣값 web-ping은 이미지의 이름이고, 이어지는 인자는 Dockerfile 및 이미지에 포함시킬 파일이 위치한 경로다. 도커에서는 이 디렉터리를 컨텍스트라고 한다.
build 명령어를 입력하면 Dockerfile 스크립트에 포함된 인스트럭션이 차례로 실행되며 그 결과가 출력된다.

빌드된 이미지는 로컬 이미지 캐시에 저장되며 도커 명령으로 이미지 목록을 확인하면 볼 수 있다.

새로 빌드한 이미지로부터 컨테이너를 실행해 도커 웹 사이트에 5초마다 요청을 보내보자.

docker container run -e TARGET=docker.com -e INTERVAL=5000 web-ping

이 컨테이너는 포어그라운드(foreground)로 동작하므로 Ctrl + C 로 눌러 중지시킬 수 있다. 그러면 애플리케이션이 종료되고 컨테이너도 종료 상태가 된다.

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

// web-ping 이미지의 히스토리 확인하기
docker image history web-ping

  • CREATED BY 항목은 해당 레이어를 구성한 Dockerfile 스크립트의 인스트럭션이다.
  • Dockerfile 인스트럭션과 이미지 레이어는 1:1 관계를 갖는다.
  • 도커 이미지는 이미지 레이어가 모인 논리적 대상이다.
  • 레이어는 도커 엔진의 캐시에 물리적으로 저장된 파일이다. 이미지 레이어는 여러 이미지와 컨테이너에서 공유되기 때문이다.
  • 만약 Node.js 애플리케이션이 실행되는 컨테이너를 여러 개 실행한다면 이들 컨테이너는 모두 Node.js 런타임이 들어있는 이미지 레이어를 공유한다.
// 출력된 이미지 목록에서 각 이미지의 용량을 확인할 수 있다.
docker image ls 

// 이미지 캐시에 실제 사용된 디스크 용량 확인하기
docker system df

이미지 레이어를 여러 이미지가 공유한다면, 공유되는 레이어는 수정할 수 없어야한다. 수정할 수 있다면 그 수정이 레이어를 공유하는 다른 이미지에도 영향을 미치게 된다.
도커는 이미지 레이어를 읽기 전용으로 만들어 두어 이런 문제를 방지한다. 이미지를 빌드하면서 레이어가 만들어지면 레이어는 다른 이미지에서 재사용 될 수 있다. 하지만 수정할 수 없다.

다음장은 Dockerfile 스크립트를 최적화해 도커 이미지의 용량을 줄이고 빌드를 빠르게 만드는 기법에 활용된다.

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

조금 전에 빌드한 web-ping 이미지에는 애플리케이션이 구현
된 자바스크립트 파일이 들어있다. 이 파일을 수정하고 이미지를 다시 빌드하면, 새로운 이미지 레이어가 생긴다. 도커의 이미지 레이어가 특정한 순서대로만 배치된다고 가정한다. 그래서 이 순서 중간에 있는 레이어가 변경되면 변경된 레이어보다 위에 오는 레이어를 재사용 할 수 없다.

app.js 수정하고 처음 이미지빌드 했을때

  • 복사할 파일의 내용이 변경 됐기 때문에 캐시를 재사용하는 대신 다시 실행됨
  • 그 이후 부터는함께 다시 실행됨 (캐시 활용 x)

한번 빌드하고 똑같이 빌드 했을떄

CMD 인스트럭션은 스크립트 마지막에 위치할 필요가 없다. FROM 인스트럭션 뒤라면 어디에 배치해도 된다. 수정할 일이 잘 없을 것이므로 초반부에 배치하면 된다.
ENV 인스트럭션 하나로 여러 개의 환경 변수를 정의 할 수 있다.

FROM diamol/node

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

ENV TARGET="blog.sixeyed.com" \
    METHOD="HEAD" \
    INTERVAL="3000"
    
WORKDIR /web-ping
COPY app.js
cd ../web-ping-optimized
docker image build -t web-ping:v3 .

이미지 컨테이너를 실행해 보면 동작이 동일하다. 그러나 app.js 파일을 수정하고 이미지를 빌드해 보면, 마지막 단계를 제외하고는 모든 레이어를 캐시에서 재사용한다.

3.6 연습문제

commit 명령어를 사용함
docker commit [컨테이너 id][이미지 name]

도커 컨테이너의 수정된 내용은 컨테이너가 삭제 되면 내용이 사라진다.
컨테이너에서 수정한 내용이 이미지에 영향을 끼치지 않기 떄문이다.
하여, 수정사항이 있을때마다 수정된 컨테이너로 새로운 이미지를 생성해 두어야 컨테이너가 삭제 됐을때 이미지를 통해서 컨테이너를 복구할 수 있다.

profile
잼나게 코딩하면서 살고 싶어요 ^O^/

0개의 댓글