[Docker] Dockerfile

Dockerfile

 
지금까지 Dockerhub를 통해 이미지를 다운 받아서 사용했다. 그렇다면 이러한 이미지들은 어떻게 만들어진 것일까? 바로 Dockerfile을 사용해 Docker 이미지를 만들 수 있다.
 

Dockerfile은 Docker 이미지를 만들게 해주는 파일이다. Spring Boot 프로젝트 자체를 Docker 이미지로 만든다거나 하는데 사용할 수 있다. 참고로 Spring Boot 프로젝트를 Docker 이미지로 만들게 되면 JDK 런타임 환경이나 JAR 파일이나 애플리케이션을 실행하는 명령 등등이 포함될 수 있다.
 

 

 

FROM : 베이스 이미지 생성

 
Dockerfile로 이름을 짓고 파일 내에서 문법에 맞는 명령어로 작성하면 된다. 첫 번째로 배울 명령어는 FROM이다. 해당 명령어는 베이스 이미지를 생성하는 역할을 한다. Docker 컨테이너를 특정 초기 이미지를 기반으로 추가적인 세팅을 할 수 있는데, 여기서 '특정 초기 이미지'를 베이스 이미지라고 한다.
 

# 문법
FROM [이미지명]
FROM [이미지명]:[태그명]
  • 태그명을 적지 않으면 latest

예시를 통해 살펴보자.

 

1. Dockerfile 만들기

FROM openjdk:17-jdk

 

2. Dockerfile을 기반으로 이미지 만들기

$ docker build -t my-jdk17-server .

 

3. 이미지를 기반으로 컨테이너 띄우기

$ docker run -d my-jdk17-server

 

4. 컨테이너 조회하기

$ docker ps # 실행되고 있는 컨테이너가 없다.
$ docker ps -a # 확인해보니 컨테이너가 종료되어 있다.

Docker의 컨테이너는 내부적으로 필요한 명령을 다 수행하면 컨테이너가 저절로 종료된다.
 

5. 컨테이너 내부로 들어가서 jdk가 잘 깔렸는지 확인해보기
내부적으로 필요한 명령을 다 수행하면 컨테이너가 종료된다. 그렇다면 이 종료된 컨테이너 안에 들어가서 디버깅을 하려면 어떻게 해야 할까?

 

종료된 컨테이너 안에 들어가려 하면 에러 발생

 

Dockerfile에 아래와 같이 명령어를 추가함으로써 컨테이너가 바로 종료되는 걸 막을 수 있다.

FROM openjdk:17-jdk

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] # 500초 동안 시스템을 일시정지 시키는 명령어
$ docker build -t my-jdk17-server . # 이미지 빌드
$ docker run -d my-jdk17-server # 컨테이너 실행
$ docker ps # 실행 중인 컨테이너 조회
$ docker exec -it [컨테이너 ID] bash # 컨테이너 접속

$ java -version # JDK 설치되어 있는지 확인

 

 

 

COPY : 파일 복사(이동)

 
COPY는 호스트 컴퓨터에 있는 파일을 복사해서 컨테이너로 전달한다.
 

# 문법
COPY [호스트 컴퓨터에 있는 복사할 파일의 경로] [컨테이너에서 파일이 위치할 경로]

# 파일 복사 예시
COPY app.txt /app.txt

# 폴더 복사 예시(/ 붙이기)
COPY my-app /my-app/

# 와일드 카드 사용 예시
COPY *.txt /text-files/

그렇다면 특정 파일 또는 폴더만 COPY하고 싶지 않을 때는 어떻게 할까? 이를 위해 .dockerignore가 존재한다!

 

1. .dockerignore 파일 만들기

readme.txt

 

2. Dockerfile 만들어서 이미지 생성 및 컨테이너 실행

FROM ubuntu

COPY ./ /

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] # 디버깅용 코드
$ docker build -t my-server .
$ docker run -d my-server
$ docker exec -it [Container ID] bash

$ ls

 

 

 

ENTRYPOINT : 컨테이너가 시작할 때 실행되는 명령어

 
ENTRYPOINT는 컨테이너가 생성되고 최초로 실행될 때 수행되는 명령어를 의미한다.
 

# 문법
ENTRYPOINT [명령문...]

# 예시(기본적으로 리눅스 명령어 입력) 
ENTRYPOINT ["node", "dist/main.js"]

 

 

 

RUN : 이미지를 생성하는 과정에서 사용할 명령문 실행

 
RUN은 이미지 생성 과정에서 명령어를 실행시켜야 할 때 사용한다.
 

# 문법
RUN [명령문]

# 예시
RUN npm install

ENTRYPOINT 역시 명령어를 실행시키는데 RUN은 무슨 차이점이 있을까? 명령어의 실행 시점이 다르다는 점에 주의해야 한다. ENTRYPOINT는 생성된 이미지를 기반으로 컨테이너를 생성한 직후에 명령어를 실행시킬 때 사용하고, RUN이미지 생성 과정에서 필요한 명령어를 실행시킬 때 사용한다.
 

 

 

WORKDIR : 작업 디렉토리를 지정

 
WORKDIR으로 작업 디렉터리를 전환하면 그 이후에 등장하는 모든 RUN, CMD, ENTRYPOINT, COPY, ADD 명령문은 해당 디렉터리를 기준으로 실행된다. 작업 디렉터리를 굳이 지정해주는 이유는 컨테이너 내부의 폴더를 깔끔하게 관리하기 위해서이다.
 

컨테이너도 미니 컴퓨터와 같기 때문에 Dockerfile을 통해 생성되는 파일들을 특정 폴더에 정리해두는 것이 추후에 관리가 쉽다. 만약 WORKDIR을 쓰지 않으면 컨테이너 내부에 존재하는 기존 파일들과 뒤섞여버린다.

# 문법
WORKDIR [작업 디렉토리로 사용할 절대 경로]

# 예시
WORKDIR /usr/src/app

 

 

 

EXPOSE : 컨테이너 내부에서 사용 중인 포트를 문서화하기

 
EXPOSE는 컨테이너 내부에서 어떤 포트에 프로그램이 실행되는지를 문서화하는 역할만 한다. 즉 작동방식과는 관련이 없는 명령어이다.
 

# 문법
EXPOSE [포트 번호]

# 예시
EXPOSE 3000
  • 3000번 포트에서 실행된다고 알려주는 역할 정도

'INFRA > Docker' 카테고리의 다른 글

[Docker] Docker Compose - 2  (2) 2025.06.17
[Docker] Docker Compose - 1  (4) 2025.06.16
[Docker] Docker Volume(도커 볼륨)  (7) 2025.06.04
[Docker] 자주 쓰는 Docker CLI  (2) 2025.06.04
[Docker] Docker 기본 개념  (2) 2025.06.01