- 도커 이미지 생성 순서 및 원리를 이해한다.
- Dockerfile에 대해 이해하고, 이를 활용하여 도커 이미지 생성을 수행한다.
- 도커 이미지를 생성할 때에 직접 네이밍이 가능하다는 것을 이해한다.
- 순서는 아래와 같다.
- Dockerfile -> 도커 클라이언트 -> 도커 서버 -> 이미지 생성
- 우선 도커 파일에 입력된 것들이 도커 클라이언트에 전달이 된다.
- 도커 클라이언트에 전달된 중요한 작업을 도커 서버가 수행하게 된다.
- 도커 서버에서 필요한 작업을 다 진행하고 나면, 결국 이미지가 생성이 된다.
$ docker build .
$ docker run -it 2ea97da6bcfc5fc7983dee3050ae199ce60d8727f01a5
- Dockerfile이란 도커 이미지를 만들기 위한 설정 파일이라 할 수 있다.
- 컨테이너가 어떻게 동작해야 할지를 사전에 정의해줄 수 있다.
- 때문에 도커 파일 생성을 위해선, 우선 도커 이미지가 필요로 하는 것이 무엇인지를 알아야 한다.
- 도커 이미지는 크게 두 가지 구역으로 구분된다.
- 시작 명령어
- 파일 스냅샷
- 따라서 Dockerfile에 아래와 같은 작업이 요구된다.
- 컨테이너 시작시 실행 될 명령어를 명시해준다. (시작시 명령어에 해당)
- 베이스 이미지를 명시해준다. (파일 스냅샷에 해당)
- 추가적으로 필요한 파일을 다운 받기 위한 몇가지 명령어를 명시해준다. (파일 스냅샷에 해당)
실습을 통해 이해해보자.
- "hello world" 출력하기를 수행해보자.
- 실습 순서는 다음과 같다.
- 도커 파일을 만들 폴더 하나를 만든다. ex) mkdir dockerfile-folder
- 위에서 생성한 도커 파일 폴더를 VsCode로 실행한다.
- CLI나 혹은 VsCode를 이용해 Dockerfile을 생성한다. ex) touch Dockerfile
- 그리고 Dockerfile의 기본 구조를 살펴보고, 필요한 키워드와 명령어를 기입한다.
- Dockerfile -> 도커 클라이언트 -> 도커 서버를 거쳐 이미지를 생성하도록 수행한다. ex) docker build .
- 생성된 이미지를 활용하여 hello world를 출력한다. ex) docker run -it {이미지 아이디}
- Dockerfile 기본 구조는 아래와 같다.
- FROM
- 이지미 생성시 기반이 되는 이미지 레이어(베이스 이미지)를 넣는다.
- {이미지 이름} {태그} 형식으로 작성한다.
- 태그는 버전이다. 태그를 안붙이면 자동적으로 가장 최신의 것으로 다운 받는다.
- RUN
- 도커 이미지가 생성되기 전에 수행되는 쉘 명령어이다.
- 추가적으로 필요한 파일들을 다운로드 받는다. (없으면 주석 처리를 하면 된다.)
- CMD
- 도커 컨테이너가 시작되었을 때 실행할 실행파일 혹은 쉘 스크립트이다.
- 해당 명령어는 DockerFile 내에서 단 1회만 사용할 수 있다.
- 위에서 RUN 부분만 주석처리하고, Dockerfile을 도커 클라이언트에 전달하여 도커 서버가 인식하게 하려면 아래와 같은 명령어를 사용해야 한다.
- docker build .
- docker build는 자동으로 알아서 Dockerfile부터 찾고 그 내용에 맞게 build를 진행해준다.
- 이미 alpine 캐싱되어 있는 이미지이기 때문에 새롭게 빌드하는 작업이 없다.
- 그래도 새로운 이미지 writing은 정상적으로 이루어졌고, 이미지 아이디 값도 sha256 옆에 생성이 되었다.
- 생성된 이미지를 실행하여 컨테이너를 생성함과 동시에 출력해보자.
- docker run -it {이미지 아이디}
- 정상적으로 출력됨을 확인할 수 있다.
- 참고 1: 베이스 이미지란 무엇일까?
- 도커 이미지는 여러 개의 레이어로 구성되어 있다.
- 이미지 안에 무언가 추가적인 요소를 넣으면 레이어가 하나 더 쌓인다고 할 수 있다.
- 그런 레이어들 중에서 가장 근본이자 기본이 되는 것이 베이스 이미지이다.
- 즉, 베이스 이미지는 생성할 이미지의 기반이 되는 부분이다. (OS라고 생각하면 된다. Window, MacOs, Linux 등)
- 참고 2: docker build ./ 를 통해 무슨일 일어나는 것일까?
1) 베이스 이미지를 다운로드 받는다.
2) 그리고 임시 컨테이너를 만든다.
3) 베이스 이미지에 들어있는 파일 스냅샷을 참고하여, 파일과 레이어들을 임시 컨테이너의 하드 디스크에 올린다.
4) 베이스 이미지에 있는 시작 명령어도 임시 컨테이너의 명령어 영역에 올린다.
5) 새로운 이미지를 만든다.
6) 임시 컨테이너에 들어온 명령어를 새로운 이미지의 시작명령어로 적용시킨다.
7) 동시에 임시 컨테이너에 들어온 파일 및 레이어들을 참고하여, 새로운 이미지의 파일 스냅샷으로 적용시킨다.
8) 최초에 받아온 베이스 이미지와 비슷하지만, 엄연히 다른 새로운 이미지가 생성되었다. (이미지 ID 값 다름)
9) 임시 컨테이너는 삭제된다.
(임시 컨테이너는 새로운 이미지를 만들기 위해, 그야말로 일시적으로 만들어진 컨테이너일 뿐인다.)
- 참고 3: 만약 Dockerfile을 개발 및 상용환경으로 분리하여 적용하고자 한다면 고려해야할 점은 무엇일까?
- 우선 당연히 Dockerfile을 따로 작성해야 한다.
- 가령 Dockerfile.dev(개발)와 Dockerfile(상용)으로 파일명을 나눌 수 있을 것이다.
- 다만 docker build ./는 기본적으로 Dockerfile만 자동으로 인식해준다. 따라서 Dockerfile.dev를 인식하게 해주려면 명령어 옵션을 추가해줘야 한다.
- 형식은 다음과 같다.
- docker build -f {도커파일명} ./
- -f 옵션은 빌드할때 쓰일 도커파일을 임의로 지정해주는 옵션이다.
- ex) docker build -f Dockerfile.dev ./
$ docker build -t bakumando/helloworld:latest ./
$ docker run -it bakumando/helloworld:latest
- 사실 docker run -it {이미지 아이디}에서 {이미지 아이디} 값을 계속해서 사용하는 건 쉽지 않은 일이다.
- 그래서 새롭게 이미지를 생성할 때에 이름을 부여할 수 있다.
곧장 실습으로 들어가보자.
- 우선 이미지 생성을 해보자.
- 어려울 거 없다. build 단계에서 추가적인 키워드를 사용해주면 된다.
- docker build -t {네이밍한 이미지 이름} .
- writing 및 naming이 정상적으로 이루어졌음을 알 수 있다.
- 이미지 실행은 더 쉽다. {이미지 아이디} 대신에 {네이밍한 이미지 이름}을 넣어주면 된다.
- docker run -it {네이밍한 이미지 이름}
- 참고 1: 도커 이미지 네이밍 시에 효과적인 방법 혹은 규칙이 있을까?
- 기본 예시) docker build ./
- 네이밍 예시) docker build -t bakumando/helloworld:latest ./
- 중간에 볼드 효과가 들어간 부분만 새롭게 추가되었음을 알 수 있다.
- 아래와 같은 규칙이 적용된 것이며, 이게 보편적이고 간편한 방식이라 할 수 있다.
- -t {나의 도커 아이디}/{저장소or프로젝트이름}:버전
- -t는 옵션을 주겠다는 명령어 이다.
- 그 이후에는 굳이 설명하지 않아도 무엇이 들어가는 것인지를 이해할 수 있을 것이다.
- {나의 도커 아이디}와 {저장소or프로젝트이름}는 사이는 /(슬래쉬)를 넣어서 구분한다.
- {저장소or프로젝트이름}와 버전 사이는 :(콜론)을 넣어 구분한다.