티스토리 뷰
❗️이 글은 엘튼 스톤맨의 "도커 교과서" 교재를 참고하여 작성하였습니다.
이 글에서 지정한 웹 사이트가 노출되는지 확인하는 기능을 하는 "web-ping"이라는 애플리케이션을 만들어보자.
지정된 URL에 HTTP 요청을 3초마다 보내는 동작을 컨테이너가 종료될 때까지 반복하도록 한다.
목차
1. 도커 허브에 공유된 이미지 사용하기
2. Dockerfile 작성하기
3. 컨테이너 이미지 빌드하기
4. 도커 이미지와 이미지 레이어 이해하기
5. 이미지 레이어 캐시를 이용한 Dockerfile 스크립트 최적화
6. 연습
1. 도커 허브에 공유된 이미지 사용하기
📍 이미지를 내려받는 과정
(1) run
: 사용할 이미지가 있는지 확인 후 없다면 자동으로 pull하고 컨테이너를 생성하고 시작한다.
docker container run 이미지 이름
(2) pull
: 도커 CLI를 통해 원하는 이미지만 내려받는다.
docker image pull 이미지 이름
📍 pull 방법을 통해 컨테이너 이미지 받기
docker image pull diamol/ch03-web-ping
이미지 이름은 diamol/ch03-web-ping으로 이 이미지는 도커 허브에 저장된다.
도커 허브는 가장 먼저 이미지를 찾기 위해 접근하는 저장소로 무료로 제공되는 공개 레지스트리이다.

이미지를 내려받는 과정을 보면 여러 개의 파일을 동시에 내려받는 것을 확인할 수 있다.
이런 각각의 파일을 "이미지 레이어" 라고 한다.
도커 이미지는 논리적으로는 하나의 대상이지만, 물리적으로 여러 개의 작은 파일로 구성되어 있다.
도커는 이런 파일들을 조립해 컨테이너의 내부 파일 시스템을 만들어 이미지를 사용할 수 있도록 한다.
📍 받은 이미지로 컨테이너 실행
docker container run -d --name web-ping diamol/ch03-web-ping
- -d 플래그는 --detach의 축약형으로 컨테이너는 백그라운드에서 동작한다.
- --name 플래그를 사용하여 컨테이너에 원하는 이름을 부여할 수 있다.
이 컨테이너로 실행된 애플리케이션은 지정된 URL에 반복해서 HTTP 요청을 보낸다.
컨테이너의 상태를 확인해보자.
docker container logs web-ping

blog.sixeyed.com에 반복적으로 HTTP요청을 보내는 것을 확인할 수 있다.
환경변수는 운영체제에서 제공하는 키-값 쌍이다.
도커 컨테이너도 호스트 os를 가져오는 것이 아닌 컨테이너 호스트명이나 IP 주소처럼 도커가 부여해준다.
컨테이너를 생성할 때 기본 값과 다른 값을 환경변수로 설정할 수 있고, 값을 변경하면 애플리케이션 동작 내용도 바뀐다.
📍 환경 변수 변경
실행 중인 컨테이너를 삭제하고 환경 변수 TARGET 값을 다른 값으로 지정한 새로운 컨테이너를 실행해보자.
docker rm -f web-ping
docker container run --env TARGET=google.com diamol/ch03-web-ping

--env 태그로 컨테이너 실행 시 환경변수를 변경할 수 있다.
환경 변수를 바꾸기 전과 후의 차이점으로,
- --detach 플래그를 적용하지 않아 애플리케이션 출력 내용이 콘솔에 나타난다.
- HTTP 요청을 보내는 대상이 google.com으로 변경되었다.
=> 도커 이미지는 설정값의 기본값을 포함해 패키징되지만, 컨테이너 실행할 때 이 설정값을 바꿀 수 있다.
+++그림 추가
2. Dockerfile 작성하기
📍 Dockerfile
- 애플리케이션을 패키징하기 위한 간단한 스크립트
- 일련의 인스트럭션으로 구성되어 있고, 실행한 결과로 도커이미지가 만들어짐
web-ping의 전체 Dockerfile 스크립트를 살펴보자
FROM diamol/node
ENV TARGET="blog.sixeyed.com"
ENV METHOD="HEAD"
WORKDIR /web-ping
COPY app.js
CMD ["node", "/web-ping/app.js"]
📍 인스트럭션 종류
- FROM
: 도커 이미지의 바탕이 될 베이스 이미지를 지정,
Dockerfile로 이미지를 빌드 할 때 먼저 FROM 인스트럭션으로 지정된 이미지를 받아온다.
- ENV
: 환경 변수 값을 지정, 값을 지정하기 위해 [key]="[value]" 형식을 따른다.
- WORKDIR
: 컨테이너 이미지 파일 시스템에 디렉터리를 만들고, 해당 디렉터리를 작업 디렉터리로 지정
- COPY
: 로컬 파일 시스템의 파일 혹은 디렉터리를 컨테이너 이미지로 복사
- CMD
: 도커가 이미지로부터 컨테이너를 실행했을 때 실행할 명령을 지정
📍 이미지 빌드 위한 web-ping 파일 확인
먼저 https://github.com/gilbutITbook/080258 을 git clone해서 로컬 디렉터리에 가져온다.
다음 명령어를 입력하여 web-ping 디렉터리 안으로 이동한다.
cd ch03/exercises/web-ping
ls
ls를 통해 디렉터리 안에 세 개의 파일이 있는 것을 확인할 수 있다.

app.js의 파일을 확인해보면 다음과 같다.
const https = require("https");
const options = {
hostname: process.env.TARGET,
method: process.env.METHOD
};
console.log(
"** web-ping ** Pinging: %s; method: %s; %dms intervals",
options.hostname,
options.method,
process.env.INTERVAL
);
process.on("SIGINT", function() {
process.exit();
});
let i = 1;
let start = new Date().getTime();
setInterval(() => {
start = new Date().getTime();
console.log("Making request number: %d; at %d", i++, start);
var req = https.request(options, res => {
var end = new Date().getTime();
var duration = end - start;
console.log(
"Got response status: %s at %d; duration: %dms",
res.statusCode,
end,
duration
);
});
req.on("error", e => {
console.error(e);
});
req.end();
}, process.env.INTERVAL);
Node.js 표준 라이브러리를 사용해 환경 변수에 지정된 URL에 HTTP 요청을 보낸다.
3. 컨테이너 이미지 빌드하기
이미지 빌드위해 필요한 것
- Dockerfile 스크립트
- 이미지 이름
- 패키징에 필요한 파일의 경로
📍 이미지 빌드하기
다음 명령을 사용해 Dockerfile 스크립트로 이미지를 빌드해보자.
docker image build --tag web-ping .
--tag의 인잣값 web-ping은 이미지의 이름이고, 뒤에오는 인자는 Dockerfile 및 이미지에 포함시킬 파일 경로이다.
위의 명령에서는 경로를 현재 작업 디렉터리라는 의미로 " . " 입력했다.

build 명령을 입력하면 Dockerfile 스크립트에 포함된 인스트럭션이 차레로 실행되며 그 결과가 출력된다.
build 명령에서 오류가 발생한 경우
- 도커 엔진이 정상적으로 동작 중인지 확인
- 윈도나 맥 환경이면 도커 데스크톱의 상태 확인
- 현재 작업 디렉터리가 정확한지 확인
- build 명령을 정확하게 입력했는지 확인
출력 마지막에 'successfully built', 'successfully tagged'라는 메시지가 나오면 이미지를 성공적으로 빌드한 것이다.
📍이미지 목록 확인
'w'로 시작하는 태그명을 가진 이미지 목록을 확인해보자
docker image ls 'w*'

이렇게 빌드된 이미지는 도커 허브에서 내려받은 이미지와 다음과 같은 내용을 똑같이 사용할 수 있다.
- 이미지에 포함된 애플리케이션
- 환경 변수 이용한 설정 방법
📍 새로 빌드한 이미지로부터 컨테이너 실행
docker container run -e TARGET=docker.com -e INTERVAL=5000 web-ping

- 대상은 docker.com, 요청 간격은 5000ms로 설정
- 이 동작은 foreground에서 동작하므로 ctrl+c를 눌러 중지시킬 수 있다.
4. 도커 이미지와 이미지 레이어 이해하기
📍 web-ping 이미지 히스토리 확인하기
docker image history web-ping

- CREATED BY: 해당 레이어를 구성한 Dockerfile 스크립트의 인스트럭션
- Dockerfile 인스트럭션과 이미지 레이어 => 1:1 관계
📍 Docker Image
- 패키징에 포함시킨 모든 파일
- 여러 메타데이터 정보(이미지가 어떻게 빌드됐는지)
- 이미지 레이어가 모인 논리적 대상

web-ping과 other-app은 서로 diamol/node 이미지 기반으로, 기반 이미지의 운영체제 레이어와 Node.js 런타임을 포함한다.
Dockerfile 스크립트의 FROM 인스트럭션 사용하는 이유이다.
web-ping의 app.js 파일은 몇 KB 정도 크기이다. web-ping 이미지의 전체 용량은 얼마일까?
📍Image 용량 확인하기
docker Image ls
출력된 이미지 목록에서 이미지 용량을 확인할 수 있는데

- 이미지 목록의 SIZE 항목의 수치는 논리적 용량으로 실제 점유하는 디스크 용량이 아니다.
- 다른 이미지와 레이어를 공유하면 디스크 용량을 덜 차지한다.
📍 Image 저장에 사용된 디스크 용량
논리적용량이 아닌 실제 사용된 디스크 용량을 확인하기 위해 다음과 같은 명령을 입력한다.
docker system df

- 다운로드한 이미지의 총량(SIZE): 130.1MB
- 다운로드한 이미지 중 사용하지 않는 용량(RECLAIMABLE): 75.49MB
이렇게 절약되는 디스크 공간은 같은 기반 레이어를 공유하는 애플리케이션의 숫자가 많을 수록 늘어난다.
=> 이미지 레이어를 여러 이미지가 공유한다면, 공유되는 레이어는 수정할 수 없어야 한다.
공유되는 레이어가 수정되면 공유하는 다른 이미지에 영향을 미치기 때문에 이미지 레이어를 읽기 전용으로 만들어 문제를 방지한다.
5. 이미지 레이어 캐시를 이용한 Dockerfile 스크립트 최적화
도커의 이미지 레이어가 특정한 순서대로만 배치된다고 가정했을 때, 순서 중간에 있는 레이어가 변경되면
변경된 레이어보다 위에 오는 레이어를 재사용할 수 없다.
다음 실습을 통해 이해해보자.
📍 새로운 도커 이미지 빌드
ch03-web-ping 디렉터리에 있는 app.js 파일을 수정하고 빌드한다.
docker image build -t web-ping:v2 .

파일을 수정하고 이미지를 빌드하면 새로운 이미지 레이어가 생긴다.
인스트럭션의 결과가 이전 빌드와 같다면, 이전에 캐시된 레이어를 재사용한다.
🔎 캐시에 일치하는 레이어가 있는지 확인하기 위해 해시값 이용
- 해시값은 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
- CMD: 잘 수정하지 않으니 앞에 배치
- ENV: 인스트럭션 하나로 여러 개 환경변수 정의할 수 있어 하나로 합침
새로운 스크립트로 이미지 다시 빌드해보자.
cd ../web-ping-optimized
docker image build -t web-ping:v3 .
7단계의 인스트럭션이 5단계로 줄었지만 결과는 동일하다. 마지막 단계를 제외하고 모든 레이어를 재사용하는 것을 확인할 수 있다.

✏️ 정리
빨리 이미지를 빌드하고 검증된 이미지를 운영환경에 적용시키기 위해 기억할 것 두 가지
- Dockerfile 스크립트 최적화
- 이식성 있는 이미지 만들기
6. 연습 문제
📍 Dockerfile 스크립트 없이 도커 이미지 만들기
Dockerfile의 목적 : 애플리케이션 배포 자동화
다음과 같은 경우에 Dockerfile 스크립트 없이 도커 이미지를 만들어야 한다.
- 자동화 없이 수동으로 직접 배포
- 스크립트로 작성할 수 없는 절차가 필요한 경우
도커 허브에 공유된 diamol/ch03-lab 이미지 안에 /diamol/ch03.txt 파일이 있다.
📍 과제에서 해야할 부분
- ch03.txt 파일 뒤에 자신의 이름을 추가
- 수정된 파일을 포함하는 새로운 이미지를 빌드
🔑 과제 힌트
- -it 플래그를 사용하면 컨테이너 대화식 실행 가능
- 파일 시스템의 컨테이너는 컨테이너가 종료된 후에도 남아있다.
- docker container --help 명령으로 명령어 찾기
📝 문제 풀이
1) diamol/ch03-lab 이미지 내려받기

2) 컨테이너 -it 태그로 대화식 실행

3) ch03.txt에 텍스트 추가

cat 명령어에 >> 옵션을 넣어 입력한 내용을 ch03.txt에 추가해준다.
exit을 입력하여 종료해준다.
4) 변경한 사항으로 새로운 이미지 만들기
다음 명령을 입력하여 container ID를 확인한다.

- commit: 종료된 컨테이너 상태 그대로의 이미지를 생성

5) 새로 생성된 이미지로부터 컨테이너 실행

'Docker' 카테고리의 다른 글
[Docker] 5. Docker volume 이용한 Persistent Storage (0) | 2023.07.22 |
---|---|
[Docker] 4. 레지스트리에 이미지 공유하기 (0) | 2023.07.18 |
[Docker] 3. Application build (0) | 2023.07.08 |
[Docker] 1. Docker란 무엇인가? (수정 중) (0) | 2023.07.05 |