Dockerfile

Q·2022년 7월 25일
0

Docker

목록 보기
10/14

Contents

  • 이미지를 생성하는 방법
  • Dockerfile 작성
  • Dockerfile 빌드
    - 이미지 생성
    - 빌드 과정
  • Dockerfile로 빌드할 때 주의할 점

1. 이미지를 생성하는 방법

개발한 어플리케이션을 컨테이너화할 때, 기본적인 방법은 다음과 같습니다.

  1. 아무것도 존재하지 않는 이미지(ex, 우분투)로 컨테이너를 생성

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

  3. 컨테이너를 이미지로 commit

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

도커는 위와 같은 일련의 과정을 손쉽게 기록하고 수행할 수 있는 빌드(build) 커맨드를 제공합니다.

완성된 이미지를 생성하기 위해 컨테이너에 설치해야하 하는 패키지, 추가해야 하는 소스코드, 실행해야 하는 명령어와 쉘 스크립트 등을 하나의 파일에 기록해두면, 도커는 이 파일을 읽어서 컨테이너에서 작업을 수행한 뒤 이미지로 만듭니다.

이러한 작업을 기록한 파일의 이름을 Dockerfile이라고 하며, 빌드 명령어는 Dockerfile을 읽어서 이미지를 생성합니다.

Dockerfile을 사용하면 직접 컨테이너를 생성하고 이미지로 커밋해야 하는 번거로움을 덜어줄 뿐만 아니라 깃과 같은 개발도구를 통해 어플리케이션의 빌드 및 배포를 자동화할 수 있다.

Dockerfile은 어플리케이션을 개발하는 용도 외에도 여러 목적으로 사용할 수 있습니다.

생성한 이미지를 도커 허브 등을 통해 배포할 때, 이미지 자체를 배포하는 대신 이미지를 생성하는 방법을 기록해 놓은 Dockerfile을 배포할 수 있다. 특히 배포되는 이미지를 신뢰할 수 없거나 직접 이미지를 생성해서 사용하고 싶다면 도커 허브에 올려져있는 Dockerfile로 빌드하는 것도 하나의 방법이 됩니다.

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

2. Dockerfile 작성

Dockerfile에는 컨테이너에서 수행해야 할 작업을 명시하는데, Dockerfile을 작성하기 위해서는 Dockerfile에 사용되는 명령어를 알아야합니다. 도커를 위한 특수한 파일인만큼 기존의 스크립트 언어와 비교했을 때 완전히 새로운 방식으로 쓰이지만, 컨테이너에서 사용되는 기초적인 명령어를 알기 쉽게 변환한 것으므로 어렵지 않게 습득할 수 있습니다.

웹 서버 이미지 생성 예제

간단한 웹 서버 이미지를 생성하는 예로 살펴보도록 하겠습니다.

먼저 예제에 사용할 디렉토리를 생성하고 디렉토리 안에 HTML 파일을 미리 만들어 둡니다.

1. mkdir dockerfile && cd dockerfile
2. echo test >> test.html

새롭게 생성한 디렉토리 안에서 아래의 내용으로 Dockerfile이라는 이름의 파일을 저장합니다.

1. FROM ubuntu:18.04
2. MAINTAINER changjunlee
3. LABEL "purpose"="practice"
4. RUN apt update
5. RUN apt install apache2 -y
6. ADD test.html /var/www/html
7. WORKDIR /var/www/html
8. RUN ["/bin/bash", "-c", "echo hello >> test2.html"]
9. EXPOSE 80
10. CMD apachectl -DFOREGROUND

위 Dockerfile은 이미지에 아파치 웹 서버를 설치한 뒤, 로컬에 있는 test.html 파일을 웹 서버로 접근할 수 있는 컨테이너의 디렉토리인 /var/www/html로 복사합니다.

Dockerfile에서 사용되는 명령어는 여러가지가 있지만, 우선 위에서 사용한 FROM, RUN, ADD 등의 기초적인 명령어를 우선적으로 살펴보도록 하겠습니다. Dockerfile은 한 줄이 하나의 명령어가 되고, 명령어를 명시한 뒤에 옵션을 추가하는 방식입니다. 명령어는 소문자로 표기해도 상관없지만 보통 대문자로 표기합니다.

위 예제에서 사용된 명령어에 대한 설명은 다음과 같습니다.

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

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

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

  • RUN : 이미지를 만들기 위해 컨테이너 내부에서 명령어를 실행합니다. 위 예제에서는 apt update와 apt install apache2 명령어를 실행하기 때문에 아파치 웹 서버가 설치됩니다.
    (단, Dockerfile을 이미지로 빌드하는 과정에서 입출력이 불가능하기 때문에 Y/N 옵션 선택을 미리 -y 옵션으로 선택해놓아야 합니다. 만약 별도의 입력을 받아야 한다면 build 명령어는 이를 오류로 간주하고 빌드를 종료합니다.)

  • ADD : 로컬 파일을 이미지에 추가합니다. 추가하는 파일은 Dockerfile이 위치한 디렉토리인 컨텍스트(Context)에서 가지고 옵니다. 컨텍스트는 뒤에서 설명하도록 하겠습니다.
    예제에서는 Dockerfile이 위치한 디렉토리에서 test.html 파일을 이미지의 /var/www/html 디렉토리에 추가합니다.
    ADD 명령어는 JSON 배열의 형태로 ["추가할 파일이름", ... "컨테이너에 추가될 위치"]와 같이 사용할 수 있습니다. 추가할 파일은 여러 개 지정할 수 있습니다.

  • WORKDIR : 명령어를 실행할 디렉토리를 나타냅니다. bash에서 cd 명령어를 입력하는 것과 동일하며, 여기에서는 /var/www/html을 현재 디렉토리로 설정하였습니다. (여러번 사용하면 cd를 여러번 사용하는 것과 동일합니다.)

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

  • CMD : CMD는 컨테이너가 시작될 때마다 실행할 명령어(커맨드)를 설정하며, Dockerfile에서 한 번만 사용할 수 있습니다. Dockerfile에서 CMD를 명시함으로써 이미지에 apachectl -DFOREGROUND라는 커맨드를 내장하게 되고, 이 때문에 컨테이너를 생성할 때 별도의 커맨드를 입력하지 않아도 이미지에 내장된 apachectl -DFOREGROUND 커맨드가 적용되어서 컨테이너가 시작될 때 자동으로 아파치 웹 서버가 실행됩니다. (아파치웹서버는 하나의 터미널을 차지하는 포그라운드 모드로 실행되기 때문에 -d 옵션을 사용해 detached 모드로 컨테이너를 생성해야 합니다.)
    CMD의 입력은 JSON 배열 형태인 ["실행 가능한 파일", "명령줄 인자1", "명령줄 인자2" ...]의 형태로도 사용할 수 있습니다. CMD는 ENTRYPOINT의 명령줄 인자로 사용될 수 있는데, 명령어 관련은 다른 글에서 추가로 설명하도록 하겠습니다.

3. Dockerfile 빌드

3.1. 이미지 생성

위에서 만든 Dockerfile을 빌드해보겠습니다. 명령어는 다음과 같습니다.

docker build -t mybuild:0.0 ./

-t 옵션은 생성될 이미지의 이름을 설정합니다. 위 명령을 실행하면 mybuild:0.0 이라는 이름의 이미지가 생성됩니다. -t 옵션을 사용하지 않으면 16진수 형태의 이름으로 이미지가 생성되므로 가급적이면 -t 옵션을 사용하는 것이 좋습니다.build 명령어의 끝에는 Dockerfile이 저장된 경로를 입력합니다. 일반적으로 로컬에 저장된 Dockerfile을 사용하지만 외부 URL로부터 Dockerfile의 내용을 가져와 빌드할 수도 있습니다. 이 예시에서는 로컬에 Dockerfile을 저장했으므로 현재디렉토리인 ./ 를 입력했습니다.

빌드가 시작되면 위의 내용이 출력됩니다.

빌드가 끝나면 최종적으로 mybuild:0.0이라는 이름의 이미지가 생성됩니다. 이 이미지에서 아파치 웹 서버가 설치되어 있으며, 컨테이너가 시작될 때 웹 서버를 실행하도록 CMD를 설정했기 때문에 별다른 설정없이도 웹 서버가 실행됩니다.

아래 명령어로 컨테이너를 생성해보겠습니다.

docker run -d -P --name myserver mybuild:0.0

-P 옵션은 이미지에 설정된 EXPOSE의 모든 포트를 호스트에 연결하도록 설정합니다. Dockerfile에서 EXPOSE를 80번으로 설정했기 때문에, 컨테이너의 80번 포트를 사용하게 됩니다.

Dockerfile에 이미지의 라벨을 purpose=practice로 설정했는데, 이는 docker images 커맨드에 라벨을 적용하여 검색할 수 있습니다.

docker images --fileter "label=purpose=practice"

라벨은 도커 이미지뿐만 아니라 컨테이너, 도커 엔진 등에도 메타데이터를 추가할 수 있는 유용한 방법입니다.
컨테이너는 docker run 명령어에서 --label 옵션을 사용하여 추가할 수 있고, docker ps 명령어에서 >--filter 옵션을 적용하여 검색할 수 있습니다. 부가적인 정보를 추가함으로 원하는 조건의 컨테이너나 이
미지 등을 쉽게 찾을 수 있습니다.

3.2. 빌드 과정

3.2.1. 빌드 컨텍스트

이미지 빌드를 시작하면 도커는 먼저 빌드 컨텍스트를 읽습니다. 빌드 컨텍스트는 이미지를 생성하는데 필요한 각종 파일, 소스코드, 메타데이터 등을 담고 있는 디렉토리를 의미하며, Dockerfile이 위치한 디렉토리가 빌드 컨텍스트가 됩니다.

빌드 컨텍스트는 Dockerfile이 빌드될 이미지에 파일을 추가할 때 사용됩니다. Dockerfile에서 이미지를 추가하는 방법은 ADD 외에도 COPY가 있는데, 이 명령어들은 빌드 컨텍스트의 파일을 이미지에 추가합니다.

위 예제에서 빌드 경로를 './'로 지정함으로써 test.html 파일을 빌드 컨텍스트에 추가했으며, ADD 명령어를 통해 빌드 컨텍스트에서 test.html 파일을 이미지에 추가했습니다.

컨텍스트는 build 커맨드의 맨 마지막에 지정된 위치에 있는 모든 파일을 모두 포함시킵니다. 깃과 같은 외부 URL에서 Dockerfile을 읽어 들인다면 해당 저장소에 있는 파일과 서브 모듈을 포함합니다. 따라서 Dockerfile이 위치한 곳에는 이미지 빌드에 필요한 파일만 있는 것이 바람직하고, 루트 디렉토리('/')와 같은 곳에서 이미지를 빌드하지 않도록 주의해야 합니다.

컨텍스트는 단순 파일뿐만 아니라 하위 디렉토리도 전부 포함하므로 빌드에 불필요한 파일이 포함된다면 빌드 속도가 느려지고, 호스트의 메모리를지나치게 점유할 수 있습니다.

이를 방지하기 위해서 깃에서 사용하는 .gitignore과 유사한 기능을 하는 .dockerignore이라는 파일을 작성하면 빌드 시에 이 파일에 명시된 이름의 파일은 컨텍스트에서 제외할 수 있습니다. 이 파일은 Dockerfile이 위치한 경로와 같은 곳에 위치해야 합니다.

1. # vi .dockerignore
2. test2.html
3. *.html
4. */*.html
5. test.htm?

제외할 파일의 경로는 Dockerfile이 존재하는 경로를 기준으로 합니다.

3.2.2. Dockerfile을 이용한 컨테이너 생성과 커밋

build 명령어는 Dockerfile에 기록된 대로 컨테이너를 실행한 뒤 완성된 이미지를 만들어냅니다. 하지만, 이미지를 만드는 관정이 하나의 컨테이너에서 일어나는 것은 아닙니다. 이는 이미지를 빌드할 때 나오는 출력을 통해서 확인이 가능합니다.

각 Step은 Dockerfile에 기록된 명령어 한줄 한줄에 해당합니다. ADD, RU과 같은 명령어가 실행될 때마다 새로운 컨테이너가 하나씩 생성되며 이를 이미지로 커밋하게 됩니다.

즉, Dockerfile에서 커맨드 한 줄이 실행될 때마다 이전 Step에서 생성된 이미지에 새로운 컨테이너가 생성되어 추가되며, 다시 새로운 이미지 레이어로 저장하게 됩니다. 따라서, 이미지의 빌드가 완료되면 Dockerfile의 커맨드 line 수만큼 레이어가 존재하게 되며, 중간에 컨테이너도 같은 수만큼 생성되고 삭제됩니다.

위 출력 결과에서 Removing intermediate container... 는 중간에 이미지 레이어를 생성하기 위해 임시로 생성된 컨테이너를 삭제하는 것이고, 삭제되기 전에 출력되는 ID는 커밋된 이미지 레이어를 의미합니다.

3.2.3. 캐시를 이용한 이미지 빌드

한 번 이미지 빌드를 마치고 난 뒤 다시 같은 빌드를 진행하면 이전의 이미지 빌드에서 사용했던 캐시를 사용합니다. 위 예제에서 사용한 Dockerfile의 내용의 일부를 지운 파일로 빌드를 다시 진행해보겠습니다.

1. # vi Dockerfile2
2. FROM ubuntu:18.04
3. MAINTAINER changjunlee
4. LABEL "purpose"="practice"
5. RUN apt update

이번에는 파일의 이름을 Dockerfile2로 저장하고, build 커맨드의 -f 또는 --file 옵션으로 Dockerfile의 이름을 지정합니다.

docker build -f Dockerfile2 -t mycache:0.0 ./

별도의 빌드 과정이 진행되지 않고 Using cache라는 출력 내용과 함께 바로 이미지가 생성되는 것을 확인할 수 있습니다. 이전에 빌드했던 Dockerfile에 같은 내용이 있다면 build 명령어는 이를 새로 빌드하지 않고, 같은 커맨드의 줄까지 이전에 사용한 이미지 레이어를 활용해 이미지를 생성합니다. 이는 같은 커맨드를 여러 번 실행해야 하는 여러 개의 이미지를 빌드하거나 빌드 도중 Dockerfile의 문법과 기타 오류가 발생했을 때 불필요하게 다시 커맨드를 실행하지 않게 합니다.

이미지 빌드 중 오류가 발생했을 때는 build 커맨드가 중단되고, 이미지 레이어의 생성을 위해 마지막으로 >생성된 임시 컨테이너가 삭제되지 않은 채로 남게 됩니다. 또한, 이미지의 빌드가 완전히 되지 않았기 때문에 >-t 옵션의 값으로 지정된 이미지의 이름이 아닌 <none>:<none>으로 이미지가 생성됩니다. 이를 삭제하>기 위해서는 이미지의 ID를 입력하여 삭제할 수 있습니다.

하지만 캐시 기능이 필요하지 않을 때도 존재합니다.

깃허브와 같은 소스코드 저장소에서 git clone 등의 커맨드를 사용해 빌드 할때가 여기서 해당됩니다. Dockerfile에서RUN git clone 을 사용해 이미지를 빌드했다면, RUN에 대한 이미지 레이어를 계속 캐시로 사용하기 때문에 실제 깃 저장소에서 리비전 관리가 일어나도 매번 빌드할 때마다 고정된 소스코드를 사용하게 됩니다.

이런 경우에 캐시를 사용하지 않으려면 --no-cache 옵션을 추가하면 됩니다. 이 옵션을 사용하면 기존 빌드에 사용된 캐시를 사용하지 않고, Dockerfil을 처음부터 다시 이미지 레이어로서 빌드합니다.

docker build --no-cache -t mybuild:0.0 .

또한, 캐시로 사용할 이미지를 직접 지정할 수도 있습니다. 특정 Dockerfile을 확장해서 사용한다면 기존의 Dockerfile로 빌드한 이미지를 빌드 캐시로 사용할 수 있습니다.

예를 들어, 도커 허브 nginx 공식 저장소에서 nginx:latest 이미지를 빌드하는 Dockerfile에 일부 내용을 추가해 사용한다면, 로컬의 nginx:latest 이미지를 캐시로 사용할 수 있습니다.

docker build --cache-from nginx -t my_extend_nginx:0.0 .
3.2.4. 멀티 스테이지를 이용한 Docker 빌드

일반적으로 어플리케이션을 빌드할 때는 많은 의존성 패키지와 라이브러리가 필요합니다. 예를 들어, Go로 작성된 소스코드를 빌드하기 위해서는 Go와 관련된 빌드 툴과 라이브러리가 미리 설치되어 있어야 합니다. Dockerfile에서 Go 소스코드를 빌드하기 위해서 가장 먼저 생각나는 방법은 아래의 Dockerfile처럼 Go와 관련된 도구들이 미리 설치된 이미지를 FROM에 명시한 뒤, RUN 커맨드로 소스코드를 컴파일하는 것입니다.

아래는 Hello World를 출력하는 간단한 Go 소스코드와 빌드된 프로그램을 실행하는 도커 이미지를 생성하는 Dockerfile 입니다.

1. // main.go
2. package main
3. import "fmt"
4. func main() {
5.     fmt.Println("hello world")
6. }
1. # vi Dockerfile
2. FROM golang
3. ADD main.go /root
4. WORKDIR /root
5. RUN go build -o /root/mainApp /root/main.go
6. CMD ["./mainApp"]

위 Dockerfile을 빌드하고, 이미지의 크기를 확인하면 다음과 같습니다.

단순히 hello world만 출력하는 프로그램을 실행하는 이미지인데, 이미지의 크기는 864MB를 차지하고 있습니다. 실제 실행 파일의 크기는 매우 작지만, 소스코드 빌드에 사용되는 각종 패키지 및 라이브러리가 불필요하게 이미지의 크기를 차지하고 있습니다.

17.05 버전 이상을 사용하는 도커 엔진이라면 이미지의 크기를 줄이기 위해 멀티 스테이지(Multi-Stage) 빌드 방법을 사용할 수 있습니다. 멀티 스테이지 빌드는 하나의 Dockerfile 안에 여러 개의 FROM 이미지를 정의함으로써 빌드 완료 시 최종적으로 생성될 이미지의 크기를 줄이는 역할을 합니다.

다음은 멀티 스테이지 빌드를 사용하는 Dockerfile 입니다.

# vi Dockerfile
FROM golang
ADD main.go /root
WORKDIR /root
RUN go build -o /root/mainApp /root/main.go
 
FROM alpine:latest
WORKDIR /root
COPY --from=0 /root/mainApp .
CMD ["./mainApp"]

일반적인 Dockerfile과는 다르게, 2개의 FROM을 통해서 2개의 이미지가 명시되어 있습니다.

첫 번째 FROM에 명시된 golang 이미지는 이전과 동일하게 main.go. 파일을 /root/mainApp으로 빌드했습니다.

그러나 두 번째 FROM 아래에서 사용된 COPY 명령어는 첫 번째 FROM에서 사용된 이미지의 최종 상태에 존재하는 /root/mainAp 파일을 두 번째 이미지인 alpine:latest에 복사합니다. 이때, --from=0은 첫 번째 FROM에서 빌드된 이미지의 최종 상태를 의미합니다.

docker build . -t go_helloworld:multi-stage

다시 빌드하여 이미지를 생성한 후에 확인해보면 이미지의 크기가 많이 감소한 것을 확인할 수 있습니다.

멀티 스테이지 빌드를 사용하는 Dockerfile은 2개 이상의 이미지를 사용할 수 있으며, 각 이미지는 먼저 FROM에서 명시된 순서대로 0, 1, ...의 순으로 차례대로 구분되어 사용합니다. 이를 활용하면 여러 개의 이미지를 사용해 멀티 스테이지 빌드를 활용할 수 있습니다.

1. FROM golang
2. ADD main.go /root
3. WORKDIR /root
4. RUN go build -o /root/mainApp /root/main.go
5. 
6. FROM golang
7. ADD main2.go /root
8. WORKDIR /root
9. RUN go build -o ./root/mainApp2 /root/main2.go
10. 
11. FROM alpine:latest
12. WORKDIR /root
13. COPY --from=0 /root/mainApp .
14. COPY --from=1 /root/mainApp2 .​

또한 특정 단계의 이미지에 별도의 이름을 정의할 수 있다. 아래는 첫 번째 단계의 최종 이미지에 builder라는 이름을 붙여서 사용한 예시입니다.

1. FROM golang as builder
2. ADD main.go /root
3. WORKDIR /root
4. RUN go build -o /root/mainApp /root/main.go
5. 
6. FROM alpine:latest
7. WORKDIR /root
8. COPY --from=builder /root/mainApp .
9. CMD ["./mainApp"]

4. Dockerfile로 빌드할 때 주의할 점

Dockerfile을 아무렇게나 작성하면 저장 공간을 불필요하게 차지하는 이미지나 레이어가 너무 많은 이미지가 생성될 수 있습니다.

다음은 Dockerfile을 사용할 때 이미지를 비효율적으로 빌드하는 예제입니다.

1. # vi Dockerfile
2. FROM ubuntu:20.04
3. RUN mkdir /test
4. RUN fallocate -l 100m /test/dummy
5. RUN rm /test/dummy

fallocate라는 커맨드로 100MB 크기의 파일을 가상으로 만들어 컨테이너에 할당하고, 이를 이미지 레이어로 빌드합니다. 그리고 이 파일을 rm 명령어로 삭제합니다.

1. docker build -t falloc_100mb:0.0
2. docker images

위에서 빌드한 이미지로 컨테이너를 생성하면 기본 ubuntu:20.04 이미지의 크기와 같지 않고 100MB 더 큰 이미지가 생성됩니다.

그러나 빌드한 이미지로 컨테이너를 생성하면 100MB 크기의 /test/dummy 파일은 존재하지 않습니다. 이는 Dockerfile에서 RUN rm /test/dummy 명령어로 이 파일을 삭제한 상태로 이미지를 빌드했기 때문입니다.

이는 컨테이너로 이미지를 생성할 때 컨테이너의 변경된 사항만 새로운 이미지 레이어로 생성하는 방식의 단점 중의 하나입니다.

rm 명령어로 파일을 삭제하더라도 이는 "파일을 삭제했다"라는 변경사항으로서의 레이어로 새롭게 저장될 뿐, 실제 100MB 크기의 파일은 여전히 이전 레이어에 남아있기 때문입니다.

즉, 실제로 컨테이너에서 사용하지 못하는 파일이 이미지 레이어로 존재하기 때문에 저장 공간은 차지하지만 실제로는 의미가 없는 저장 공간일 수도 있다는 것입니다.

이를 방지하는 방법은 간단하게 Dockerfile을 작성할 때, '&&'으로 각 RUN 명령어를 하나로 묶는 것입니다. 즉, 하나의 RUN으로 여러 개의 명령어를 실행하도록 작성하면 됩니다.

# vi Dockerfile
FROM ubuntu:20.04
RUN mkdir /test && \
    fallocate -l 100m /test/dummy && \
    rm /test/dummy

falloc_100mb_2 이미지를 생성해보면, 기본 ubuntu 이미지와 크기가 같은 것을 확인할 수 있습니다.

profile
Data Engineer

0개의 댓글