[Docker] Dockerfile과 Docker Compose

yedi·2025년 2월 9일
post-thumbnail

AWS ECR에 Docker 이미지를 등록하려면 먼저 Dockerfile을 작성해야 한다는 것을 확인했다.

Dockerfile의 개념을 이해하고, 실행 과정과 예제를 통해 주요 명령어를 살펴보자.
또한, 여러 개의 컨테이너를 효율적으로 관리할 수 있는 Docker Compose에 대해서도 알아보자.


Dockerfile


개념

Dockerfile은 Docker 이미지를 생성하기 위한 설정 파일입니다.
이 파일을 통해 애플리케이션 실행에 필요한 환경, 소프트웨어, 라이브러리, 명령어 등을 정의하며, 이를 기반으로 이미지를 빌드하여 애플리케이션을 실행할 수 있습니다.
Dockerfile은 애플리케이션의 실행 환경을 코드로 정의하는 중요한 역할을 합니다.


주요 명령어

명령어 설명 예시
FROM 베이스 이미지를 지정 FROM amazonlinux:2023
COPY 파일을 컨테이너로 복사 COPY popup-paging-web-1.0.0.war .
RUN 이미지 빌드 중 실행할 명령어 지정 RUN yum update -y
CMD 컨테이너 시작 시 실행할 기본 명령어 CMD ["java", "-jar", "/app/api.jar"]
ENTRYPOINT CMD와 유사하지만, 실행 명령어 고정 ENTRYPOINT ["bin/catalina.sh", "run"]
EXPOSE 컨테이너가 사용할 포트 지정 EXPOSE 80

예제

Web 프로젝트와 API 프로젝트 각각의 Dockerfile에 대해 살펴보자.

wget, curl
: 외부 파일을 다운로드하거나 HTTP 요청을 보내는 데 필요한 도구

  1. Web Dockerfile
    Amazon Linux 2023을 기반으로 Java 17과 Tomcat 9을 설치하고, 애플리케이션의 WAR 파일을 Tomcat 서버의 webapps 디렉토리에 배포하여 실행하는 설정을 포함하고 있습니다.
    최종적으로 Tomcat 서버가 실행되어 해당 WAR 파일을 웹 애플리케이션으로 제공합니다.

    # 1. Amazon Linux 2023 기반 이미지 사용
    FROM amazonlinux:2023
    
    # 2. Java 17 및 필수 패키지 설치
    RUN yum update -y && \
        yum install -y --allowerasing java-17-amazon-corretto wget curl unzip git tar && \
        yum clean all
    
    # 3. Tomcat 9.0.65 다운로드 및 설치
    WORKDIR /usr/local
    RUN wget https://archive.apache.org/dist/tomcat/tomcat-9/v9.0.65/bin/apache-tomcat-9.0.65.tar.gz && \
        tar -xvzf apache-tomcat-9.0.65.tar.gz && \
        mv apache-tomcat-9.0.65 tomcat && \
        rm -f apache-tomcat-9.0.65.tar.gz && \
        chmod -R 777 /usr/local/tomcat/
    
    # 4. WAR 파일 복사 (이름 변경 O)
    WORKDIR /usr/local/tomcat/webapps/
    RUN rm -rf ROOT ROOT.war
    COPY popup-paging-web-1.0.0.war ROOT.war
    
    # 5. Tomcat 실행
    WORKDIR /usr/local/tomcat
    ENTRYPOINT ["bin/catalina.sh", "run"]

    복사(COPY) 설정을 참고해보자.

    방법 1) COPY popup-paging-web-1.0.0.war .
    popup-paging-web-1.0.0.war 파일이 그대로 복사되어, http://<dns>/popup-paging-web-1.0.0/common/main으로 접근해야 합니다.

    방법 2) COPY popup-paging-web-1.0.0.war ROOT.war
    ROOT.war 파일로 설정되면 Tomcat이 이를 루트 경로(/)로 인식하여, http://<dns>/common/main으로 접근 가능합니다.

    또한, RUN rm -rf ROOT ROOT.war 명령어는 기존의 ROOT 폴더나 ROOT.war 파일을 삭제하여, 새 ROOT.war 파일이 깨끗하게 배포될 수 있도록 하기 위함입니다.


  2. Api Dockerfile
    Amazon Linux 2023을 기반으로 Java 17을 설치하고, API 애플리케이션 JAR 파일을 컨테이너에 복사하여 실행하는 설정을 포함하고 있습니다.
    popup-paging-api-0.0.1-SNAPSHOT.jar 파일을 /app/api.jar로 복사한 후, Java 명령어를 통해 애플리케이션을 실행합니다.

    # 1. Amazon Linux 2023을 기반으로 하는 이미지 사용
    FROM amazonlinux:2023
    
    # 2. 패키지 업데이트 및 Java 설치
    RUN yum update -y && \
        yum install -y --allowerasing java-17-amazon-corretto wget curl unzip git && \
        yum clean all
    
    # 3. 작업 디렉터리 설정
    WORKDIR /app
    
    # 4. API 애플리케이션 파일 복사
    COPY popup-paging-api-0.0.1-SNAPSHOT.jar /app/api.jar
    
    # 5. API 애플리케이션 실행
    CMD ["java", "-jar", "/app/api.jar"]

실행 과정

Dockerfile을 작성하여 애플리케이션 환경을 정의 → docker build로 이미지를 빌드하고, docker run으로 실행 → 이미지를 AWS ECR에 푸시하여 배포 및 실행 준비 완료

  1. Dockerfile 작성
    Dockerfile을 작성하여 애플리케이션을 실행하기 위한 환경과 명령어를 정의합니다. 이 파일을 통해 애플리케이션이 실행되는 환경을 코드로 설정할 수 있습니다.

  2. Docker 이미지 빌드
    작성한 Dockerfile을 바탕으로 docker build 명령어를 사용하여 Docker 이미지를 생성합니다.

    docker build -t myapp .

    이 명령어는 현재 디렉토리(.)에서 Dockerfile을 읽고, myapp이라는 태그를 붙여 이미지를 빌드합니다.

  3. Docker 컨테이너 실행
    빌드된 이미지를 바탕으로 docker run 명령어를 사용하여 Docker 컨테이너를 실행합니다.

    docker run -p 8080:8080 myapp
    

    이 명령어는 myapp 이미지를 기반으로 컨테이너를 실행하며, 로컬 머신의 포트 8080을 컨테이너의 포트 8080과 연결하여 애플리케이션에 접근할 수 있게 합니다.

  4. AWS ECR에 이미지 등록
    생성된 Docker 이미지를 AWS ECR(Elastic Container Registry)과 같은 레지스트리에 푸시하여, 다양한 환경에서 이미지를 쉽게 배포하고 실행할 수 있습니다. 이미지를 ECR에 등록하기 위한 docker push 명령어를 사용합니다.



위와 같이 여러 개의 Dockerfile을 한 번에 관리하고 효율적으로 운영할 수 있도록 도와주는 도구가 Docker Compose다.

앞서 설명한 Web Dockerfile과 Api Dockerfile을 바탕으로 Docker Compose에 대해 자세히 알아보자.

Docker Compose


개념

여러 Docker 컨테이너를 쉽게 정의하고 실행할 수 있도록 도와주는 도구입니다.
여러 개의 서비스를 포함하는 애플리케이션을 한 번에 관리할 수 있게 해 주며, 각 서비스가 어떤 컨테이너로 실행될지, 네트워크 설정, 볼륨 설정 등을 코드로 정의할 수 있습니다.

① 서비스(Service)

  • 하나의 서비스는 하나의 Docker 컨테이너를 의미합니다.
  • 예를 들어, 애플리케이션의 웹 서버와 데이터베이스가 각각 독립적인 서비스로 실행될 수 있습니다.

② 네트워크(Network)

  • 각 서비스는 기본적으로 Docker Compose에 의해 동일한 네트워크에 연결됩니다. 이를 통해 서비스 간 통신이 가능해집니다.

③ 볼륨(Volume)

볼륨(Volume)
: Docker 컨테이너에서 데이터를 영구적으로 저장하거나 컨테이너 간에 데이터를 공유하기 위한 저장소입니다.
: 컨테이너가 종료되거나 삭제되어도 데이터를 유지할 수 있습니다.

  • 서비스 간에 공유하거나 지속적으로 저장해야 하는 데이터를 관리하기 위해 볼륨을 정의할 수 있습니다.

docker-compose.yml 파일

  • Docker Compose를 사용하여 서비스를 정의하려면 docker-compose.yml 파일을 작성합니다.
  • 이 파일에는 서비스, 이미지, 네트워크, 볼륨 등의 설정을 YAML 형식으로 정의합니다.

사용 흐름

  1. docker-compose.yml 작성
    서비스를 정의하고, 각 서비스에 필요한 설정을 작성합니다.

  2. docker-compose up 실행
    docker-compose.yml 파일을 기반으로 모든 서비스를 빌드하고, 필요한 컨테이너를 생성하여 실행합니다.

  3. docker-compose down 실행
    실행 중인 컨테이너들을 종료하고, 생성된 네트워크 및 볼륨을 삭제합니다.


docker-compose.yml 예제

version: '3'  # Docker Compose 파일의 버전을 정의
services:  # Docker Compose로 실행할 여러 개의 서비스를 정의하는 섹션
  web:
    build:
      context: ./  # 현재 디렉터리에서 Dockerfile을 찾음
      dockerfile: web/Dockerfile  # web 애플리케이션 Dockerfile 경로
    ports:
      - "8080:8080"  # 호스트의 8080 포트를 컨테이너의 8080 포트에 연결
    networks:
      - app-network

  api:
    build:
      context: ./  # 현재 디렉터리에서 Dockerfile을 찾음
      dockerfile: api/Dockerfile  # api 애플리케이션 Dockerfile 경로
    ports:
      - "60818:60818"  # 호스트의 60818 포트를 컨테이너의 60818 포트에 연결
    networks:
      - app-network

networks:
  app-network:  # 두 서비스가 연결될 네트워크를 정의
    driver: bridge  # 기본 브리지 네트워크 드라이버를 사용하여 서비스 간에 네트워크 연결을 가능하게 함

webapi라는 두 개의 컨테이너이자 서비스가 정의되어 있으며, 각각 ./web/Dockerfile./api/Dockerfile을 기준으로 이미지를 빌드하고, 호스트와 컨테이너 간 포트를 맵핑합니다.

서비스 모두 app-network라는 동일한 네트워크에 연결되며, 이 네트워크를 통해 서로 통신할 수 있습니다.

web 서비스는 호스트의 8080 포트를, api 서비스는 60818 포트를 컨테이너의 포트에 연결하여 외부에서 접근할 수 있도록 합니다.

0개의 댓글