Journey to Security/클라우드

[Docker] Dockerfile을 이용해서 이미지 빌드하고 실행하기 (1) - Nginx

Cordilog 2026. 1. 7. 14:29

도커파일(Dockerfile)은 단순히 이미 만들어진 도커 이미지를 가져다 쓰는 것을 넘어서, 목적에 맞는 어플리케이션 환경을 직접 구성하고 배포하는 것을 가능하게 해준다.

Dockerfile이 무엇인지, 어떤 문법으로 작성되는지 살펴보고, 실제 Nginx와 Apache 웹 서버를 커스텀 이미지로 빌드해보자.

1. Dockerfile이란?

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

이미지가 어떤 베이스 위에서 만들어지고, 어떤 소프트웨어가 설치되며, 실행 시 어떤 명령을 수행할지 정의하는 청사진과 같다.

이러한 작업을 Dockerizing(도커라이징)이라고 부르며, 이는 인프라 구성을 코드로 관리하는 IaC(Infrastructure as Code)의 시발점이자 CI/CD(지속적 통합/배포) 파이프라인의 핵심 과정이다.

이미지 생성 메커니즘

Dockerfile은 독자적인 DSL(Domain Specific Language) 언어를 사용한다. 작성 흐름은 다음과 같다.

  1. Base Image: 운영체제나 런타임 등 기초가 되는 이미지를 불러온다.
  2. Layers: 필요한 패키지를 설치하거나 설정을 변경하며 레이어(Layer)를 쌓는다.
  3. Build: 작성된 내용을 하나의 파일로 만들고 빌드하여 이미지를 생성한다.

 

2. Dockerfile 핵심 문법(Syntax)

Dockerfile은 지시어(Instruction)와 인자(Argument)로 구성된다. 대소문자를 구분하지 않지만, 가독성을 위해 지시어는 대문자로 표기하는 것이 관례다.

주요 지시어

지시어 설명 및 예시
FROM 베이스 이미지 지정. 모든 Dockerfile의 시작점이다.

FROM ubuntu:latest
RUN 이미지 빌드 시 실행할 명령어. 패키지 설치 등에 사용된다.

RUN apt update
CMD 컨테이너 실행 시 기본 명령어. Dockerfile 내에서 하나만 유효하다.

CMD ["node", "app.js"]
COPY 파일 복사. 호스트의 파일이나 폴더를 이미지 내부로 복사한다.

COPY index.html /var/www/html/
WORKDIR 작업 디렉터리 이동. 리눅스의 cd 명령어와 유사하다.

WORKDIR /app

 

  • RUN 사용시 Layer 최적화 (&&) :RUN 지시어가 실행될 때마다 이미지에는 새로운 레이어가 생성된다. 레이어가 많을수록 이미지 크기가 커지고 비효율적이다. 따라서 연관된 명령어는 && (AND 연산자)와 \ (줄바꿈)를 사용하여 하나로 묶는 것이 좋다.
# 비효율적인 방식 (레이어 2개 생성)
RUN apt update
RUN apt install nginx

# 효율적인 방식 (레이어 1개 생성)
RUN apt update && \
    apt install nginx

 

  • COPY vs ADD 둘 다 파일을 복사하지만 ADD가 더 강력한 기능을 가진다.
    • COPY: 로컬 파일 복사만 가능. (일반적인 경우 권장)
    • ADD: 로컬 파일 복사 + URL 다운로드 + 압축 파일 자동 해제 기능 포함.
  • CMD vs ENTRYPOINT
    • CMD: 컨테이너 시작 시 실행될 기본 명령어. docker run 실행 시 인자를 넘기면 CMD 내용은 무시(덮어쓰기)된다.
    • ENTRYPOINT: 컨테이너 시작 시 무조건 실행되는 명령어. 인자를 넘기면 ENTRYPOINT의 파라미터로 붙는다.
  • ENV vs ARG
    • ENV: 환경 변수 설정. 이미지 빌드 시점뿐만 아니라 컨테이너 실행 시점에도 유효하다.
    • ARG: 빌드 시점에만 유효한 변수. 이미지를 빌드할 때 --build-arg 옵션으로 값을 넘길 수 있다.

 

3. Dockerfile로 빌드한 이미지로 웹 서버 띄우기

 

Step 1. 리소스 정리 (Clean-up)

실습 시 충돌을 방지하기 위해 기존 컨테이너와 이미지를 정리하고 시작하는 것이 좋다.

# 모든 컨테이너 중지 및 삭제
root@host:/home/username# docker rm -f $(docker ps -aq)

# 모든 이미지 삭제
root@host:/home/username# docker rmi -f $(docker images)

# 확인
root@host:/home/username# docker images

 

 

Step 2. 작업 디렉토리 생성 (Build context 분리)

도커 이미지를 만들 때는 가장 먼저 별도의 디렉터리(폴더)를 생성하고 그 안으로 이동해야 한다.

root@host:/home/username# mkdir dockerfile
root@host:/home/username# cd dockerfile

 

별도의 작업 디렉토리를 만드는 이유:

이미지를 빌드할 때 사용할 docker build ./ 명령은 현재 디렉터리에 있는 모든 파일을 도커 데몬으로 전송한다.

이를 빌드 컨텍스트(Build Context)라고 한다.

만약 홈 디렉터리(/home/username)나 루트(/)에서 바로 작업을 하면, 내 컴퓨터에 있는 불필요한 파일들까지 모두 도커 엔진이 읽어들이게 되어 빌드 속도가 느려지고 보안상 위험할 수 있다.

따라서 도커 빌드 작업은 항상 격리된 폴더에서 수행하는 습관을 들이는 것이 좋다.

 

Step 3. Dockerfile  작성 (Nginx 기반)

이미지 빌드 전, docker run의 볼륨 마운트 옵션을 복습해보자.

docker run --name webserver1 -v $(pwd):/usr/share/nginx/html -p 8080:80 -d nginx:latest

 

아래와 같이 도커파일을 작성하면 이제 매번 docker run 명령으로 옵션을 길게 쓰는 대신, 위 설정을 그대로 담은 이미지를 빌드할 수 있다.

1) Dockerfile 작성

리눅스 환경에서는 vi(vim)이나 nano 에디터를 열어서 다음과 같이 도커파일을 작성할 수 있다.

# 베이스 이미지로 Nginx 최신 버전 사용
FROM    nginx:latest AS website
# 현재 디렉터리의 모든 파일을 컨테이너 웹 루트로 추가
ADD     . /usr/share/nginx/html/
# 빌드 변수 선언 (문서화 목적)
ARG     port:8001
# 80번 포트 개방 알림
EXPOSE  80

2) 이미지 빌드 

이제 작성한 파일을 기반으로 이미지를 빌드한다.

이때 이름(Repository)버전(Tag)을 명확히 구분하여 지정한다.

예)

 

  • 이미지 이름: my-nginx
  • 버전: 1.0

 

명령어:
 
root@host:/home/username/dockerfile# docker build -t my-nginx:1.0 ./
  • docker build: Dockerfile을 읽어 이미지를 생성한다. ./는 빌드 컨텍스트(Build Context) 위치를 의미한다.

3) 컨테이너 실행

빌드된 이미지를 사용하여 컨테이너를 실행한다. 컨테이너 이름도 식별하기 좋게 지정한다.

명령어:

root@host:/home/username/dockerfile# docker run --name website-1 -p 8001:80 -d my-nginx:1.0

 

4) 브라우저 접속 확인

웹 브라우저에서 http://localhost:8001로 접속하면 현재 디렉토리의 파일 리스트나 index.html이 보이는 것을 확인할 수 있다.