본문 바로가기

IT 엔지니어/CLOUD

Docker image build

 

소스코드(100MB)

개발도구(500MB)

애플리케이션(5MB)

single-stage / mutlti-stage

싱글 스테이지 빌드 (Single-stage build)

  • 한 Dockerfile 안에서 이미지 한 개만 만들어서 그걸 그대로 사용.
  • 빌드 도구, 중간 파일, 임시 디펜던시 등도 이미지에 포함돼서 용량이 커지고 보안 이슈도 생길 수 있어.

📦 예시

FROM node:18

WORKDIR /app = 이동 명령
COPY . .
RUN npm install
RUN npm run build

CMD ["node", "dist/index.js"]

🔻 문제점

  • npm install, npm run build에 필요한 도구들이 최종 이미지에도 남음.
  • 이미지가 커지고, 불필요한 파일 포함될 수 있음.

🔹 멀티 스테이지 빌드 (Multi-stage build)

  • Dockerfile 안에서 여러 FROM을 써서, 빌드는 한 이미지에서최종 결과물만 추려서 다른 이미지에 복사.
  • 최종 이미지는 최소한의 실행 파일만 포함해서 훨씬 가벼워짐.

✅ 예시

# 🔧 1단계: 빌드 전용 스테이지
FROM node:18 AS builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build

# 🚀 2단계: 실행용 스테이지
FROM node:18-slim
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json .
RUN npm install --omit=dev
CMD ["node", "dist/index.js"]

🔥 장점

  • 최종 이미지에 dist만 들어감 → 불필요한 dev 디펜던시, 빌드 도구 없음
  • 작고 빠르고, 보안도 좋아짐

📌 차이 요약

구분 싱글 스테이지 멀티 스테이지

FROM 한 번만 사용 여러 번 사용 가능
이미지 크기 작음
불필요한 파일 포함될 수 있음 제거 가능
보안성 낮을 수 있음 상대적으로 높음
사용 난이도 간단 약간 복잡하지만 효율적

[이미지 빌드 용량 차이 ]

dnf -y install golang-bin

vi main.go
-----------------------------
package main

import "fmt"

func main() {
                fmt.Println("Hello DOCKER")
}    

-----------------------------
go run main.go
<Hello Docker>
-----------------------------
go build main.go
main 파일 생성

./main
<Hello Docker>

싱글 vs 멀티의 주요 차이는 
이미지 크기와 빌드 효율성
vi dockerfile

from golang:1.16
workdir /go/src/github.com/test/hello
run go get -d -v github.com/urfave/cli
copy main.go main.go
run GOOS=linux go build -a -o hello main.go
entrypoint ["./hello"]
-----------------------------

docker build -t singlestage .
docker run --rm singlestage

singlestage   latest    e6296d29cd21   50 seconds ago   941MB

-----------------------------
vi Dockerfile2

rom golang:1.16 as builder
workdir /go/src/github.com/test/hello
run go get -d -v github.com/urfave/cli
copy main.go main.go
run GOOS=linux go build -a -o hello main.go

------
from busybox
workdir /opt/greet/bin
copy --from=builder /go/src/github.com/test/hello/ .

entrypoint ["./hello"]
-----------------------------

docker build -t multistage .
docker run --rm multistage

multistage    latest    91b0d3f01359   17 seconds ago   6.22MB

 

 

from ubuntu
run echo shell Command..!
run ["echo","Exec Command..~"]
run ["/bin/bash","-c","echo 'Command Exec Command'"]

docker build -t demo  --no-cache --progress plain .

#0 building with "default" instance using docker driver

#1 [internal] load build definition from Dockerfile
#1 transferring dockerfile: 172B done
#1 DONE 0.0s

#2 [internal] load metadata for docker.io/library/ubuntu:latest
#2 DONE 0.0s

#3 [internal] load .dockerignore
#3 transferring context: 2B done
#3 DONE 0.0s

#4 [1/4] FROM docker.io/library/ubuntu:latest
#4 CACHED

#5 [2/4] RUN echo shell Command..!
#5 0.165 shell Command..!
#5 DONE 0.2s

#6 [3/4] RUN ["echo","Exec Command..~"]
#6 0.345 Exec Command..~
#6 DONE 0.3s

#7 [4/4] RUN ["/bin/bash","-c","echo '/bin/bash Command Exec Command'"]
#7 0.227 /bin/bash Command Exec Command
#7 DONE 0.2s

#8 exporting to image
#8 exporting layers 0.0s done
#8 writing image sha256:a3156ed564f1359427a06c8b0d89db5523ca18de04f207036e7ba0a999150110 done
#8 naming to docker.io/library/demo done
#8 DONE 0.0s

 

 

🛠️ RUN, CMD, ENTRYPOINT 차이 정리

항목 용도 실행 시점 예시 특징

RUN 이미지 빌드 시 명령 실행 docker build 단계 RUN apt update 결과가 이미지에 영구 반영
CMD 컨테이너 실행 시 기본 명령      

애플리케이션 실행 시 사용됨 | docker run 시 | CMD ["nginx", "-g", "daemon off;"] | 나중에 docker run 명령으로 덮어쓸 수 있음 | | ENTRYPOINT | 컨테이너 실행 시 항상 실행될 명령 | docker run 시 | ENTRYPOINT ["nginx"] | CMD를 인자로 취급, 덮어쓰기 어려움 |

CMD vs ENTRYPOINT 심화

상황 ENTRYPOINT CMD

docker run에서 명령어 변경 ENTRYPOINT는 그대로 유지됨 CMD는 덮어씀
유연하게 인자 넘기기 ENTRYPOINT + CMD 조합 활용 예: ENTRYPOINT ["curl"] + CMD ["<https://naver.com>"]
완전히 바꾸고 싶을 때 --entrypoint 옵션 사용 그냥 명령어로 덮어쓰기 가능
vi Dockerfile

from ubuntu:16.04
entrypoint ["top"]
cmd ["-d","10"]

docker build -t test .

docker run --rm -it test -d 1 

CMD 명령 덮어쓰기 가능

ENTRYPOINT의 인자로 사용
docker run --rm --entrypoint date test

entrypoint도 덮어쓰기 가능
from ubuntu:16.04
run apt-get update && apt-get -y upgrade
run apt-get -y install nginx

expose 80 /// -p 8080:80 내부 포트 80임을 선언

cmd ["nginx","-g","daemon off"]

vi TEST
FROM nginx
ONBUILD ADD myweb.tar /var/www/html
-----------------------------
vi TEST2
FROM TEST

docker build -t TEST2-1 .

자동으로 /var/www/html로 복사

ONBUILD 는 자동 진행 트리거 명령어

도커파일에 CMD 없어도 이미지 및 컨테이너 생성 가능
docker run 시 바로 종료됨
대신 
docker run --name test sleep 60 // 60초 동안 생존

 

 

 

<실습>

from centos:8

run ["useradd","user1"]
run ["whoami"]
run ["id"]

user user1
run ["whoami"]
run ["id"]
run ["cal"]

cmd ["/bin/bash","-c","cal"]
cmd ["cal"]
run 은 이미지 빌드 시 수행

cmd 는 빌드한 이미지 이용하여 컨테이너 생성 시 수행/ 덮어쓰기 가능

entrypoint 

[ADD /COPY]

from ubuntu:latest

run apt-get update && apt-get -y upgrade
run apt-get -y install nginx

copy index.html /var/www/html
copy index.tar.gz /var/www/html

add add.tar.gz /var/www/html
압축 해제 후 복사

cmd ["nginx","-g","daemon off;"]

index.html
index.tar.gz 
add.tar.gz 압축해제한 index2.html 
복사되어야 한다
vi index.html

tar -czf index.tar.gz index.html

cp index.html index2.html

tar -czf add.tar.gz index2.html

docker run --rm add ls /var/www/html

index.html
index.nginx-debian.html
index.tar.gz
index2.html

from ubuntu:latest

run apt-get update && apt-get -y upgrade
run apt-get -y install nginx

copy index.html /var/www/html
copy index.tar.gz /var/www/html
add add.tar.gz /var/www/html

copy test.tar /tmp/

(COPY test.tar .
RUN tar -xf test.tar -C /var/www/html)
(workdir /tmp/)

run tar -xf /tmp/test.tar -C /var/www/html

cmd ["nginx","-g","daemon off;"]

🔧 명령 정리

tar -czf docker.tar.gz Dockerfile index.html
docker build -t myweb3 - < docker.tar.gz

압축해제 방법 2 가지

이 흐름에서 일어나는 일은?

  1. docker.tar.gz 압축 파일에는 Dockerfile과 index.html이 포함되어 있어.
  2. docker build - < docker.tar.gz 명령은 압축을 푸는 게 아니라, Docker가 빌드 컨텍스트로 압축 파일을 직접 받아서 내부적으로 해석하는 거야.
  3. Docker는 압축을 풀고 내부의 Dockerfile을 기준으로 이미지를 빌드해.

🔸 1. docker build - < file.tar.gz

👉 이 경우는 Docker 자체가 압축을 자동 해제해서 내부 파일(Dockerfile 포함)을 빌드 컨텍스트로 사용해.

즉, tar.gz 파일 안에 Dockerfile과 관련 파일이 있으면 Docker가 해석 가능해.

💡 요점: 이건 컨텍스트 압축 해제, 즉 Docker 외부에서 입력으로 압축된 컨텍스트를 주면, Docker가 자동으로 압축 해제해 빌드함.


🔸 2. ADD file.tar.gz /some/path

👉 이건 Dockerfile 내부에서 실행되는 명령으로, 이미지 안에 파일을 추가하면서 자동 압축 해제까지 해줌.

💡 요점: ADD는 명시적으로 tar 계열 파일을 이미지에 복사하면서, 그 자리에서 압축을 풀어줌.

'IT 엔지니어 > CLOUD' 카테고리의 다른 글

Docker yml  (1) 2025.05.18
Docker Registry  (0) 2025.05.17
Docker  (1) 2025.05.15
Docker image  (0) 2025.05.14
Docker Resource Limit  (0) 2025.05.13