[Docker] Spring Boot App을 Dockerlizing하기 : 2. Docker-compose를 이용하여 멀티 컨테이너 구성하기(+MariaDB 연결)
이전 포스팅에서 Spring Boot 프로젝트를 Dockerfile을 작성하여 빌드하고, 컨테이너상에서 실행시키는 것. 그리고 Dockerhub에 배포해 보는 것까지를 해 보았다.
https://sjh9708.tistory.com/81
이제 여러개의 컨테이너들을 한 번에 실행시키고 상호연결시킬 수 있도록 하는 docker-compose에 대해서 알아보도록 하자.
Dockerfile
FROM openjdk:11
WORKDIR /app/wisefee/
ARG JAR_PATH=../build/libs/
COPY ${JAR_PATH}/*.jar /app/wisefee/wisefee.jar
ENV PROFILE dev
ENTRYPOINT ["java", "-jar", "wisefee.jar"]
앞에서 작성했던 Dockerfile의 내용이다.
1. 빌드된 Spring boot 웹 Application을 실행시키기 위해서 필요한 JDK를 기반 이미지로 사용하였다. 해당 이미지에는 Java 11과, 필요한 라이브러리들이 설치되어 있다.
2. 컨테이너 내부에서 명령어 등을 실행할 WORKDIR 경로를 지정해준다. 이후의 명령은 해당 디렉토리에서 실행될 것이다.
3. ARG는 Dockerfile에서의 변수를 지정하는 것이다.
4. 빌드된 JAR 파일을 선택하여 Docker 이미지 안으로 복사한다. Web 어플리케이션을 실행시키기 위해서는 소스파일이 있어야 하기 때문에, 언급했던 빌드 산출물은 .jar 파일을 복사해야 한다.
- ${JAR_PATH}/*.jar : 이미지 안으로 복사할 JAR 파일을 선택하기 위한 경로이다.
- /app/wisefee/wisefee.jar : 이미지 내에서 JAR 파일이 위치할 경로와 파일 이름을 지정한다.
5. Docker 컨테이너에서 사용할 환경 변수를 정의한다. 애플리케이션이 개발 환경에서 실행되도록 설정하는데 사용하려고 작성한 부분이다.
6. 컨테이너가 실행될 때, JAR 파일을 실행하는 커멘드를 정의한다. ENTRYPOINT는 컨테이너가 시작될 때, 자동으로 실행되는 프로세스를 지정한다.
Docker-compose
Docker Compose 파일(docker-compose.yml)은 애플리케이션을 구성하는 각 컨테이너의 설정과 관계를 정의한다. 컨테이너의 이미지, 환경 변수, 포트 매핑, 볼륨 마운트 등의 설정을 포함한다.
1. 컨테이너의 동시 실행: Docker Compose를 사용하여 여러 개의 컨테이너를 한 번에 실행하고 관리할 수 있다. 컨테이너들은 Docker Compose 파일에서 정의된 설정에 따라 동시에 시작된다.
2. 애플리케이션의 서비스 라우팅: Docker Compose는 여러 컨테이너가 상호 작용할 수 있도록 서비스 간의 네트워크 연결을 자동으로 구성한다. 이를 통해 컨테이너 간 통신이 쉽게 이루어질 수 있다.
3. 편리한 환경 관리: Docker Compose를 사용하면 개발, 테스트, 스테이징 및 운영 환경 간의 설정을 쉽게 전환할 수 있다. 다양한 환경에서 동일한 Docker Compose 파일을 사용하여 애플리케이션을 실행할 수 있다.
Docker-compose 작성하기
1. 버전, 네트워크, 서비스 정의하기
version: "3.7"
networks:
wisefee-network:
driver: bridge
services:
wisefee-database:
container_name: wisefee-database
networks:
- wisefee-network
wisefee-app:
container_name: wisefee-app
networks:
- wisefee-network
- version : Docker-compose의 파일의 버전을 정의한다.
- networks : 컨테이너들이 사용할 네트워크를 정의한다. 서로 다른 컨테이너 간의 Docker 내부에서의 통신이 가능하게 하려면, 같은 네트워크 상에 속해 있어야 한다.
- services : 실행시킬 여러 개의 서비스를 정의한다. 각 서비스는 Docker 컨테이너를 생성하고 실행한다.
해당 compose 파일에서는 Spring boot Application과 데이터베이스를 사용할 것이므로 두 개의 서비스를 만들어주었다.
container_name을 통해 컨테이너 이름을 정해줄 수 있으며, networks를 통해 컨테이너 간 네트워크 사용을 연결시켜준다.
2. 데이터베이스 서비스 설정하기
version: "3.7"
networks:
wisefee-network:
driver: bridge
services:
wisefee-database:
platform: linux/x86_64 #Mac M1칩 사용 제외하고는 주석처리
image: mariadb:10.11.2
container_name: wisefee-database
environment:
MYSQL_DATABASE: "wisefee-database"
MYSQL_ROOT_PASSWORD: "1111"
ports:
- 3308:3306
volumes:
- ./volumes/mariadb:/var/lib/mysql
networks: #사용할 네트워크 지정
- wisefee-network
wisefee-app:
container_name: wisefee-app
networks:
- wisefee-network
데이터베이스에 해당하는 서비스인 wisefee-database 쪽 내용을 작성 해주었다.
- platform : Mac M1 Process를 사용하여 docker-compose를 빌드하는 경우 작성한다. 아니라면 작성하지 않아도 된다.
- image : 베이스 이미지로 사용하려는 데이터베이스인 mariadb를 사용한다.
- environment : 서비스 환경 변수를 설정한다. 여기서는 데이터베이스의 연결 정보를 설정하였다.
- ports : [호스트 포트 : 컨테이너 내부 포트]를 매핑시킨다. 즉, 컨테이너 안에서의 3306포트를 컨테이너 밖 호스트 컴퓨터에서는 3308 포트로 사용할 수 있도록 매핑시키는 것이다.
- volumes : 마운팅하여 데이터베이스 파일을 호스트에 영속적으로 저장할 수 있도록 설정하였다.
기본적으로 컨테이너에서 돌고 있는 서비스들은 컨테이너가 삭제될 시, 지금까지의 모든 작업 내용들이 사라지게 된다.
하지만 데이터베이스의 내용은 컨테이너를 삭제하고, 다시 빌드하여 사용할 때에도 유지가 되어야 한다. 그러므로 컨테이너 안에서의 데이터베이스의 작업 내용이 유지될 수 있도록 마운팅을 하는 것이다.
컨테이너 안의 /var/lib/mysql 디렉터리 안에는 MariaDB 내부의 데이터들이 저장되어 있다. 해당 내용들을 호스트 컴퓨터(컨테이너 외부)의 ./volumes/mariadb 디렉터리에 저장하도록 마운팅하여 재실행되더라도 작업 내용을 유지할 수 있도록 한다.
3. 웹 어플리케이션 서비스 설정하기
version: "3.7"
networks:
wisefee-network:
driver: bridge
services:
wisefee-database:
platform: linux/x86_64 #Mac M1칩 사용 제외하고는 주석처리
image: mariadb:10.11.2
container_name: wisefee-database
environment:
MYSQL_DATABASE: "wisefee-database"
MYSQL_ROOT_PASSWORD: "1111"
ports:
- 3308:3306
volumes:
- ./volumes/mariadb:/var/lib/mysql
networks: #사용할 네트워크 지정
- wisefee-network
wisefee-app:
build: #image를 DockerFile 기반으로 사용한다
context: ../.. #DockerFile이 있는 디렉토리
dockerfile: ./Dockerfile #기존에 설정해둔 DockerFile을 지정히여 build 된 jar 파일을 container에 올린다.
restart: always #컨테이너 재실행
depends_on: #database service가 실행된 이후에 실행
- wisefee-database
ports:
- 8081:8080
container_name: wisefee-app
environment:
SPRING_DATASOURCE_URL: jdbc:mariadb://wisefee-database:3306/wisefee-database?characterEncoding=UTF-8&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 1111
networks:
- wisefee-network
이어서 Spring boot app에 해당하는 서비스인 wisefee-app 쪽 내용을 추가작성 해주었다.
- build : Image를 Dockerfile을 이용하여 직접 빌드하여 사용하도록 작성하였다.
위의 데이터베이스 서비스의 경우에는 mariadb 베이스 이미지를 사용했는데, 이번에는 직접 작성한 Dockerfile을 통해 이미지를 빌드해서 사용하려고 한다.
context에 Dockerfile의 경로를, dockerfile에 Dockerfile의 이름을 작성해준다. - restarts : 컨테이너 내부에서 오류가 발생하더라도, 자동으로 처음부터 재시작하도록 해 준다.
- depends_on : 스프링 프로젝트는 데이터베이스가 실행되기 이전에 실행되게 되면 Connection에 실패할 것이다. 따라서 데이터베이스가 먼저 켜진 이후, 해당 서비스가 실행되도록 설정해준다.
- ports : [호스트 포트 : 컨테이너 내부 포트]를 매핑시킨다. 컨테이너 안에서의 8080포트를 컨테이너 밖 호스트 컴퓨터의 8081 포트로 매핑하였다.
- environment : App 내 환경 변수를 설정한다. 여기서는 데이터베이스의 연결 정보를 설정하였다.
눈여겨 보아야 할 점은 DATASOURCE_URL에서의 host가 wisefee-database로 설정되어 있다는 점이다.
컨테이너 내부에서, 다른 컨테이너 서비스인 wisefee-database 데이터베이스에 접근하려면
호스트(컨테이너 외부)에서 접근할 때 사용되는 localhost:3308이 아니라, "컨테이너이름 : 컨테이너상포트"인 wisefee-database:3306으로 접근해야 한다.
또한 이것은 같은 네트워크 상에 있는 서비스일 경우에만 가능하므로 위에서 설명한 네트워크 설정을 해주어야 한다.
Docker-compose 빌드 및 실행하기
작성한 docker-compose.yaml가 있는 디렉터리로 이동하여 다음 CLI 명령어를 사용하여 빌드하고, 컨테이너에서 실행시킨다.
1. Docker-compose build
docker-compose build
빌드하게 되면, docker-compose 안에서 사용된 Dockerfile들의 빌드가 일괄적으로 자동으로 진행되며, 각각의 이미지들을 생성하게 된다.
2. Docker-compose up
docker-compose up -d
docker-compose.yaml에서 빌드된 이미지들과, 베이스 이미지들을 모두 컨테이너에 올려 실행시킨다.
컨테이너들은 docker-compose.yaml에서 설정된 포트, 환경변수, 볼륨 등을 적용받아서 작동하게 된다.
3. Docker-compose stop
docker-compose stop
해당 CLI 명령어는 docker-compose를 통해 실행중인 컨테이너들을 일시중지하는 명령어이다.
4. Docker-compose rm
docker-compose rm -f
해당 CLI 명령어는 docker-compose의 일시중지된 컨테이너들을 삭제하는 명령어이다.
앞에서 언급했듯이, volumes 설정을 통해 마운팅된 정보들을 제외하고는 컨테이너 내부의 모든 사항들이 삭제된다.
Dockerhub의 이미지로 Docker-compose 빌드 및 실행하기
version: "3.7"
networks:
wisefee-network-dev-deploy:
driver: bridge
services:
wisefee-database:
platform: linux/x86_64 #Mac M1칩 사용 제외하고는 주석처리
image: mariadb:10.11.2
container_name: wisefee-database-dev-deploy
environment:
MYSQL_DATABASE: "wisefee-database"
MYSQL_ROOT_PASSWORD: "1111"
ports:
- 3309:3306
volumes:
- ./volumes/mariadb:/var/lib/mysql
networks: #사용할 네트워크 지정
- wisefee-network-dev-deploy
wisefee-app:
image: sjh9708/devserver-wisefee-app:latest
restart: always #컨테이너 재실행
depends_on: #database service가 실행된 이후에 실행
- wisefee-database
ports:
- 8082:8080
container_name: wisefee-app-dev-deploy
environment:
SPRING_DATASOURCE_URL: jdbc:mariadb://wisefee-database:3306/wisefee-database?characterEncoding=UTF-8&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: 1111
networks:
- wisefee-network-dev-deploy
이번에는 SpringBoot 웹 Application을 이전 포스팅에서 Dockerfile을 기반으로 DockerHub에 올려두었던 이미지를 사용하여 구성하였다.
wisefee-app에서 build 대신 image를 사용하여 아래의 Dockerhub의 이미지를 사용하도록 설정해주었다.
마찬가지로 docker-compose build 및 docker-compose up -d를 통해 컨테이너를 실행시켜 주면 된다.
빌드할 Dockerfile이 없으므로 docker-compose build에서는 아무 동작을 하지 않는 것을 확인할 수 있다.
8082 포트로 접근해보면, 컨테이너 내부에서 웹이 성공적으로 잘 돌고 있는 것을 확인할 수 있었다.
'Backend > Docker & Kubernetes' 카테고리의 다른 글
[Docker] Docker Image를 DockerHub로 배포 시 아키텍처 호환 문제 해결하기(Mac M1) (0) | 2023.09.12 |
---|---|
[Kubernetes] 쿠버네티스의 개념과 구성 요소 (0) | 2023.09.11 |
[Docker] Spring Boot App을 Dockerlizing하기 : 1. 이미지와 컨테이너, 그리고 Dockerfile 작성하기 (0) | 2023.08.03 |
[Docker] 도커의 개념과 장점 (0) | 2023.01.25 |