본문 바로가기
Study/DevOps

[Docker-Compose] 여러 Docker 컨테이너를 한꺼번에 관리하기

by DevJaewoo 2022. 10. 4.
반응형

Docker Compose LOGO

Intro

이전에 Docker 이미지 다운로드 및 컨테이너 실행 방법에 대해 알아봤었다.

하지만 하나의 PC에서 여러 컨테이너를 실행해야 하는 경우 일일이 다 관리하기도 힘들고, 네트워크 설정도 복잡하다.

이럴 때 docker-compose를 사용하면 yml 파일을 만드는것 만으로 간단하게 컨테이너들을 관리할 수 있다.

이번 시간엔 간단한 예제를 통해 docker-compose 사용 방법을 알아보자.

 

[Docker] 도커 간단한 명령어 모음

도커 간단 사용법 이전 글에서 Docker를 설치하는 방법에 대해 알아봤다. 이번엔 Docker의 이미지, 컨테이너 관리 방법에 대해 알아보자. [Docker] 도커 설치하기 도커 설치 및 간단한 사용법 이번

devjaewoo.tistory.com


프로젝트 구조

소스 코드는 Github에 업로드 되어있다.

 

프로젝트 구조는 아래와 같이 설정했다.

docker-compose-test
├── backend
│   └── dockerfile
├── frontend
│   └── dockerfile
├── postgres
└── docker-compose.yml

 

  • backend: Spring Backend 서버
  • frontend: React Frontend 서버
  • postgres: PostgreSQL database 폴더 (없어도 무방하다.)

위와 같이 컨테이너 3개를 생성할 것이며, backend와 PostgreSQL 컨테이너는 서로 통신이 가능하게 설정해볼 것이다.


Frontend 컨테이너 만들기

아래의 명령어로 Frontend 서버를 간단하게 만들 수 있다.

명령어를 실행하기 위해 NodeJS가 설치되어 있어야 한다.

npx create-react-app frontend

 

frontend 폴더가 생성됐다면 React 서버를 실행시켜보자.

cd frontend
npm start

 

http://localhost:3000으로 접속했을 때 아래와 같은 화면이 뜨면 된다.

React 실행화면

 

실행이 잘 된다면 dockerfile을 생성하자.

FROM node:latest	# Node 컨테이너 환경에서 실행한다.
RUN mkdir -p /usr/app/frontend	# /usr/app/frontend 디렉터리를 생성한다.
WORKDIR /usr/app/frontend	# 생성한 디렉터리를 Default 디렉터리로 설정한다.

COPY package.json .	# WORKDIR에 package.json 파일을 복사한다.
RUN npm install	# package.json의 패키지들을 설치한다.
COPY . .	# 나머지 파일들을 WORKDIR에 복사해온다.

ENTRYPOINT [ "npm", "start" ]	# 서버를 실행한다.
EXPOSE 3000	# 3000번 포트를 호스트와 공유한다.

 

Dockerfile이 잘 설정됐는지 확인하려면 아래의 명령어로 이미지를 만들어보면 된다.

docker build -t frontend .			# Build
docker run --rm -itd -p 3000:3000 frontend	# Run

Backend 컨테이너 만들기

Spring Boot Project를 생성하고, 아래와 같이 dependencies를 설정하자.

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'org.postgresql:postgresql'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

 

프로젝트를 빌드하자. PostgreSQL이 없는 지금 상태로는 test가 fail나기 때문에 Build Task에서 제외시켜줘야 한다.

 

./gradlew build -x test

 

빌드가 완료됐다면 Dockerfile을 설정하자.

FROM openjdk:17-alpine
RUN mkdir -p /usr/app/backend
WORKDIR /usr/app/backend

# Build가 완료된 파일을 복사한다.
COPY ./build/libs/*.jar .

# Default DB Host를 localhost로 설정한다. 컨테이너 실행 시 변경할 수 있다.
ENV DATABASE_HOST=localhost

ENTRYPOINT [ "java", "-jar", "backend-0.0.1-SNAPSHOT.jar", "--DATABASE_HOST=${DATABASE_HOST}" ]
EXPOSE 8080

docker-compose 설정

이제 docker-compose로 만들어진 컨테이너들을 하나로 묶어서 실행해보자.

PostgreSQL은 이미 만들어진 이미지를 그대로 사용할 것이기 때문에 별도의 dockerfile은 필요없다.

 

프로젝트 폴더에 docker-compose.yml 파일을 생성한다.

version: "3"	# docker-compose 버전
services:	# 서비스 목록
  frontend:	# 서비스 이름
    build:	# 이미지 Build 옵션
      context: ./frontend	# Build될 프로젝트가 위치한 경로
      dockerfile: dockerfile	# 프로젝트 폴더의 dockerfile 이름

    container_name: frontend	# 컨테이너 이름

    ports:	# host와 공유할 포트 목록
      - 3000:3000	# host:container

    depends_on:	# 아래의 서비스들이 모두 시작된 이후에 이 서비스를 시작
      - backend	# backend 서비스가 시작될 때 까지 기다림

  backend:
    build:
      context: ./backend
      dockerfile: dockerfile

    container_name: backend
    ports:
      - 80:8080
    environment:	# 환경변수 설정
      - SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/postgres
      - SPRING_DATASOURCE_USERNAME=postgres
      - SPRING_DATASOURCE_PASSWORD=postgres

    depends_on:
      - database	# database 서비스가 시작될 때 까지 기다림

  database:
    image: postgres:latest	# postgres 이미지 사용
    environment:	# 환경변수 설정
      - POSTGRES_USERNAME=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:	# host와 container가 공유할 디렉터리 지정
      - ./postgres:/var/lib/postgresql/data:rw	# host의 postgres 폴더를 컨테이너의 /var/lib/postgresql/data와 공유하고, 읽기/쓰기가 가능하도록 설정

 

이제 아래의 명령어를 실행하면 docker-compose.yml 파일의 내용을 읽어들여 설정한 대로 컨테이너들을 실행시켜준다.

docker-compose up

 

실행하면 자동으로 이미지가 빌드되고 컨테이너가 실행된다.

Docker Compose 로그

 

아래와 같이 DB 때문에 실행되지 않았던 backend도 정상적으로 실행되는 것을 볼 수 있다.

backend                         | 2022-10-04 02:54:44.502  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
backend                         | 2022-10-04 02:54:44.543  INFO 1 --- [           main] com.example.backend.BackendApplication   : Started BackendApplication in 10.311 seconds (JVM running for 12.19)
frontend                        | Compiled successfully!
frontend                        | 
frontend                        | You can now view frontend in the browser.
frontend                        | 
frontend                        |   Local:            http://localhost:3000
frontend                        |   On Your Network:  http://172.18.0.4:3000
frontend                        | 
frontend                        | Note that the development build is not optimized.
frontend                        | To create a production build, use npm run build.
frontend                        | 
frontend                        | webpack compiled successfully
frontend                        | Compiling...
frontend                        | Compiled successfully!
frontend                        | webpack compiled successfully
backend                         | 2022-10-04 04:06:25.344  INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
backend                         | 2022-10-04 04:06:25.355  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
backend                         | 2022-10-04 04:06:25.359  INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms

컨테이너 동작 확인

Docker Desktop에서 컨테이너가 잘 뜨는지 확인해보자.

Docker Compose 컨테이너 확인

 

localhost에 접속하여 Backend 서버가 잘 실행됐는지 확인해보자.

Backend 컨테이너 동작 확인

 

http://localhost:3000에 접속하여 Frontend 서버가 잘 실행됐는지 확인해보자.

React 컨테이너 동작 확인

반응형