Dockerfile 개념과 작성 방법
Dockerfile은 Docker 이미지를 생성하기 위한 텍스트 기반의 스크립트 파일입니다. 개발자들이 명령어를 토대로 작성한 Dockerfile을 기반으로 애플리케이션의 실행 환경을 포함한 이미지를 생성할 수 있습니다. 이번 글에서는 Dockerfile의 개념, 작성 방법, 유의사항들에 대하여 알아보도록 하겠습니다.
Dockerfile
Dockerfile은 Docker 이미지를 정의하는 데 사용되는 구성 파일입니다. 파일에 작성된 명령어를 순차적으로 실행하여 컨테이너 이미지를 빌드합니다. Dockerfile은 애플리케이션의 배포와 관리를 용이하게 만들어 DevOps 환경에서 필수적인 도구로 자리 잡았습니다.
주요 특징
- 컨테이너 실행 환경을 코드로 관리
- 일관된 개발 및 배포 환경 제공
- 재사용 및 확장 가능
Dockerfile은 이미지 빌드를 위해 명령어들이 단계별로 작성됩니다. 애플리케이션 실행을 위한 환경, 패키지 정보 등이 포함되어 작성되며, 이를 사용하면 일관된 환경을 유지할 수 있습니다. 따라서 개발 및 배포 과정에서 발생하는 환경 설정 이슈를 효과적으로 해결할 수 있습니다. (특히, "제 PC에서는 돌아가는데요?"와 같은 문제를 방지할 수 있습니다. 😃)
생성된 도커 이미지는 컨테이너 실행 시 사용되며, 컨테이너가 실행되는 완전한 환경을 캡슐화한 형태를 가집니다.
Dockerfile 내용을 이해하면 컨테이너 환경을 파악하고 활용하는 데 큰 도움이 됩니다.
Dockerfile 구조
Dockerfile 기본 구조
주요 명령어
- FROM
- 모든 Dockerfile은 FROM 명령어로 시작되며 운영 체제 이미지를 설정
- <이미지이름>:<태그> 구조로 작성되며 태그를 입력하지 않은 경우 자동으로 latest 버전으로 실행
- 예: FROM ubuntu:20.04
- RUN
-
이미지를 빌드하는 동안 컨테이너 내에서 입력된 명령어를 실행하여 이미지를 구성, 주로 소프트웨어를 설치하거나, 파일을 생성하거나, 설정을 변경하는 데 사용
- RUN 명령어와 동시에 apt-get update와 install을 함께 실행하는 것을 추천
- 예: RUN apt-get update && apt-get install -y nginx
-
- CMD
- 컨테이너가 실행 시 기본으로 실행될 명령어
- Dockerfile내에는 하나의 CMD만 존재할 수 있고, 여러개의 CMD가 존재하는 경우 마지막 라인의 CMD가 적용됨
- 예: CMD ["nginx", "-g", "daemon off;"]
- COPY
- 로컬 파일을 컨테이너 이미지로 복사
- 예: COPY index.html /usr/share/nginx/html/
- WORKDIR
- 작업 디렉토리를 설정
- 예: WORKDIR /app
- EXPOSE
- 컨테이너에서 사용할 포트 지정
- 예: EXPOSE 80
- ENTRYPOINT
- 컨테이너가 실행될 때 고정적으로 실행할 명령어를 설정
- 예: ENTRYPOINT ["/bin/bash"]
실무에서 자주 사용되는 명령어
- ADD
- COPY와 유사하지만, URL에서 파일을 다운로드하거나 tar 파일을 자동으로 압축 해제 가능
- 예: ADD https://example.com/app.tar.gz /app
- LABEL
- 이미지를 설명하는 메타데이터 추가
- 예: LABEL maintainer="your_email@example.com"
- ENV
- 환경 변수를 설정
- 예: ENV SPRING_PROFILES_ACTIVE=prod
- ARG
- 빌드 시 사용하는 변수
- 예: ARG JDK_VERSION=17
- VOLUME
- 컨테이너에서 데이터를 유지하기 위한 볼륨 설정
- 예: VOLUME /data
- USER
- 실행 사용자 및 그룹 설정
- 예: USER appuser
- HEALTHCHECK
- 컨테이너의 상태를 주기적으로 확인
- 예: HEALTHCHECK --interval=30s CMD curl -f http://localhost:8080/health || exit 1
- ONBUILD
- 상속받는 Dockerfile에 명령어를 추가할 때 사용
- 예: ONBUILD COPY . /app
- SHELL
- 명령어 실행 시 사용할 기본 셸을 변경
- 예: SHELL ["/bin/bash", "-c"]
Dockerfile 예시
Spring Boot 애플리케이션을 위한 Dockerfile
# Base image 설정
FROM openjdk:17-jdk-slim
# 유지보수를 위한 메타데이터 추가
LABEL maintainer="your_email@example.com"
# 빌드 시 사용할 변수 설정
ARG JAR_FILE=target/my-spring-boot-app.jar
# 환경 변수 설정 (dev 환경)
ENV SPRING_PROFILES_ACTIVE=dev
# 작업 디렉토리 설정
WORKDIR /app
# 애플리케이션 JAR 파일 복사
COPY ${JAR_FILE} app.jar
# 애플리케이션이 의존하는 추가 파일 복사 (예: 설정 파일)
ADD config/dev/application-dev.yml /app/config/application.yml
# 애플리케이션 실행에 사용할 포트 노출
EXPOSE 8080
# 컨테이너 상태를 확인하기 위한 Healthcheck 설정
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1
# 실행 명령어 설정
ENTRYPOINT ["java", "-jar", "app.jar"]
빌드 및 실행 방법
- Dockerfile이 위치한 디렉토리에서 이미지를 빌드합니다.
- docker build -t my-spring-boot-app .
- 생성된 이미지를 기반으로 컨테이너를 실행합니다.
- docker run -p 8080:8080 my-spring-boot-app
Dockerfile 작성 시 주의사항
- 이미지 크기 최적화
- 불필요한 파일을 COPY하지 않도록 .dockerignore 파일 사용
- 멀티스테이지 빌드를 활용하여 최종 이미지 크기를 줄입니다.
- 캐싱 활용
- 명령어 순서를 신중히 작성하여 캐싱 효과를 극대화합니다.
- 보안 고려
- 민감한 정보를 Dockerfile에 포함하지 않고, 공식 이미지를 사용
- 레이어 수 줄이기
- 여러 명령어를 RUN에 결합하여 불필요한 레이어 생성 방지
- 컨테이너 실행 사용자 설정
- 보안 강화를 위해 USER 명령어를 사용, 루트 사용자로 실행되는 것을 방지하