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 |