6장. Dockerfile 작성
이 장을 마치면: Dockerfile이 무엇인지 알고, 우리 서비스(API 서버 + 프론트엔드)의 Dockerfile을 Claude Code로 만들어, 한 줄씩 읽으며 무슨 뜻인지 설명할 수 있다.
5장에서 "우리 서비스를 이미지로 만들어 컨테이너로 실행한다"는 큰 그림을 그렸습니다. 그렇다면 이미지는 어떻게 만들까요? 아무렇게나 만들 수는 없고, "이 이미지를 이렇게 만들어라"라고 적어 둔 설명서가 필요합니다. 그 설명서가 바로 이번 장의 주인공, Dockerfile입니다.
이번 장에서도 Dockerfile을 직접 타이핑하지는 않습니다. Claude Code에게 만들어 달라고 한 뒤, 만들어진 내용을 한 줄씩 읽고 이해하는 것이 목표입니다. 남이 써 준 설명서라도 무슨 뜻인지 알아야, 나중에 문제가 생겼을 때 대응할 수 있으니까요. 그리고 이 장에서는 설명서를 만들기만 하고, 실제로 이미지를 굽는(빌드) 것은 다음 7장에서 합니다.
[지금 여기]
우리는 22단계를 거쳐 "라이브 투표 서비스"를 직접 만들고, 컨테이너에 담아, AWS 클라우드에 배포합니다. 아래가 그 전체 여정 지도입니다. 지금은 6단계, Dockerfile을 작성할 차례입니다.
- 1장개발 환경 준비 (터미널 / Node.js / Git / GitHub / VS Code / Claude Code)
- 2장Claude Code 사용법 익히기
- 3장무엇을 만들지 기획 (라이브 투표 서비스)
- 4장로컬에서 서비스 만들기 (React + Express + PostgreSQL)
- 5장Docker 개념
- 6장Dockerfile 작성
- 7장컨테이너 빌드·실행
- 8장AWS 시작 (계정 / IAM / 리전 / 비용)
- 9장이미지 태깅
- 10장ECR에 이미지 올리기
- 11장VPC 네트워크 구성
- 12장RDS 데이터베이스 생성
- 13장SSM 터널로 RDS 초기화
- 14장ECS Fargate + ALB로 배포 (기본 완성)
- 15장CI/CD (GitHub Actions)
- 16장IaC (Terraform)
- 17장배포 자동화 연결
- 18장현업 운영 구조 이해
- 19장무중단 배포
- 20장신규 버전 배포 & 롤백
- 21장(심화) 프론트를 Vercel로 분리 배포
- 22장마무리 (회고 + 리소스 삭제)
- 방금 끝낸 것: 5장에서 Docker가 왜 필요한지(환경 차이 문제)를 이해하고, Docker Desktop을 설치했습니다.
- 이번 장에서 하는 것: 우리 서비스를 이미지로 만드는 설명서 (Dockerfile)를 API 서버용·프론트엔드용으로 각각 만들고, 한 줄씩 읽어 이해합니다. (이미지를 실제로 굽는 것은 7장입니다.)
이번 장에서 완성되는 것
한 문장으로: vote-app/backend와 vote-app/frontend 폴더 안에
각각 Dockerfile(과 .dockerignore)이 생기고, 그 내용을 여러분이
한 줄씩 읽고 무슨 뜻인지 설명할 수 있게 됩니다.
이렇게 되면 성공입니다: VS Code 왼쪽 파일 목록에서 backend/Dockerfile,
frontend/Dockerfile을 열었을 때 그 안에 명령들이 채워져 있고, 여러분이
FROM이 무슨 뜻인지, 왜 프론트엔드는 두 단계로 나뉘는지 말로 설명할 수
있습니다.
사전 조건
이 장은 앞 장들의 결과물 위에서 시작합니다. 아래가 갖춰져 있어야 합니다.
- 1~4장 완료: 문서(Documents) 폴더 안에
vote-app폴더가 있고, 그 안에frontend(React) 폴더와backend(Express) 폴더가 만들어져 있어야 합니다. (4장에서 Claude Code로 만든 그 폴더들입니다.) - 5장 완료: Docker가 무엇인지 이해했고, Docker Desktop을 설치했습니다.
이 장에서는 Docker Desktop이 켜져 있지 않아도 됩니다 이번 장은 "설명서(Dockerfile)를 만들고 읽기"만 합니다. Docker로 실제 이미지를 굽는 것은 7장이라, 지금 당장 Docker Desktop을 켤 필요는 없습니다. (물론 켜 두어도 아무 문제 없습니다.)
시작 전에: VS Code로 vote-app을 열고, backend/frontend 폴더 확인
- VS Code를 실행하고, 위쪽 메뉴에서 File(파일) → Open Folder(폴더
열기)로 문서(Documents) 폴더 안의
vote-app을 엽니다. (1장 1.6절에서 한 방법 그대로입니다.) - VS Code 왼쪽의 파일 목록(탐색기)에
frontend와backend폴더가 보이는지 확인합니다. 두 폴더가 보이면 준비된 것입니다.- 만약 두 폴더가 안 보인다면 4장을 아직 안 끝낸 것입니다. 4장으로 돌아가 서비스 만들기를 마친 뒤 다시 오세요.
- 위쪽 메뉴에서 Terminal(터미널) → New Terminal(새 터미널)로
터미널을 열고, 아래로 지금 위치가
vote-app인지 확인합니다.
pwd # 경로 끝이 /vote-app 이어야 합니다
끝이 /vote-app이 아니면 1장 1.6절대로 vote-app을 다시 여세요.
6.1 Dockerfile이란 — 이미지를 만드는 설명서
Dockerfile 이미지를 "어떤 순서로, 무엇을 넣어" 만들지 적어 둔 텍스트 파일입니다. 요리 레시피와 같습니다. 레시피에 재료와 조리 순서가 적혀 있듯, Dockerfile에는 "어떤 기반에서 시작해 → 무엇을 복사하고 → 어떤 명령을 실행하고 → 어떻게 띄울지"가 순서대로 적혀 있습니다.
5장에서 이미지를 "붕어빵 틀"에 비유했습니다. 그 틀을 우리 서비스에 맞게
새로 찍어내려면, "이 틀은 이렇게 만들어라"라는 설명서가 필요합니다.
그 설명서가 Dockerfile입니다. 파일 이름은 확장자도 없이 그냥 Dockerfile
(첫 글자 대문자)입니다.
Dockerfile은 한 줄에 하나씩 "명령어(지시어)"를 씁니다. 자주 나오는 명령어 여섯 개만 익혀 두면, 어떤 Dockerfile을 봐도 대략 읽을 수 있습니다.
| 명령어 | 뜻 | 레시피에 비유하면 |
|---|---|---|
FROM |
어떤 기반(베이스 이미지)에서 시작할지 | "어떤 반죽으로 시작한다" |
WORKDIR |
이미지 안에서 작업할 폴더를 정한다 | "이 도마 위에서 작업한다" |
COPY |
내 파일을 이미지 안으로 복사한다 | "재료를 도마에 올린다" |
RUN |
이미지를 만드는 도중 명령을 실행한다 | "굽는다, 섞는다" |
EXPOSE |
이 컨테이너가 사용할 포트를 알려 준다 | "몇 번 창구로 서빙한다" |
CMD |
컨테이너가 시작될 때 실행할 명령 | "손님에게 낼 때 이렇게 낸다" |
이 여섯 개는 지금 외우지 않아도 됩니다. 6.4~6.5에서 우리 Dockerfile을 읽으며 하나씩 다시 만날 테니, 지금은 "이런 지시어들이 있구나" 정도만 눈에 담아 두세요.
6.2 [활용 사례] Dockerfile은 실무에서 어디에 쓰이나
Dockerfile은 우리 투표 서비스에만 쓰는 특별한 게 아닙니다. 오늘날 거의 모든 소프트웨어 회사가 Dockerfile을 씁니다. 실제로 어디에 쓰이는지 몇 가지만 보면, "아, 그래서 이걸 배우는구나"가 실감 납니다.
- 팀의 "표준 실행 환경"을 문서 하나로 고정 — 회사에서 새 팀원이 들어오면, 예전에는 "Node.js 몇 버전 깔고, DB 깔고, 설정 맞추고…"를 며칠씩 했습니다. Dockerfile이 있으면 그 모든 게 파일 한 장에 적혀 있어서, 명령 한 줄로 똑같은 환경이 만들어집니다. "내 컴퓨터에선 되는데"(5장) 문제가 사라지는 것이죠.
- CI에서 자동으로 빌드·테스트 — GitHub에 코드를 올리면, 회사의 자동화 시스템(CI)이 그 Dockerfile로 이미지를 만들어 테스트를 돌립니다. 사람마다 다른 환경이 아니라, 언제나 똑같은 환경에서 검사하니 결과를 믿을 수 있습니다. (우리도 3부 15장에서 이걸 직접 해 봅니다.)
- 언어·프레임워크가 무엇이든 같은 방식 — Node.js뿐 아니라 파이썬, 자바, Go, PHP 등 어떤 언어로 만든 프로그램이든 각자의 Dockerfile을 써서 똑같이 "이미지"로 만듭니다. 그래서 서버 입장에서는 안에 무슨 언어가 들었든 "컨테이너"라는 규격으로 똑같이 다룰 수 있습니다.
- 오픈소스 프로그램을 그대로 실행 — 인터넷에 공개된 프로그램 중 상당수가 Dockerfile(또는 완성된 이미지)을 함께 제공합니다. 그래서 복잡한 설치 과정 없이 명령 한 줄로 남이 만든 프로그램을 내 컴퓨터에서 띄워 볼 수 있습니다.
정리하면, Dockerfile은 "이 프로그램을 이런 환경에서 이렇게 실행하라"를 글로 못박아 둔 표준 설명서입니다. 그래서 사람이 바뀌든 컴퓨터가 바뀌든 항상 똑같이 재현됩니다.
6.3 [맛보기] 아주 간단한 Dockerfile 한 줄씩 읽어 보기
우리 서비스에 들어가기 전에, 세상에서 가장 짧은 Dockerfile 하나를 먼저 읽어 봅시다. 아래는 "Node.js 위에서 인사말 한 줄을 출력하는" 연습용 Dockerfile입니다. (우리 프로젝트와는 상관없는, 감을 잡기 위한 예시입니다. 지금은 만들거나 실행하지 말고, 눈으로만 읽으세요.)
# Node.js 22가 깔린 가벼운 이미지에서 시작한다
FROM node:22-alpine
# 컨테이너가 켜지면 인사말 한 줄을 출력한다
CMD ["node", "-e", "console.log('안녕, 컨테이너!')"]
딱 두 줄입니다. 한 줄씩 뜯어보면:
FROM node:22-alpine— "Node.js 22가 이미 설치된 이미지"를 출발점으로 삼습니다. 우리가 Node.js를 직접 깔 필요가 없어집니다.CMD [...]— 이 이미지로 만든 컨테이너가 켜지는 순간 실행할 명령을 적습니다. 여기서는안녕, 컨테이너!를 화면에 출력합니다.#으로 시작하는 줄 — 주석입니다. 사람이 읽으라고 적은 설명일 뿐, 실행에는 영향을 주지 않습니다.
보다시피 Dockerfile은 "위에서 아래로, 한 줄에 지시 하나씩" 읽으면 됩니다. 어렵지 않죠? 이제 이 감각을 그대로 가지고, 우리 서비스의 진짜 Dockerfile을 만들어 읽어 봅시다.
Claude Code를 아직 실행하지 않아도 됩니다 위 예시는 눈으로 읽기만 하는 맛보기라 실행하지 않습니다. 다음 절부터 실제로 Claude Code를 실행해 우리 Dockerfile을 만듭니다.
6.4 [우리 프로젝트] API 서버 Dockerfile 만들기
이제 우리 백엔드(Express API 서버)를 이미지로 만드는 Dockerfile을 Claude Code로 만들어 봅시다.
1단계. Claude Code 실행
앞의 "사전 조건"에서 연 VS Code 터미널(vote-app 폴더)에서 Claude
Code를 실행합니다.
claude
AI 입력창이 뜨면 준비된 것입니다. (터미널을 닫았다면 Terminal → New
Terminal로 다시 열고 pwd로 /vote-app인지 확인한 뒤 claude를
입력하세요.)
2단계. API용 Dockerfile을 만들어 달라고 요청
AI 입력창에 아래 프롬프트를 그대로 입력하고 Enter를 누릅니다.
Claude Code가 backend/Dockerfile 파일을 만들었다고 답하면 다음
단계로 갑니다. (파일을 만들기 전 확인을 물으면 안내에 따라 허용하세요.)
3단계. 만들어진 파일 열어서 읽기
VS Code 왼쪽 파일 목록에서 backend 폴더를 펼치고 → Dockerfile을
클릭해 엽니다. 만들어진 내용은 대략 아래와 비슷합니다(세부 사항은 조금
다를 수 있습니다). 한 줄씩 읽어 봅시다.
# 1) Node.js가 깔려 있는 이미지에서 시작한다
FROM node:22-alpine
# 2) 이미지 안에서 /app 폴더를 작업 폴더로 삼는다
WORKDIR /app
# 3) 부품 목록 파일부터 복사한다 (설치를 위해)
COPY package*.json ./
# 4) 목록에 적힌 부품(라이브러리)들을 설치한다
RUN npm install
# 5) 나머지 소스 코드를 전부 복사한다
COPY . .
# 6) 이 서버는 3000번 포트를 쓴다고 알려 준다
EXPOSE 3000
# 7) 컨테이너가 시작되면 이 명령으로 서버를 켠다
CMD ["node", "server.js"]
각 줄의 의미를 풀면 이렇습니다.
FROM node:22-alpine— Node.js 22 버전이 이미 설치된 가벼운 (alpine) 이미지에서 출발합니다. 우리가 Node.js를 직접 깔 필요가 없어집니다.WORKDIR /app— 앞으로의 작업을 이미지 안/app폴더에서 합니다. 이 폴더가 없으면 자동으로 만들어집니다.COPY package*.json ./— 먼저 부품 목록 파일만 복사합니다. (왜 소스보다 먼저 복사하는지는 6.7에서 설명합니다.)RUN npm install— 목록에 적힌 라이브러리들을 이미지 안에 설치합니다.COPY . .— 이제 나머지 소스 코드 전체를 이미지로 복사합니다.EXPOSE 3000— 이 컨테이너는 3000번 창구(포트)로 통신한다고 표시합니다. (우리 API 서버가 4장에서 3000번 포트를 썼던 것과 같습니다.)CMD ["node", "server.js"]— 컨테이너가 켜지면 이 명령으로 서버를 시작합니다.
여기서 새로 나온 개념 두 개, 베이스 이미지와 alpine을 짚고 갑시다.
베이스 이미지(Base Image)
Dockerfile의 FROM에 적는, 출발점이 되는 이미지입니다. 예를 들어
Node.js 프로그램을 담으려면 이미 Node.js가 깔려 있는 이미지에서
시작하는 게 편하겠죠. 그런 "이미 준비된 기반"이 베이스 이미지입니다.
맨땅에서 리눅스부터 쌓는 대신, 남이 잘 만들어 둔 기반 위에서 시작하는
셈입니다.
node:22-alpine의 alpine
alpine은 용량이 아주 작은 리눅스를 뜻합니다. 같은 Node.js라도
node:22(일반)보다 node:22-alpine(가벼운 버전)이 훨씬 작아서,
이미지를 가볍게 만들려고 자주 씁니다. 이미지가 가벼우면 좋은 점은
6.8에서 정리합니다.
#으로 시작하는 줄은 주석입니다
Claude Code에게 "주석을 달아 달라"고 하면 이렇게 각 줄의 뜻을 함께
적어 줘서 이해에 도움이 됩니다. 주석은 실행에 영향을 주지 않으니,
나중에 지워도 이미지는 똑같이 만들어집니다.
파일 이름은 정확히 Dockerfile
확장자 없이 첫 글자만 대문자인 Dockerfile이어야 합니다.
dockerfile.txt나 DockerFile처럼 되어 있으면 7장에서 빌드할 때
인식하지 못합니다. VS Code 파일 목록에서 이름이 정확히 Dockerfile인지
확인하세요.
6.5 [우리 프로젝트] 프론트엔드 Dockerfile — 두 단계로 만들기
프론트엔드는 조금 다릅니다. React로 만든 화면은 코드 그대로 실행하는 게 아니라, 먼저 "빌드"라는 과정을 거쳐 브라우저가 읽을 수 있는 순수한 파일들(HTML/CSS/JS)로 변환한 뒤, 그 결과물을 웹 서버가 사용자에게 전달합니다.
빌드(Build)
개발용으로 작성한 코드를, 실제로 브라우저에서 돌아갈 수 있는 최종
파일들로 변환하는 과정입니다. React 코드(4장에서 Vite로 만든)가
빌드를 거치면 정적인 HTML/CSS/JS 묶음이 되고, 그 결과물은 보통
dist라는 폴더에 담깁니다.
그래서 프론트엔드 Dockerfile은 두 단계로 나뉩니다. 앞 단계에서 React를 빌드하고, 뒤 단계에서 그 결과물만 가벼운 웹 서버에 담습니다. 이 방식을 멀티스테이지 빌드라고 합니다.
멀티스테이지 빌드(Multi-stage Build) 하나의 Dockerfile 안에서 작업을 여러 단계(스테이지)로 나누는 방식입니다. 앞 단계에서 무거운 도구로 결과물을 만들고, 뒤 단계에서는 그 결과물만 가볍게 담습니다. 최종 이미지에 불필요한 것(빌드 도구 등)이 안 들어가서 이미지가 작고 깔끔해집니다.
[활용 사례] 멀티스테이지 빌드는 이럴 때 쓴다 멀티스테이지는 "만들 때는 무거운 도구가 필요하지만, 실행할 때는 결과물만 있으면 되는" 경우에 두루 쓰입니다.
- React/Vue 같은 웹 프론트엔드 — 빌드에는 Node.js가 필요하지만, 완성된 정적 파일을 서빙할 때는 Node.js가 필요 없습니다. (지금 우리가 하는 경우입니다.)
- Go·Java 같은 컴파일 언어 — 컴파일에는 무거운 개발 도구가 필요하지만, 실행에는 완성된 실행 파일 하나만 있으면 됩니다. 그래서 최종 이미지에는 실행 파일만 담아 아주 작게 만듭니다.
1단계. 프론트엔드용 Dockerfile 요청
Claude Code 입력창(6.4에서 이미 실행해 두었습니다)에 아래를 입력합니다.
2단계. 만들어진 파일 열어서 읽기
VS Code 왼쪽 파일 목록에서 frontend 폴더를 펼치고 → Dockerfile을
클릭해 엽니다. 대략 이렇게 되어 있습니다.
# ===== 1단계: 빌드 =====
# Node.js 이미지에서 React 코드를 빌드한다
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build # 빌드 결과물이 /app/dist 에 생긴다
# ===== 2단계: 서빙 =====
# 가벼운 Nginx 웹 서버 이미지에서 시작한다
FROM nginx:alpine
# 1단계에서 만든 빌드 결과물만 가져와 웹 서버 폴더에 넣는다
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
핵심만 짚으면 이렇습니다.
- 1단계(
AS build): Node.js 이미지에서 React 코드를npm run build로 변환해 결과물(/app/dist)을 만듭니다. 이 단계는 무거운 빌드 도구를 씁니다.FROM ... AS build의build는 이 단계에 붙인 이름표입니다. - 2단계(서빙): 가벼운 Nginx 웹 서버 이미지에서 새로 시작해, 1단계의
결과물만
COPY --from=build로 가져옵니다. Node.js나 빌드 도구는 최종 이미지에 포함되지 않습니다.
Nginx(엔진엑스)
만들어진 정적 파일(HTML/CSS/JS)을 사용자 브라우저에 전달해 주는
가볍고 빠른 웹 서버입니다. React 빌드 결과물을 서빙하는 데 흔히 씁니다.
nginx:alpine은 그 Nginx의 가벼운 버전 이미지입니다.
COPY --from=build
"앞의 build 단계에서 만든 파일을 여기로 가져와라"는 뜻입니다. 이 한
줄이 멀티스테이지 빌드의 핵심입니다. 무거운 1단계에서 결과물(dist)만
쏙 빼서, 가벼운 2단계 이미지 안 /usr/share/nginx/html(Nginx가 웹페이지를
꺼내 보여 주는 폴더)에 넣는 것이죠.
이렇게 하면 최종 프론트엔드 이미지에는 무거운 빌드 도구 없이, 웹 서버와 완성된 화면 파일만 담겨 아주 가벼워집니다.
Nginx는 CMD가 없어도 켜집니다
API Dockerfile과 달리 이 프론트엔드 Dockerfile 끝에는 CMD가 없을 수
있습니다. nginx:alpine 이미지 자체에 "시작하면 Nginx 웹 서버를 켠다"는
기본 명령이 이미 들어 있기 때문입니다. 그래서 우리가 따로 적지 않아도
컨테이너가 켜지면 Nginx가 웹 서버로 동작합니다.
6.6 [우리 프로젝트] .dockerignore — 상자에 넣지 말 것 골라내기
이미지를 만들 때, 우리 폴더의 모든 파일이 다 필요한 건 아닙니다. 어떤
파일은 오히려 넣으면 안 됩니다. 이걸 걸러 주는 파일이 .dockerignore
입니다.
.dockerignore
이미지를 만들 때 "이미지 안에 넣지 않을 파일 목록"을 적어 두는 파일입니다.
4장에서 본 .gitignore(GitHub에 올리지 않을 목록)의 Docker 버전이라고
보면 됩니다. 파일 이름은 점(.)으로 시작하는 .dockerignore입니다.
무엇을 넣지 말아야 할까요? 대표적으로 이런 것들입니다.
node_modules— 설치된 라이브러리 폴더. 어차피 이미지 안에서RUN npm install로 새로 설치하므로, 복사해 넣으면 용량만 커지고 충돌도 납니다..env— 비밀번호 같은 민감한 정보. 이미지 안에 구워 넣으면 위험합니다. (환경변수는 7장에서 실행할 때 따로 넣어 줍니다.).git— 코드 이력 폴더. 이미지 실행에는 필요 없습니다.
Claude Code에게 두 폴더 것을 한꺼번에 만들어 달라고 합시다.
만든 뒤 VS Code 파일 목록에서 backend/.dockerignore, frontend/.dockerignore
두 파일이 생겼는지 확인합니다. 열어 보면 위에서 말한 목록이 한 줄씩
적혀 있습니다.
점(.)으로 시작하는 파일이 안 보인다면
.dockerignore처럼 점으로 시작하는 파일은 "숨김 파일"로 취급됩니다.
VS Code 파일 목록에는 보통 그대로 보이지만, 혹시 안 보이면 Claude
Code에게 "backend 폴더 안 파일 목록을 보여 줘"라고 물어 확인할 수
있습니다.
.dockerignore가 있으면 이미지가 더 작고, 안전하고, 빠르게 만들어집니다.
6.7 왜 목록 파일부터 복사했나 — 레이어 캐시
마지막으로, 6.4에서 미뤄 둔 질문 하나를 풉니다. API Dockerfile에서
소스 코드 전체(COPY . .)보다 부품 목록 파일(COPY package*.json)을
먼저 복사한 이유가 있습니다. 여기엔 "레이어 캐시"라는 개념이 숨어
있습니다. 지금은 원리만 가볍게 이해하면 됩니다.
레이어(Layer)와 캐시(Cache) Docker는 Dockerfile의 명령을 한 줄씩 실행하면서 그 결과를 "층(레이어)" 으로 차곡차곡 쌓아 이미지를 만듭니다. 그리고 한 번 만든 층은 저장해 뒀다가(캐시), 다음에 다시 만들 때 그 층에서 바뀐 게 없으면 새로 만들지 않고 그대로 재사용합니다. 그러면 이미지를 훨씬 빨리 만들 수 있습니다.
이게 왜 순서와 관련 있을까요? 우리가 개발하면서 코드를 수정하면, 보통
소스 코드는 자주 바뀌지만 부품 목록(package.json)은 잘 안 바뀝니다.
그래서:
- 목록을 먼저 복사하고 설치해 두면, 소스만 고쳤을 때는 "설치
(
RUN npm install)" 층이 그대로 재사용됩니다. → 이미지 만들기가 빨라집니다. - 만약 소스와 목록을 한꺼번에 복사했다면, 소스 한 글자만 바뀌어도 그 뒤의 라이브러리 설치를 매번 처음부터 다시 해야 합니다. → 느려집니다.
즉 "잘 안 바뀌는 것을 앞에, 자주 바뀌는 것을 뒤에" 두는 것이 이미지를 빠르게 만드는 요령입니다. Claude Code는 보통 이 순서를 알아서 지켜 Dockerfile을 만들어 줍니다. 여러분은 "왜 이렇게 돼 있지?"를 이해하는 것으로 충분합니다.
6.8 [참고] 이미지를 가볍게 만드는 이유
지금까지 alpine 베이스 이미지, 멀티스테이지 빌드, .dockerignore가
계속 "이미지를 가볍게" 만든다고 했습니다. 이미지가 가벼우면 좋은 점이
많기 때문입니다.
- 레지스트리에 올리고 내려받는 게 빨라집니다. (2부에서 AWS ECR에 올릴 때)
- 서버에서 배포가 빨라집니다.
- 저장 공간과 비용이 줄어듭니다.
그래서 실무에서도 alpine 같은 가벼운 베이스 이미지와 멀티스테이지 빌드,
.dockerignore를 습관처럼 함께 씁니다. 우리 Dockerfile도 이 세 가지를
모두 갖췄습니다.
[확인] 6장이 잘 끝났는지 눈으로 확인하기
VS Code 왼쪽 파일 목록에서 아래 파일들이 실제로 생겼는지 확인합니다.
backend/Dockerfilebackend/.dockerignorefrontend/Dockerfilefrontend/.dockerignore
그리고 각 파일을 열었을 때, 안에 명령들이 채워져 있고 여러분이 그 뜻을
말로 설명할 수 있으면 이 장은 성공입니다. 예를 들어 누가 옆에서
"FROM node:22-alpine이 무슨 뜻이야?"라고 물으면, "Node.js 22가 이미
깔린 가벼운 이미지에서 시작한다는 뜻"이라고 답할 수 있으면 됩니다.
이미지 빌드는 아직 안 합니다
이 장은 설명서(Dockerfile)를 만들고 읽는 데까지입니다. 이 설명서로
실제 이미지를 굽고 컨테이너로 실행하는 것은 7장에서 합니다. 그러니
지금 docker build 같은 명령을 실행하지 않아도 정상입니다.
막히면
이 장에서 초보자가 자주 막히는 지점과 대처법입니다.
-
backend나frontend폴더가 VS Code에 안 보인다. 4장의 서비스 만들기가 아직 안 끝난 것입니다. 4장으로 돌아가 프론트엔드· 백엔드 폴더가 만들어질 때까지 진행한 뒤 다시 오세요. 또는 VS Code가 다른 폴더를 열고 있을 수도 있습니다. File → Open Folder로 문서 폴더의vote-app을 다시 여세요. -
Claude Code가
Dockerfile을 만들었다는데 파일이 안 보인다. 엉뚱한 폴더에 만들었을 수 있습니다. Claude Code에게 "backend 폴더 안에 Dockerfile이 있는지 확인해 줘"라고 물어보세요. 다른 위치에 있으면 "backend 폴더 안으로 옮겨 줘"라고 요청합니다. -
만들어진 Dockerfile 내용이 이 책의 예시와 조금 다르다. 괜찮습니다. Claude Code는 여러분의 실제 프로젝트를 보고 맞춰 만들기 때문에, 시작 명령(
CMD)의 파일 이름이나 포트 번호 등이 조금 다를 수 있습니다. 중요한 건FROM으로 시작해COPY·RUN·CMD흐름으로 이어지는 큰 구조가 같은지입니다. 뜻이 이해되면 됩니다. -
파일 이름이
Dockerfile이 아니라dockerfile.txt등으로 되어 있다. Claude Code에게 "파일 이름을 정확히 Dockerfile로 바꿔 줘(확장자 없이)" 라고 요청하세요. 7장에서 빌드하려면 이름이 정확히Dockerfile이어야 합니다.
[체크리스트]
아래가 모두 됐는지 확인해 보세요. 하나라도 안 됐다면 해당 절로 돌아가 다시 진행합니다.
- □ Dockerfile이 "이미지를 만드는 설명서"임을 안다
- □
FROM/WORKDIR/COPY/RUN/EXPOSE/CMD의 뜻을 대략 말할 수 있다 - □
backend/Dockerfile을 만들고, 한 줄씩 읽어 뜻을 설명할 수 있다 - □ 베이스 이미지와
alpine이 무엇인지 안다 - □
frontend/Dockerfile이 왜 멀티스테이지(빌드 → Nginx 서빙)인지 이해했다 - □
COPY --from=build가 무슨 일을 하는지 안다 - □
backend/.dockerignore,frontend/.dockerignore를 만들고, 무엇을 제외하는지 안다 - □ 목록 파일을 소스보다 먼저 복사하는 이유(레이어 캐시)를 이해했다
모두 체크됐다면, 우리 서비스를 이미지로 만드는 설명서(Dockerfile)가 준비된 것입니다.