본문 바로가기
독서/시작하세요! 도커 & 쿠버네티스

3. 도커 이미지

by Thinking 2023. 11. 29.

도커 이미지 생성

사용자만의 이미지를 직접 생성하는 실습을 해보겠습니다. 이미지로 만들 컨테이너를 생성하고, 컨테이너 내부에 first라는 이름의 파일을 하나 생성해 기존의 이미지로부터 변경사항을 만듭니다.

docker commit 명령어를 입력해 컨테이너를 이미지로 만듭니다. 위에서는 이미지의 이름을 commit_test, 태그를 first로 설정했습니다. -a 옵션은 author을 나타내고 이미지의 작성자를 나타내는 메타데이터를 이미지에 포함시킵니다. commit_test:first 이미지의 작성자 데이터는 "alicek106"으로 설정됩니다. 

commit_test 이름에 first라는 태그로 이미지가 생성되었습니다. 이번에는 commit_test:first 이미지로 새로운 이미지를 생성해 봅시다. commit_test:first 이미지로 컨테이너를 생성한 뒤 second라는 파일을 추가해 commit_test:second라는 이미지를 새롭게 생성합니다. 

 

 

이미지 구조 이해

위와 같이 컨테이너를 이미지로 만드는 작업은 commit 명령어로 쉽게 수행할 수 있습니다. docker inspect 명령어는 많은 정보를 출력하지만 가장 주의깊게 볼 것은 Layers 항목입니다. 위 first, second, ubuntu 이미지 크기가 각각 188MB라고 출력돼도 188MB 크기의 이미지가 3개 존재하는 것은 아닙니다. 이미지를 커밋할 때 컨테이너에서 변경된 사항만 새로운 레이어로 저장하고, 그 레이어를 포함해 새로운 이미지를 생성하기 때문에 전체 이미지의 실제크기는 188MB + first 파일의 크기 + second 파일의 크기가 됩니다. first 파일은 commit_test:first 이미지를 생성할 때 사용했던 컨테이너에서 변경된 사항이고, second 파일은 commit_test:second 이미지를 생성할 때 사용했던 컨테이너에 변경된 사항입니다. 

 

 

이미지 추출 & 배포

도커 이미지를 별도로 저장하거나 옮기는 등 필요에 따라 이미지를 단일 바이너리 파일로 저장해야 할 때가 있습니다. docker save 명령어를 사용하면 컨테이너의 커맨드, 이미지 이름과 태그 등 이미지의 모든 메타데이터를 포함해 하나의 파일로 추출할 수 있습니다. -o 옵션에는 추출될 파일명을 입력합니다. 이미지를 생성했다면 이를 다른 도커 엔진에 배포할 방법이 필요합니다. save나 export와 같은 방법으로 이미지를 단일 파일로 추출해서 배포할 수도 있지만 도커 엔진수가 너무 많다면 이는 힘든 방법입니다. 또한 도커의 이미지 구조인 레이어 형태를 이용하지 않으므로 매우 비효율적입니다. 

첫 번째 해결 방법은 도커에서 공식적으로 제공하는 도커 허브 이미지 저장소를 사용하는 것입니다. 도커 허브는 도커 이미지를 저장하기 위한 클라우드 서비스라고 생각하면 좋은데, 사용자는 단지 이미지를 올리고 내려받기만 하면 되므로 매우 간단하게 사용할 수 있습니다.

두 번째 해결 방법은 도커 사설 레지스트리를 사용하는 것으로서 사용자가 직접 이미지 저장소를 만들 수 있습니다. 그러나 사용자가 직접 이미지 저장소 및 사용되는 서버, 저장 공간등을 관리해야 하므로 첫 번째 방법보다는 사용법이 까다롭습니다.

 

* 포그라운드 실행 : 하나의 작업을 실행하면 그 작업이 끝날 때까지 기다리고 다시 또 다른 작업을 실행하는 방식입니다.

* 백그라운드 실행 : 프로세스를 실행시킴과 동시에 다른 작업을 병행할 수 있는 방식입니다.

 

 

Dockerfile 이미지를 생성하는 방법

개발한 애플리케이션을 컨테이너화할 때 가장 먼저 생각나는 방법은 아래와 같습니다.

1. 아무것도 존재하지 않는 이미지로 컨테이너를 생성.

2. 애플리케이션을 위한 환경을 설치하고 소스코드 등을 복사해서 잘 동작하는지 확인

3. 컨테이너를 이미지로 커밋.

 

이 방법을 사용하면 애플리케이션이 동작하는 환경을 구성하기 위해 일일이 수작업으로 패키지를 설치하고 소스코드를 깃에서 복제하거나 호스트에서 복사해야 합니다. 물론 직접 컨테이너에서 애플리케이션을 구동해 보고 이미지로 커밋하기 때문에 이미지의 동작을 보장할 수 있다는 점도 있습니다.

 

 하지만 도커는 빌드 명령어를 제공하고, 완성된 이미지를 생성하기 위해 컨테이너에 설치해야 하는 패키지, 추가해야 하는 소스코드 등을 하나의 파일에 기록해 두면 도커는 이 파일을 읽어 컨테이너에서 작업을 수행한 뒤 이미지로 만들어냅니다. 이러한 작업을 기록한 파일의 이름을 Dockerfile이라 하며, 빌드 명령어는 Dockerfile을 읽어 이미지를 생성합니다. Dockerfile을 사용하면 직접 컨테이너를 생성하고, 이미지로 커밋해야 하는 번거로움을 덜 수 있고, 깃과 같은 개발 도구를 통해 애플리케이션의 빌드 및 배포를 자동화시킬 수 있습니다.

 

 컨테이너에서 작업을 마치고 이미지로 커밋하는 것 보다 애플리케이션을 컨테이너 화하기 위한 장기적인 시점에서 본다면 Dockerfile을 작성하는 것은 이미지를 생성하는 방법을 기록하는 것뿐만 아니라 이미지의 빌드, 배포 측면에서도 매우 유리합니다. 애플리케이션에 필요한 패키지 설치등을 명확히 할 수 있고, 이미지 생성을 자동화할 수 있으며, 쉽게 배포할 수 있기 때문입니다.

 

 

Dockerfile 작성

 Dockerfile에는 컨테이너에서 수행해야 할 작업을 명시합니다. Dockerfile을 사용하기 위한 간단한 시나리오로 웹 서버 이미지를 생성하는 예를 들어 설명하겠습니다. 먼저 이번 절의 예제에서 사용할 디렉터리를 생성하고, 디렉터리 안에 HTML 파일을 미리 만들어 둡니다.

 

Dockerfile 사용되는 명령어는 여러가지가 있지만 기본적으로 FROM, RUN, ADD 등 기본적인 명령어를 알아보겠습니다. 한 줄이 하나의 명령어가 되고, 명령어를 명시한 뒤에 옵션을 추가하는 방식입니다.

 

FROM : 생성할 이미지의 베이스가 될 이미지를 뜻합니다. Dockerfile을 작성할 때 반드시 한 번 이상 입력해야 하며, 이미지 이름의 포맷은 docker run 명령어에서 이미지 이름을 사용했을 때와 같습니다. 사용하려는 이미지가 도커에 없다면 자동으로 pullgkqslek.

 

MAINTAINER : 이미지를 생성한 개발자의 정보를 나타냅니다. 일반적으로 Dockerfile을 작성한 사람과 연락 할 수 있는 이메일 등을 입력합니다. 단 이는 도커 1.13.0 버전 이후로 사용되지 않고 대신 LABEL로 교체해 표현할 수 있습니다.

 

LABEL : 이미지에 메타데이터를 추가합니다. 메타데이터는 '키:값'의 형태로 저장되며, 여러 개의 메타데이터가 저장될 수 있습니다. 추가적인 메타데이터는 docker inspect 명령어로 이미지의 정보를 구해서 확인할 수 있습니다.

 

RUN : 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행합니다. apt-get update와 apt-get install apache2 명령어를 실행한다면 아파치 웹 서버가 설치된 이미지가 생성됩니다. 단 Dockerfile을 이미지로 빌드하는 과정에서는 별도의 입력이 불가능하기 때문에 apt-get install apache2 명령어에서 설치할 것일지를 선택하는 Y/N을 Yes로 설정해야 합니다. 이미지를 빌드할 때 별도의 입력을 받아야 하는 RUN이 있다면 build 명령어는 이를 오류로 간주하고 빌드를 종료합니다.

 

ADD : 파일을 이미지에 추가합니다. 추가하는 파일은 Dockerfile이 위치한 디렉토리인 콘텍스트에서 가져옵니다. 지금은 Dockerfile이 위치한 디렉터리에서 파일을 가져온다고 이해하면 됩니다. ADD 명령어는 JSON 배열의 형태로 ["추가할 파일 이름". "컨테이너에 추가될 위치"]와 같이 사용할 수 있고, 추가할 파일명은 여러 개를 지정할 수 있으며 배열의 마지막 원소가 컨테이너에 추가될 위치입니다.

 

WORKDIR : 명령어를 실행할 디렉터리를 나타냅니다. 배시 셀에서 cd 입력을 하는 것과 같은 기능을 합니다. 예로 WORDIR /var/www/html 이 실행되고 나서 RUN touch test 를 실행하면 /var/www/html 디렉터리에 test 파일이 생성됩니다.

 

EXPOSE : Dockerfile의 빌드로 생성된 이미지에서 노출할 포트를 설정합니다. 그러나 EXPOSE를 설정한 이미지로 컨테이너를 생성했다고 해서 반드시 이 포트가 호스트의 포트와 바인딩되는 것은 아니며, 단지 컨테이너의 80번 포트를 사용할 것임을 나타내는 것뿐입니다. EXPOSE는 컨테이너를 생성하는 run 명령어에서 모든 노출된 컨테이너의 포트를 호스트에서 퍼블리시하는 -P 플래그와 함께 사용됩니다.

 

CMD : CMD는 컨테이너가 실행될 때 마다 실행할 명령어를 설정하여, Dockerfile에서 한 번만 사용할 수 있습니다. Dockerfile에 CMD를 명시함으로써 이미지에 apachectl -DFOREGROUND라는 커맨드를 내장하면 컨테이너를 생성할 때 별도의 커맨드를 입력하지 않아도 이미지에 내장된 위 커맨드가 적용되어 컨테이너가 시작될 때 자동으로 아파치 웹 서버가 실행됩니다. 그리고 아파치 웹 서버는 하나의 터미널을 차지하는 포그라운드 모드로 실행되기 때문에 -d 옵션을 사용해 detached 모드로 컨테이너를 생성해야 합니다. 즉 CMD는 run과 같은 명령어의 이미지 이름뒤에 입력하는 커맨드와 같은 역할을 하지만 docker run 명령어에서 커맨드 명령을 인자로 입력하면 Dockerfile에서 사용한 CMD의 명령어는 run의 커맨드로 덮어 쓰입니다. CMD의 입력은 JSON 배열 형태인["실행 가능한 파일", "명령줄 인자 1", "명령줄 인자 2"] 형태로도 사용할 수 있습니다.

 

 

[Example]

FROM ubuntu:14.04  -> 가장 먼저 FROM에서 Dockerfile에서 사용할 베이스 이미지를 ubuntu:14.04로 설정

MAINTAINER alicek106 -> 이미지 MAINTAINER 이름을 alicek106으로 설정

LABEL "purpose"="practice" -> Dockerfile에서 생성될 이미지의 라벨을 purpose-practice로 설정

RUN apt-get update  -> RUN 명령어를 차례대로 실행해 아파치 웹 서버를 설치

RUN apt-get install apach2 -y     

ADD test.html /var/www/html -> ADD로 Dockerfile이 위치한 디렉터리에서 text.html 파일을 이미지의 디렉터리에 추가

WORKDIR /var/www/html        -> 해당 위치를 옮기고

RUN ["/bin/bash", "-c", "echo hello >> test2.html"]   -> 명령어로 파일을 생성하는데, 해당 위치에 파일이 생성됩니다.

EXPOSE 80                 -> 마지막으로 EXPOSE로 컨테이너가 사용해야 할 포트를 80번으로 설정하고

CMD apachect1 -DFROEGROUN            -> 컨테아너의 명령어를 apachect1 -DFOREGROUND로 설정해 이미지 빌드 마침. 

'독서 > 시작하세요! 도커 & 쿠버네티스' 카테고리의 다른 글

6. 도커 데몬  (2) 2023.12.07
5. Dockerfile 명령어  (3) 2023.12.02
4. Dockerfile 빌드  (0) 2023.11.30
2. 도커 볼륨 & 도커 네트워크  (1) 2023.11.28
1. 도커  (4) 2023.11.24