A Step-by-Step Guide to Docker Image Optimisation: Reduce Size by Over 95%
์์: ์ถฉ๊ฒฉ์ ์ด์๋ ์ด๊ธฐ ๊ฒฝํ
โNode.js ์ฑ์ ์ฒ์ ํ๋ก๋์
์ Docker๋ก ๋ฐฐํฌํ์ ๋, ์ด๋ฏธ์ง ํฌ๊ธฐ๊ฐ ๋ฌด๋ ค 1.2GB์์ต๋๋ค. ๋จ ๋ช ํฌ๋ก๋ฐ์ดํธ์ง๋ฆฌ ์๋ฐ์คํฌ๋ฆฝํธ ์ฝ๋์ ๋ง์ด์ฃ .โ
๋ถํ์ํ๊ฒ ํฐ ์ด๋ฏธ์ง๋ ์ ์ฅ ๊ณต๊ฐ๋ฟ ์๋๋ผ, ๋ฐฐํฌ ์ง์ฐ, ๋น์ฉ ์ฆ๊ฐ, ๋ณด์ ์ํ๊น์ง ์ด๋ํ์ต๋๋ค.
๋ช ์ผ๊ฐ์ ์ํ์ฐฉ์ค๋ฅผ ๊ฑฐ์ณ, ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ์ต๋ 95% ์ค์ด๋ ๊ธฐ๋ฒ๋ค์ ํฐ๋ํ์ต๋๋ค.
โ์์ฒ ๊ฐ ์ปจํ
์ด๋๋ฅผ ๋ฐฐํฌํ ๋๋ ๋ชจ๋ ๋ฉ๊ฐ๋ฐ์ดํธ๊ฐ ์ค์ํ๋ค.โ
์ด ๊ธ์์๋ ๊ทธ ์ฌ์ ์ ๋จ๊ณ๋ณ๋ก ์๊ฐํฉ๋๋ค.
1๋จ๊ณ: ๋น๋ํ ๊ธฐ๋ณธ Dockerfile
FROM node:latest
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]
์ด๋ ๊ฒ ๋น๋ํ ๊ฒฐ๊ณผ: 1.22GB
ํ
์คํธ๋ ์ฑ๊ณตํ์ง๋ง, ์ด๋ฏธ์ง๊ฐ ๋๋ฌด ๋น๋ํฉ๋๋ค.
2๋จ๊ณ: slim ๋ฒ ์ด์ค ์ด๋ฏธ์ง ์ฌ์ฉ
FROM node:slim
...
- ํ์ ์๋ ํจํค์ง ์ ๊ฑฐ
- ๋ณด์ ์ทจ์ฝ์ ๊ฐ์
- ๋น๋/ํ(run) ์๋ ํฅ์
๊ฒฐ๊ณผ: ์ฝ 345MB ๊ฐ์, 71% ์ ๊ฐ
3๋จ๊ณ: Alpine ์ด๋ฏธ์ง๋ก ์ถ๊ฐ ๊ฐ๋
FROM node:alpine
...
- musl libc, BusyBox ๋ฑ์ผ๋ก ๊ตฌ์ฑ๋ ์ด๊ฒฝ๋ ๋ฆฌ๋
์ค
- ๋ฒ ์ด์ค ์ด๋ฏธ์ง ์ฝ 5MB
๊ฒฐ๊ณผ: ์ด๋ฏธ์ง ์ฝ 258MB, ์ด 78% ๊ฐ์
๋จ, Alpine์ libc ํธํ์ฑ ์ด์๋ก ์ผ๋ถ ๋ค์ดํฐ๋ธ ๋ชจ๋์ด ๋ถ์์ ํ ์ ์์ต๋๋ค.
4๋จ๊ณ: ๋ฉํฐ์คํ
์ด์ง ๋น๋ + .dockerignore
.dockerignore
node_modules
npm-debug.log
tests
coverage
Dockerfile
.dockerignore
.env
*.md
Dockerfile
FROM node:alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
FROM node:alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/*.js ./
...
- ๋น๋ ๋๊ตฌ์ ํ
์คํธ/๊ฐ๋ฐ ํ์ผ ์ ์ธ
- ๋ฐํ์์ ํ์ํ ๊ฒ๋ง ํฌํจ
๊ฒฐ๊ณผ: ์ด๋ฏธ์ง ์ฝ 178MB, 85% ์ ๊ฐ
5๋จ๊ณ: Distroless ์ด๋ฏธ์ง ์ ์ฉ
FROM node:22-alpine AS builder
...
FROM gcr.io/distroless/nodejs22
WORKDIR /app
COPY --from=builder /app /app
CMD ["index.js"]
- ํจํค์ง ๊ด๋ฆฌ์์ ์ ์์ โ ๊ณต๊ฒฉ ํ๋ฉด ๊ฐ์
- ๋ถํ์ํ OS ๋ ์ด์ด ์ ๊ฑฐ
๊ฒฐ๊ณผ: ์ด๋ฏธ์ง 143MB, 88.2% ์ ๊ฐ
6๋จ๊ณ: ์ ์ ๋ฐ์ด๋๋ฆฌ๋ก ํจํค์ง
Dockerfile
FROM node:alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
RUN npm install -g pkg
COPY . .
RUN pkg --targets node16-alpine-x64 index.js -o app
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/app .
EXPOSE 3000
CMD ["./app"]
- Node ๋ฐํ์ ํฌํจ ๋จ์ผ ์คํ ํ์ผ ์์ฑ
- scratch or minimal Alpine ์ฌ์ฉ ๊ฐ๋ฅ
๊ฒฐ๊ณผ: ์ด๋ฏธ์ง ์ฝ 57MB, ์๋ณธ์ 4.7%
์ฃผ์: ๋์ ๋ชจ๋ ๋ก๋ฉ ๋ฑ ๋ณต์กํ ๊ตฌ์กฐ์๋ ์ ํฉํ์ง ์์ ์ ์์ต๋๋ค.
์ถ๊ฐ: Docker Slim ๋๊ตฌ ์๊ฐ
- ์ปจํ
์ด๋๋ฅผ ์คํํ๋ฉฐ ์ฌ์ฉ๋ ๋ถ๋ถ๋ง ์ถ์ ํ ์ด๋ฏธ์ง์์ ์ ๊ฑฐ
- ๊ฒฐ๊ณผ: 1.22GB โ 123MB
์ฃผ์: ํธ๋ ์ด์ฑ ์ ๋ ์์ธ ๊ฒฝ๋ก์ ํ์ผ์ด ๋๋ฝ๋๋ฉด ํ๋ก๋์
์ค๋ฅ ๊ฐ๋ฅ
๊ทธ ์ธ ๊ธฐ๋ฒ & ๋๊ตฌ
- ๋ ์ด์ด ์ต์ ํ: RUN ๋ช
๋ น์ ๋ฌถ์ด์ ์ ๊ณ ์บ์ ์ ๊ฑฐ
- BuildKit ์บ์ ๋ง์ดํธ: --mount=type=cache,target=/root/.npm
- ๋ถ์ ๋๊ตฌ
- dive: ์ด๋ฏธ์ง ๋ ์ด์ด ์๊ฐ ํ์
- Docker Scout: ๊ณต์ ์ด๋ฏธ์ง ๋ถ์/SBOM
- Buildpacks: ๋ฒ ์คํธ ํ๋ํฐ์ค ๊ธฐ๋ฐ ์๋ ์ด๋ฏธ์ง ๋น๋
โ
์ต์ข
์์ฝ
| ๋จ๊ณ | ์ด๋ฏธ์ง ํฌ๊ธฐ |
|---|
| ๊ธฐ๋ณธ | 1.22โฏGB |
| Slim | โ345โฏMB |
| Alpine | ~258โฏMB |
| ๋ฉํฐ์คํ
์ด์ง | ~178โฏMB |
| Distroless | ~143โฏMB |
| Static ๋ฐ์ด๋๋ฆฌ | ~57โฏMB |
| DockerโSlim | ~123โฏMB |
โจ ๋ง๋ฌด๋ฆฌ
1.22GB์์ 57MB๊น์ง, ๋จ์ ์ ์ฅ ์ ๊ฐ์ด ์๋:
- ๋ฐฐํฌ ์๋ ํฅ์
- ์ธํ๋ผ ๋น์ฉ โ
- ๊ณต๊ฒฉ ํ๋ฉด ์ต์ํ
- ์๋ํยทํ์ฅ์ฑ ๊ฐํ
๊ฐ ๋จ๊ณ๋ ๋
๋ฆฝ์ ์ผ๋ก ์ ์ฉํ๋ฉฐ, ๋ชจ๋ ๋จ๊ณ์ ๋์
์ด ๋ถ๊ฐ๋ฅํด๋ ์ผ๋ถ๋ง ์ ์ฉํด๋ ํฐ ํจ๊ณผ๊ฐ ์์ต๋๋ค.
์ปจํ
์ด๋ ์ต์ ํ ์ฌ์ ์ ๊พธ์คํ ํ์ต๊ณผ ๊ฐ์ ์ ๋ฐ๋ณต์ด๋ฉฐ, ํฌ์ํ๋งํผ์ ๊ฐ์น๋ฅผ ํ์คํ๊ฒ ์ ๊ณตํฉ๋๋ค.
๐ย ํ ๋ฒ์ฏค ์๊ฐํด๋ณด๋ ์ฃผ์ ๋ค
1. ๐ ์ปจํ
์ด๋ ๋ณด์์ โShift-Leftโ ์ ๋ต
๐ฏ ์ ์ค์ํ๊ฐ?
๊ฐ๋ฐ ์ด๊ธฐ ๋จ๊ณ๋ถํฐ ๋ณด์์ ๋ด์ฌํ(ShiftโLeft)ํ๋ฉด, ๋ฐฐํฌ ์ ํ์ ๋ฐ์ํ ์ ์๋ ๋ณด์ ์ด์๋ฅผ ์ฌ์ ์ ์๋ฐฉํ ์ ์์ต๋๋คย .
โ
์ฃผ์ ๊ตฌ์ฑ ์์
- ์๋ํ๋ ์ทจ์ฝ์ ์ค์บ
- CI/CD ํ์ดํ๋ผ์ธ์ ์ด๋ฏธ์งยท์์กด์ฑยทIaC ์ค์บ ๋๊ตฌ(SAST, DAST, SCA) ํตํฉ .
- ์: SonarQube, Trivy, Snyk, Dependency-Check.
- ๋ณด์ ๊ฒ์ดํธ ์ค์
- ์ทจ์ฝ์ ์์ค์ ๋ฐ๋ผ ๋น๋ ์คํจ ์กฐ๊ฑด ์ค์
- ๋ณด์ ๊ด๋ จ ์ ์ฑ
(as code) ์ ์ฉ .
- ๊ถํ ์ต์ํ
- ํ๋ก๋์
์ด๋ฏธ์ง๋ ๋ฐ๋์ root ๊ถํ ์์ด ์คํ
- distroless, scratch ์ด๋ฏธ์ง, ๋ถํ์ํ ์
ธ/ํจํค์ง ์ ๊ฑฐ.
- ๋ฐํ์ ๋ชจ๋ํฐ๋ง & ๊ฐ์ฌ
- Falco, Clair, Dockle ๋ฑ์ ๋๊ตฌ๋ฅผ ์ด์ฉํด ์คํ ์ ์ํ ํ์ง
- ๋ณด์ ๋ก๊ทธ ๋ฐ ์ด์ ํ๋ ์ค์๊ฐ ์์ง.
- Shift-Left ํ
์คํธ ๋ฌธํ
- ๊ฐ๋ฐ ์ด๊ธฐ API ๋ณด์ ํ
์คํธ(Dynamic ์ทจ์ฝ์ฑ) ํตํฉ .
- ๋ณด์ํ, ๊ฐ๋ฐํ, ์ด์ํ ๊ฐ ํ์
์ฆ์ง.
โ
์ค๋ฌด ํ
- PR๋ง๋ค ์๋ ์ค์บ ๊ฑธ๊ธฐ.
- ๋ณด์ ๊ฒฝ๋ณด๋ ์ฌ๋/์ด์ ํธ๋์ปค ์๋ฆผ.
- ๊ฐ๋ฐํ์๊ฒ ๊ฒฝ๊ณ ๋ฌธํ๋ฅผ ์กฐ์ฑํ๊ณ , ์๋ ์ฌ๋ฐฐํฌ ์๊ตฌ๋ฅผ ์ต์ํ.
2. ๐ ๋ฌด์ค๋จ ๋ฐฐํฌ ์ ๋ต & ๋คํธ์ํฌ ์ต์ ํ
๐ฏ ์ ๊ณ ๋ คํด์ผ ํ๋?
์ด๋ฏธ์ง ์ต์ ํ๋ก ์ปจํ
์ด๋ ์์ฒด๋ ๊ฐ๋ฒผ์์ก์ง๋ง, ์ ํ๋ฆฌ์ผ์ด์
๋ค์ดํ์ ์์ด ๋ฐฐํฌํ๊ณ , ๋คํธ์ํฌ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ ์ฌ์ ํ ์ค์ํฉ๋๋ค.
๐ ๏ธ ์ฃผ์ ๋ฐฐํฌ ์ ๋ต
- Blue-Green Deployment
- ๋ ํ๊ฒฝ: โBlueโ(ํํ) / โGreenโ(์ ๋ฒ์ )์ ๋ณ๋ ฌ ์ด์ฉ .
- DNS๋ ๋ก๋๋ฐธ๋ฐ์๋ก ํธ๋ํฝ ์ ํ โ ์ฆ๊ฐ์ ๋กค๋ฐฑ ๊ฐ๋ฅ.
- ๋จ์ : ๋ฆฌ์์ค ์ด์ค ์ฌ์ฉ, DB ๋ง์ด๊ทธ๋ ์ด์
์ ๋๊ธฐํ ์ฃผ์.
- Canary Deployment
- ์ ๋ฒ์ ์ ์์์ ํธ๋ํฝ(์: 1%, 10%)์๋ง ์์ํ ๋
ธ์ถ .
- ์ธ๊ทธ๋ ์ค ์ค์ ์ผ๋ก ํธ๋ํฝ ๋ถํ + ๋ชจ๋ํฐ๋ง ์ค์.
- ์ ์ง์ ํ์ฐ์ผ๋ก ์์ ์ฑโ, ์ค๋ฅ ์ ๋น ๋ฅธ ํต์ ๊ฐ๋ฅ.
- ํผํฉ ์ ๋ต
- ๋ฐ์ดํฐ์ผํฐ๋ณ๋ก Blue-Green ์ํ ํ, Canary ๋ฐฉ์์ผ๋ก ํ๋ ๋ฐฐํฌ .
๐ง ๋คํธ์ํฌ ์๋ํ ๋ฐ ์ต์ ํ
- DNS ๋ผ์ฐํ
- Routeโฏ53, Azure Traffic Manager ๋ฑ์ผ๋ก ์ง๋ฆฌ/๊ฐ์ค์น ๊ธฐ๋ฐ ํธ๋ํฝ ๋ถ๋ฆฌ .
- ๋กค๋ฐฑ, ํธ๋ํฝ ์ค์์นญ ์๋ํ์ ์ ๋ฆฌ.
- ์ธ๊ทธ๋ ์ค/์๋น์ค ๋งค๋์ ์ค์
- Nginx Ingress ํน์ Service Mesh์์ nginx.ingress.kubernetes.io/canary-weight ๋ฑ ์ด๋
ธํ
์ด์
์ฌ์ฉ .
- ์๋น์ค ์ด๋ฆ(label)์ผ๋ก Blue/Green ํฌ๋ ๋ผ์ฐํ
.
- ์๋ํ ๋๊ตฌ
- Argo Rollouts ๊ธฐ๋ฐ ๋ฐฐํฌ ํ๋ก์ฐ ๊ตฌ์ถ .
- CI/CD(Terraform + Route53) + Argo๋ฅผ ์ฐ๋ํด ์์ ๋ฌด์ค๋จ, ๊ฐ์ค์น ์กฐ์ ๊ฐ๋ฅ ๋ฐฐํฌ ํ๊ฒฝ ๊ตฌ์ถ.
โ
์์ฝ ์ ๋ฆฌ
| ์ฃผ์ | ๊ตฌ์ฑ | ํจ๊ณผ |
|---|
| ShiftโLeft ๋ณด์ | ์ด๋ฏธ์ง/์ฝ๋ ์ค์บ, ๊ถํ ์ต์ํ, ๋ฐํ์ ๋ชจ๋ํฐ๋ง, PR ๊ธฐ๋ฐ ๋ณด์ ๊ฒ์ดํธ | ์ด๊ธฐ ๋ณด์ ๊ฒฐํจ ์๋ฐฉ + ์ด์ ์ค ๋ฆฌ์คํฌ ์ต์ํ |
| ๋ฌด์ค๋จ ๋ฐฐํฌ + ๋คํธ์ํฌ ํธ๋ํฝ ๊ด๋ฆฌ | BlueโGreen / Canary ์ ๋ต, DNS/Ingress ์๋ํ, Argo Rollouts | ์ค๋จ ์๋ ๋ฐฐํฌ, ๊ฐ์์ฑ ํ๋ณด, ๋น ๋ฅธ ๋กค๋ฐฑ ๋์ ๊ฐ๋ฅ |