docker

Dokerfile 활용해 이미지 직접 만들기

경딩 2025. 4. 15. 21:34

Dockerfile 이란?

Docker 이미지는 Dockerhub 을 통해 다운받아서 사용할 수 있다. 이  Docker 이미지들도  누군가 만들어서 Dockerhub 에 올려놓은 것이다. 

 

Dockerfile 이라는 걸 활용해서 Docker 이미지를 만들 수 있다.

즉 Dockerfile 은 도커 이미지를 생성하기 위한 설정 파일이다.

이 파일에는 어떤 OS 를 사용할지, 어떤 파일을 복사하고, 어떤 명령어를 실행할 지 등 이미지 구성에 필요한 명령어들이 순차적으로 정의 되어있다.

FROM openjdk:17
COPY ./app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]

 

더보기

도커 이미지(Docker Image)

  • 도커 이미지는 애플리케이션 실행에 필요한 모든것을 포함한 불변의 실행 패키지이다.
  • OS, 실행 파일, 코드, 라이브러리 등을 포함하며, Dockerfile 을 기반으로 생성된다. 
  • 이미지를 실행하면 도커 컨테이너가 된다.

 

Dockerhub 에 올려놓은 Docker 이미지가 아닌, 나만의 Docker 이미지를 만들고 싶을 수 있다.

예를 들어, 내가 만든 Spring Boot 프로젝트가 있다. 내가 만든 Spring Boot 프로젝트 자체를 Docker 이미지로 만들고 싶을 수 있다. 이럴 때에도 Dockerfile을 활용하면 나만의 Docker 이미지를 만들 수 있게 된다.

 

즉 Dockerfile 이란? Docker 이미지를 만들게 해주는 파일

 

더보기

도커 컴포즈(Docker Compose)란?

Docker compose 는 여러 개의 도커 컨네이너를 하나의 서비스 단위로 정의하고 실행할 수 있게 해주는 도구이다.

docker-compose.yml 파일을 사용하여, 애플리케이션의 여러 컨테이너(예: 웹 서버, DB, 캐시 등)를 한 번에 정의하고 docker-compose up 명령으로 실행할 수 있다.

version: '3'
services:
  web:
    image: nginx
    ports:
      - "80:80"
  db:
    image: mysql
    environment:
      MYSQL_ROOT_PASSWORD: example

 

 


용어 정의
Dockerfile 도커 이미지를 만들기 위한 스크립트
Docker Image 실행 가능한 컨테이너 패키지
Docker Compose 여러 컨테이너를 서비스 단위로 구성, 실행 도구

 

FROM : 베이스 이미지 생성

From 은 베이스 이미지를 생성하는 역할을 한다. Docker 컨테이너를 특정 초기 이미지를 기반으로 추가적인 셋팅을 할 수 있다.

여기서 이야기 한 특정  초기 이미지 가 곧 베이스 이미지이다.

 

예를 들어 우리가 윈도우 컴퓨터를 새로 사서 실행시켜보면 기본 프로그램들(인터넷, 그림판, 메모장 등) 이 많이 깔려있다.

베이스 이미지도 이와 똑같다. 컨테이너를 새로 띄어서 미니 컴퓨터 환경을 구축할 때 기본 프로그램이 어떤게 깔려있으면 좋을지 선택하는 옵션이라고 생각하면 된다.

 

누군가는 JDK 가 깔려있는 컴퓨터 환경이 셋팅되기를 바랄 수 있고, 누군가는 Node 가 깔려있는 컴퓨터 환경을 셋팅되기를 발라 수 있다. 필요에 따라 베이스 이미지를 고르면 된다.

# 문법
FROM [이미지명]
FROM [이미지명]:[태그명]
  • 태그명을 적지 않으면 해당 이미지의 최신(latest) 버전을 사용한다.

 

실습

Dockerfile 이라는 이름의  파일을 생성해보자.

1. Dockerfile 만들기

  • Dockerfile
# JDK 17 이 포함된 공식 openJDK 이미지에서 시작
FROM openjdk:17-jdk

 

 

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

# docker build -t [이미지명]:[태그명] [Dockerfile이 존재하는 디렉터리 경로]

$ docker build -t sample .
$ docker build -t sample:1.0 .

 

  • 실제 실행 명령어
[root@localhost dockerfile-pr]# docker build -t my-jdk17-server .

  • 도커파일을 기반으로 이미지가 생성된것을 확인 할 수 있다.

태그명을 붙일 수도 있다.

 

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

docker run -d my-jdk17-server

 

4. 컨테이너 조회하기

$ docker ps # 실행되고 있는 컨테이너가 없다.

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

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

 

5. 컨테이너 내부로 들어가서 jdk 가 잘 깔렸는지 확인하기

Dockerfile 에 ENTRYPOINT 를 추가해보자.

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 설치되어 있는 지 확인

 

시스템이 정상적으로 실행중이며, docker exec 명령어로 통해 내부 셸 접속이 가능한 상태임을 확인할 수 있다.

 docker exec -it 1f bash

 

 

도커안에 접속하면 자바가 설치되어 있는 것을 확인할 수 있다.

 

 

COPY : 파일 복사(이동)

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

 

 

사용법

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

# 예시
COPY app.txt /app.txt

 

 

파일 복사해보기.

1. app.txt 파일 만들기

 

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

Dockerfile

FROM ubuntu

COPY app.txt /app.txt  # host 에 컴퓨터에있는 app.txt 컨테이너 절대경로에 복사한다.

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] # 디버깅용 코드

 

# 현재 디렉토리의 Dockerfile을 기반으로 'my-server'라는 이름(tag)으로 이미지를 빌드
$ docker build -t my-server .

# 백그라운드(-d)에서 'my-server' 이미지를 기반으로 컨테이너를 실행
$ docker run -d my-server

# 실행 중인 컨테이너 내부로 bash 셸을 실행하며 들어감 (여기서 [Container ID]는 실제 컨테이너 ID로 대체)
$ docker exec -it [Container ID] bash

# 컨테이너 내부에서 현재 디렉토리에 있는 파일 및 디렉토리 목록 확인
$ ls

 

도커로 접속해서 app.txt  파일이 있는 것을 확인해볼 수 있다.

특정 파일 또는 폴더만 COPY를 하고 싶지 않을 수 있다. 그럴 때 .dockerignore를 활용한다.
 
.dockerignore 파일 만들기
.dockerignore
readme.txt​
 
 
Dockerfile 만들어서 이미지 생성 및 컨테이너 실행
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 [명령문...]

# 예시
ENTRYPOINT ["node", "dist/main.js"]

 

 

예제

Dockerfile

# 베이스 이미지로 Ubuntu 리눅스를 사용
FROM ubuntu

# 컨테이너 시작 시 실행할 명령 설정
# /bin/bash  셸을 실행하고, -c 옵션을 통해 "echo hello" 명령어를 전달
# 결과적으로 "hello" 를 출력하고 컨테이너는 종료됨.
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]

 

$ docker build -t my-server .
$ docker run -d my-server
$ docker ps -a
$ docker logs [Container ID]

 

 

docker 로그를 확인해 보면 hello 를 잘 출력한 것을 확인 할 수 있다.

 

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

의미

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

 

사용법

# 문법
RUN [명령문]

# 예시
RUN npm install

 

RUN vs ENTRYPOINT

RUN  : 이미지 생성 과정서 필요한 명령어를 실행 시킬 때 사용

ENTRYPOINT : 생성된 이미지를 기반으로 컨테이너를 생성한 직후에 명령어를 실행시킬 때 사용

 

 

예제

미니 컴퓨터 환경이 ubuntu 로  구성되었으면 좋겠고 git 이 깔려있으면 좋겠다고 가정하자. 이런 환경을 구성하기 위해 Dockerfile 을 활용해 ubuntu. git 이 깔려있는 이미지를 만들면 좋겠다.

Dockerfile 작성하기

  1. Dockerfile
FROM ubuntu

RUN apt update && apt install -y git # 이미지 생성 과정

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] # 프로그램에 실행에 필요한 명령어 실행시키기

 

 

이미지 빌드 및 컨테이너 실행

$ docker build -t my-server .
$ docker run -d my-server
$ docker exec -it [Container ID] bash

$ git -v # 컨테이너 내에 git이 잘 설치됐는 지 확인

 

 

WORKDIR : 작업 디렉토리를 지정

 

작업 디렉터리를 굳이 지정해주는 이유는 컨테이너 내부의 폴더를 깔끔하게 관리해보자.

 

WORKDIR으로 작업 디렉터리를 전환하면 그 이후에 등장하는 모든 RUN, CMD, ENTRYPOINT, COPY, ADD 명령문은 해당 디렉터리를 기준으로 실행된다.

작업 디렉터리를 굳이 지정해주는 이유는 컨테이너 내부의 폴더를 깔끔하게 관리하기 위해서이다.

컨테이너도 미니 컴퓨터와 같기 때문에 Dockerfile을 통해 생성되는 파일들을 특정 폴더에 정리해두는 것이 추후에 관리가 쉽다.

만약 WORKDIR을 쓰지 않으면 컨테이너 내부에 존재하는 기존 파일들과 뒤섞여버린다.

 

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

# 예시
WORKDIR /usr/src/app

 

app.txt, src, config.json 파일 만들기

 

 
Dockerfile 만들어서 이미지 생성 및 컨테이너 실행
 
WORKDIR을 안 썼을 때 파일이 어떻게 구성되는 지 먼저 확인해보자.
 
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

 

 

WORKDIR을 썼을 때

Dockerfile

FROM ubuntu

WORKDIR /my-dir

COPY ./ ./

ENTRYPOINT ["/bin/bash", "-c", "sleep 500"] # 디버깅용 코드

 

$ docker build -t my-server .
$ docker run -d my-server
$ docker exec -it [Container ID] bash

$ ls

 

 

컨테이너를 통해 접속하면 my-dir 에 파일들이 저장된것을 확인할 수 있다.

 

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

  • EXPOSE는 컨테이너 내부에서 어떤 포트에 프로그램이 실행되는 지를 문서화하는 역할만 한다. docker -p 8080:8080 … 와 같은 명령어의 -p 옵션과 같은 역할은 일체 하지 않는다. 쉽게 표현하자면 EXPOSE 명령어는 쓰나 안 쓰나 작동하는 방식에는 영향을 미치지 않는다. 

사용법

# 문법
EXPOSE [포트 번호]

# 예시
EXPOSE 3000

 

참고 자료 : Inflearn(인프런) ‘비전공자도 이해할 수 있는 Docker 입문/실전