DockerFile
2025. 12. 31. 17:47ㆍDocker
🐳 Dockerfile
Dockerfile = 컨테이너가 아니라 “이미지”를 만드는 설계도 📐
Dockerfile은 Docker 이미지를 만들기 위한 설계도라고 생각하면 쉽습니다. 특정 애플리케이션을 실행하기 위해 필요한 운영체제, 라이브러리, 환경 변수, 설정 파일 등을 텍스트 파일에 차례대로 기록한 것입니다.
1. Dockerfile의 핵심 동작 원리
Dockerfile을 작성한 후 docker build 명령어를 실행하면, 도커 엔진이 도커파일의 명령어(Instruction)를 위에서부터 아래로 한 줄씩 읽으며 도커 이미지를 생성합니다.
- Layer 구조: 각 지시어는 하나의 레이어(Layer)를 형성합니다. 변경 사항이 없는 레이어는 캐시(Cache)를 사용하여 빌드 속도를 높입니다.
- 자동화: 환경 구축 과정을 코드(Infrastructure as Code)로 관리하므로, 어떤 환경에서든 동일한 상태의 컨테이너를 배포할 수 있습니다.
2. 주요 명령어 (Instructions)
가장 자주 사용되는 핵심 명령어들은 다음과 같습니다.
| 지시어 | 설명 | 예시 |
|---|---|---|
| FROM | 베이스 이미지를 지정 (반드시 첫 줄에 위치) | FROM node:18 |
| WORKDIR | 명령어가 실행될 작업 디렉토리 설정 (cd와 유사) | WORKDIR /app |
| COPY / ADD | 호스트의 파일을 이미지 내부로 복사 | COPY . . |
| RUN | 이미지 빌드 시점에 실행할 명령어 (패키지 설치 등) | RUN npm install |
| CMD | 컨테이너가 시작될 때 실행할 기본 명령 (한 번만 사용) | CMD ["node", "app.js"] |
| ENTRYPOINT | 컨테이너를 실행 파일처럼 사용할 때 고정 명령 지정 | ENTRYPOINT ["python"] |
| EXPOSE | 컨테이너가 사용할 포트 번호를 명시 | EXPOSE 8080 |
| ENV | 환경 변수 설정 | ENV NODE_ENV production |
3. 간단한 작성 예시 (Node.js 기준)
# 1. 베이스 이미지 지정
FROM node:16-alpine
# 2. 컨테이너 내 작업 디렉토리 생성
WORKDIR /usr/src/app
# 3. 라이브러리 설치를 위해 설정 파일 복사
COPY package*.json ./
# 4. 의존성 설치
RUN npm install
# 5. 나머지 소스 코드 복사
COPY . .
# 6. 포트 개방
EXPOSE 3000
# 7. 서버 실행
CMD ["node", "server.js"]
4. 효율적인 Dockerfile 작성을 위한 팁
.dockerignore파일 사용: 이미지에 포함될 필요 없는 파일(예:node_modules,.git,.env)을 제외하여 이미지 크기를 줄이세요.- 레이어 최적화: 자주 변하지 않는 부분(라이브러리 설치)을 상단에, 자주 변하는 소스 코드를 하단에 배치하여 캐시 효율을 극대화합니다.
- 최소 크기의 베이스 이미지 선택:
ubuntu보다는 가벼운alpine이나slim버전을 사용하는 것이 보안과 속도 면에서 유리합니다. - 멀티 스테이지 빌드 (Multi-stage Build): 빌드 도구와 실행 환경을 분리하여 최종 이미지 크기를 수 배 이상 줄일 수 있는 고급 기술입니다.
🐳 Dockerfile Instruction
Dockerfile은 Instruction(명령어)들의 집합입니다.
각 Instruction은 빌드 타임 / 런타임 / 레이어 생성 여부가 명확히 다릅니다.
🧱 FROM – 베이스 이미지 지정 (필수)
FROM ubuntu:24.04
📌 역할
- 이미지 빌드의 시작점
- 모든 레이어는 이 이미지 위에 쌓임
⚙️ 특징
- 반드시 첫 줄(단,
ARG예외) - 여러 번 사용 가능 → 멀티스테이지 빌드
💡 실무 포인트
latest❌ → 재현성 깨짐- 명시적 버전 ⭕ (
ubuntu:24.04)
⚙️ ARG – 빌드 타임 변수
ARG APP_ENV=prod
📌 역할
- 빌드 시점에만 사용되는 변수
- 이미지 런타임에는 기본적으로 존재 ❌
📦 사용 예
ARG VERSION
RUN echo $VERSION
docker build --build-arg VERSION=1.0 .
⚠️ 주의
- 보안 정보 저장 ❌ (히스토리에 남음)
🌍 ENV – 환경 변수 (런타임까지 유지)
ENV TZ=Asia/Seoul
📌 역할
- 컨테이너 실행 시에도 유지되는 환경 변수
📦 사용 예
ENV JAVA_OPTS="-Xms512m -Xmx512m"
⚠️ 주의
- 비밀키/패스워드 ❌
(이미지에 영구 저장됨)
📁 WORKDIR – 작업 디렉터리 설정
WORKDIR /app
📌 역할
- 이후 명령들의 기본 디렉터리
- 디렉터리 없으면 자동 생성
💡 실무 포인트
cd /app && ...보다 가독성/안전성 ⭕RUN,COPY,CMD,ENTRYPOINT에 영향
🧱 RUN – 빌드 타임 명령 실행
RUN apt-get update && apt-get install -y curl
📌 역할
- 이미지 빌드 중 명령 실행
- 실행 결과가 레이어로 고정
🧠 레이어 관점
- RUN 하나 = 레이어 하나
- 파일 생성/삭제 → diff 기록
⚠️ 실무 주의
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
❌ 레이어 용량 줄지 않음
📦 COPY – 파일 복사 (권장)
COPY src/ /app/src/
📌 역할
- 호스트 → 이미지 파일 복사
⚙️ 특징
- 단순하고 예측 가능
- 캐시 친화적
💡 실무 표준
COPY 사용, ADD 지양
📦 ADD – 확장 복사 (비권장)
ADD app.tar.gz /app
📌 추가 기능
- tar 자동 해제
- URL 다운로드
⚠️ 문제점
- 예측 불가
- 캐시 깨짐
- 보안 이슈 가능
👤 USER – 실행 사용자 변경
USER app
📌 역할
- 이후 RUN/CMD/ENTRYPOINT 실행 사용자 지정
🔐 보안 관점
- root ❌
- non-root ⭕ (권장)
🔐 RUN useradd + USER 패턴 (실무 필수)
RUN useradd -r -M -s /usr/sbin/nologin app \
&& chown -R app:app /app
USER app
📌 의미
- 시스템 사용자 생성
- 로그인 쉘 차단
- 권한 최소화
📌 EXPOSE – 사용 포트 문서화
EXPOSE 8080
📌 역할
- “이 컨테이너는 이 포트를 사용함” 선언
⚠️ 오해 금지
- 실제 포트 개방 ❌
-p,ports:에서 결정됨
🚀 CMD – 기본 실행 명령 또는 인자
CMD ["java","-jar","app.jar"]
📌 역할
- 컨테이너 기본 실행 명령
docker run시 덮어쓰기 가능
⚠️ 특징
Dockerfile에 1개만 유효
🎯 ENTRYPOINT – 고정 실행 파일
ENTRYPOINT ["java","-jar","app.jar"]
📌 역할
- 컨테이너의 “정체성”
- 실행 파일 고정
💡 추천 조합
ENTRYPOINT ["java","-jar","app.jar"]
CMD ["--server.port=8080"]
❤️ HEALTHCHECK – 컨테이너 상태 점검
HEALTHCHECK CMD curl -f http://localhost:8080/health || exit 1
📌 역할
- 컨테이너의 정상/비정상 판단
🧩 활용
- Docker Compose
- Swarm
- 일부 운영 환경
📦 VOLUME – 볼륨 사용 의도 표시
VOLUME /data
📌 역할
- 해당 경로를 영속 데이터 영역으로 선언
⚠️ 실무 주의
- 익명 볼륨 자동 생성 가능
- 운영에선 Compose에서 관리 권장
🏷 LABEL – 메타데이터 추가
LABEL version="1.0" maintainer="team@example.com"
📌 역할
- 이미지 정보 설명
- 자동화/관리 도구 활용
🧪 ONBUILD – 자식 이미지용 트리거
ONBUILD COPY . /app
📌 역할
- 이 이미지를 베이스로 사용할 때 자동 실행
⚠️ 난이도
- 디버깅 어려움
- 플랫폼 베이스 이미지에서만 사용 권장
🔄 SHELL – 기본 쉘 변경
SHELL ["/bin/bash","-lc"]
📌 역할
- RUN 명령 실행 쉘 변경
🧠 Instruction 요약 표
| 명령 | 빌드 | 런타임 | 레이어 |
|---|---|---|---|
| FROM | ⭕ | ❌ | ⭕ |
| ARG | ⭕ | ❌ | ❌ |
| ENV | ⭕ | ⭕ | ❌ |
| WORKDIR | ⭕ | ⭕ | ❌ |
| RUN | ⭕ | ❌ | ⭕ |
| COPY/ADD | ⭕ | ❌ | ⭕ |
| USER | ⭕ | ⭕ | ❌ |
| CMD | ❌ | ⭕ | ❌ |
| ENTRYPOINT | ❌ | ⭕ | ❌ |
✍️ 한 줄 결론
Dockerfile의 각 커맨드는
“언제 실행되는가(빌드/런타임)”와
“레이어를 만드는가”를 기준으로 이해해야 합니다 🐳
'Docker' 카테고리의 다른 글
| Docker Compose 네트워크 (0) | 2025.12.31 |
|---|---|
| 디폴트 브릿지 vs 사용자 정의 브릿지 (0) | 2025.12.31 |
| Docker Network (0) | 2025.12.31 |
| Union File System & Overlay File System (0) | 2025.12.31 |
| Spring Boot 앱의 JAR 파일 구조 (0) | 2025.12.30 |