DOCKER

[Docker] Dockerfile를 사용하여 dockerimage 직접 만들기

ch010104 2025. 6. 19. 16:10

1. Dockerfile이란?

  • Dockerfile은 Docker 이미지를 만들기 위한 설정 파일
  • 우리가 사용하는 Docker 이미지들은 누군가가 Dockerfile을 작성해서 만든 결과물이며, 이 파일을 기반으로 docker build 명령어를 통해 이미지를 생성

✨ 사용 예시

  • 내가 만든 Spring Boot 프로젝트를 Docker 이미지로 만들어 배포하고 싶을 때
  • Node.js 또는 JDK가 미리 설치된 이미지로 개발 환경을 세팅하고 싶을 때

Dockerfile을 통해 우리는 '내가 원하는 환경이 세팅된 컨테이너'를 구성할 수 있음

이는 마치 새 컴퓨터를 구매했을 때 운영체제만 설치된 상태에서 필요한 프로그램을 직접 설치하는 것과 같음

Dockerfile의 FROM 명령어는 바로 이 '운영체제가 설치된 초기 상태'를 의미하며, 그 위에 추가적인 명령어들을 통해 내가 원하는 상태로 점점 쌓아나가는 것


2. Dockerfile 주요 명령어 정리 및 실습

1) FROM: 베이스 이미지 생성

설명:

  • 초기 OS 또는 환경 설정을 위한 베이스 이미지를 지정.
  • FROM 명령어는 Dockerfile의 첫 줄에 위치하며, 컨테이너가 어떤 환경에서 시작될지를 결정
FROM openjdk:17-jdk
  • openjdk:17-jdk: Java 17이 설치된 리눅스 기반 이미지
  • node, ubuntu, python, alpine 등도 자주 사용되는 베이스 이미지이다

비유 설명: 컴퓨터를 처음 살 때 Windows나 macOS 중 어떤 운영체제를 쓸지를 고르는 것과 같음.

docker build -t my-jdk17-server .
docker run -d my-jdk17-server
docker exec -it [ContainerID] bash
java -version
  • 컨테이너가 자동 종료되는 것을 막기 위해 다음과 같이 작성할 수 있음
ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

2) COPY: 파일 복사

설명:

  • 호스트(내 PC) 상의 파일을 컨테이너 내부로 복사
  • Dockerfile이 있는 디렉터리 기준으로 상대 경로를 지정할 수 있으며, 폴더 전체도 복사 가능
COPY app.txt /app.txt
COPY my-app/ /my-app/
COPY *.txt /text-files/
  • COPY a b: 로컬의 a를 컨테이너 내부 경로 b로 복사
  • 와일드카드(*.txt)도 사용 가능
  • 디렉터리를 복사할 경우 꼭 /my-app/처럼 끝에 슬래시를 붙일 것

.dockerignore 파일로 복사 제외하기:

.dockerignore
node_modules
readme.txt

COPY ./ ./을 쓸 경우 불필요한 파일까지 모두 복사되므로 .dockerignore를 꼭 활용!!


 

3) ENTRYPOINT: 컨테이너 실행 시 최초 실행 명령어

설명:

  • 컨테이너가 시작되자마자 실행할 명령어를 정의
  • 이 명령어는 컨테이너가 시작될 때 한 번만 실행되며, 일반적으로 서버 실행이나 대기 상태를 위해 사용
ENTRYPOINT ["java", "-jar", "/app.jar"]

 

디버깅용 예시:

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"]

sleep을 이용하면 컨테이너가 바로 종료되지 않도록 하고, 그 사이 exec로 진입해 내부 확인이 가능


4) RUN: 이미지 생성 시 명령어 실행

설명:

  • 이미지를 빌드할 때 한 번 실행되는 명령어
  • 주로 패키지 설치, 파일 복사, 환경 설정 등에 사용
RUN apt update && apt install -y git
RUN npm install

 

RUN vs ENTRYPOINT 비교:

  • RUN: 이미지 생성 시 실행 → 결과가 이미지에 포함됨
  • ENTRYPOINT: 컨테이너 실행 시 실행 → 실행 환경 제어 목적

5) WORKDIR: 작업 디렉터리 지정

설명:

  • 이후 명령어들이 실행될 기본 경로를 지정
  • 지정하지 않으면 컨테이너 루트(/)에서 실행
WORKDIR /usr/src/app

COPY, RUN, CMD 등은 이 WORKDIR을 기준으로 동작함

 

예시:

WORKDIR /my-dir
COPY ./ ./
  • → 컨테이너 내 /my-dir 경로에 파일들이 복사됨

6) EXPOSE: 컨테이너 내부 포트를 문서화

설명:

  • 컨테이너가 내부적으로 사용하는 포트를 명시
  • 실제로 외부와 연결되려면 docker run -p 옵션으로 매핑해주어야 함
EXPOSE 8080

문서화용일 뿐, 포트를 열어주는 역할은 하지 않음


3. 실습: 프로젝트별 Dockerfile 작성 예시

⚡1) Spring Boot 프로젝트

FROM openjdk:17-jdk
COPY build/libs/*SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

명령어:

./gradlew clean build
docker build -t hello-server .
docker run -d -p 8080:8080 hello-server


⚡ 2) Nest.js 프로젝트

# Nest CLI 
설치
$ npm i -g @nestjs/cli
 # nest new {
프로젝트명
}
 $ nest new my-server
FROM node
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
ENTRYPOINT ["node", "dist/main.js"]

 

명령어:

docker build -t my-server .
docker run -d -p 3000:3000 my-server


⚡3) Next.js 프로젝트

$ npx create-next-app@latest
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3000
ENTRYPOINT ["npm", "run", "start"]

.dockerignore:

node_modules


⚡ 4) HTML + CSS + Nginx 배포

# index.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="style.css">
    <title>My Web Page</title>
</head>
<body>
<h1>MY WEB PAGE</h1>
</body>
</html>
#style.css
* {
  color: blue;
 }
FROM nginx
COPY ./ /usr/share/nginx/html

명령어:

docker build -t my-web-server .
docker run -d -p 80:80 my-web-server

index.html 파일명이 꼭 있어야 Nginx가 기본 페이지로 인식


4. 디버깅 팁

  • 컨테이너가 자동 종료되는 것을 방지하려면 ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] 추가
  • 종료된 컨테이너에는 docker exec로 접근할 수 없음 → docker ps로 실행 상태 확인
  • docker logs [ContainerID]로 로그 확인
  • 컨테이너가 어떤 과정을 거쳐 실행되는지 확인하고자 한다면 ENTRYPOINT에 sleep을 걸고 직접 진입해서 ls, cat, env 등으로 확인하는 습관을 기르자