지금부터 구축하고자 하는 환경은 Spring boot와 mysql에 대해 진행할 예정이고, Docker compose를 사용하지 않았을 때 와 Docker compose를 사용했을 때를 비교해 보겠습니다.
구성 환경

먼저 db에서 테스트와 실행 관경이 분리되어 있고, 패키지를 할 때 테스트까지 동작시켰기 때문에 test DB
와 일반 DB
를 나눴습니다.
따라서 각각을 실행 시켜줘야 하고, 이러한 테스트 db에 spring boot가 접근이 가능해야 하는 상황입니다.
참고로

현재 폴더 구조입니다.
Dockerfile과 Docker cil를 통한 예를 진행할 때는 mvn은 be폴더, mysql관련은 gonggam폴더에서 진행을 했습니다.
Docker-compose를 사용했을 때에는 gonggam폴더 내부에서 진행했다는 점 같이 생각하시면서 보시면 될 거 같습니다.
1. Dockerfile과 Docker cli
[ 일반 DB ]
docker run -d --name gonggam ^
-e MYSQL_ROOT_PASSWORD=qwe123 ^
-e MYSQL_DATABASE=gonggam^
-e TZ=Asia/Seoul ^
-e LANG=en_US.utf8 ^
-v .\docker\db-init:/docker-entrypoint-initdb.d ^
-v .\docker\database\datadir\:/var/lib/mysql ^
-p 3306:3306 ^
--platform linux/x86_64 ^
mysql:latest ^
--character-set-server=utf8mb4 ^
--collation-server=utf8mb4_unicode_ci
--name
: Image를 실행시키면 컨테이너가 동작하는데, 이 컨테이너의 이름입니다.-e
: 추가적인 옵션을 넣는 파라미터MYSQL_ROOT_PASSWORD
: 접속하고자 하는 mysql의 root계정 비번입니다.MYSQL_DATABASE
: 사용하고자 하는 테이블이다.TZ
: 컨테이너에서 사용할 사용할 시간을 정합니다.LANG
: 컨테이너 안에서 사용할 기본 언어 설정입니다.
-v
: volumne을 나타내며,--mount
로도 가능- 처음은 스키마 설정을 해줬습니다. Bind mount를 통해 Host가 아닌 로컬 위치를 잡아서 사용하게 했습니다.
- DB를 사용하면서 생길 수 있는 데이터들이 삭제되지 않도록 mount해줬습니다.
-p
: 3306포트로 들어오는 것을 publish로 열어뒀습니다.--platform
: 사용할 host 시스템과 동일하게 적용하면 됩니다.mysql:latest
: 가장 최신의 mysql 이미지를 가져오기 위해 사용--character-set-server, --collation
: Mysql 문자열 인코딩을 utf8mb4로 설정
이렇게 docker로 실행하게 되면,

이렇게 컨테이너가 실행되게 됩니다.
이와 똑같이
docker run -d --name gonggam-test-db ^
-e MYSQL_ROOT_PASSWORD=test ^
-e MYSQL_DATABASE=gonggam-test ^
-e TZ=Asia/Seoul ^
-e LANG=en_US.utf8 ^
-v .\docker\db-init:/docker-entrypoint-initdb.d ^
-p 3307:3306 ^
--platform linux/x86_64 ^
mysql:latest ^
--character-set-server=utf8mb4 ^
--collation-server=utf8mb4_unicode_ci
테스트에 대한 DB도 실행할 수 있는데, 여기서 다른 점은 volume을 스키마만 적용했다는 것입니다. 테스트만 적용하기 때문에 추가적인 데이터가 유지될 필요가 없기 때문이죠
마지막으로 jar파일입니다.
jar파일의 경우 저는 maven을 사용해서
mvn clean package
를 통해 jar파일을 만들고
이 jar파일을 이미지로 만들어서 실행시키면 되겠죠 (물론 jar파일까지 같이 만드는 작업을 할 수도 있습니다.)
이미지를 만들기 위해 Dockerfile을 만들어 보겠습니다.
FROM amazoncorretto:17
MAINTAINER Psy <my-email@abc.ac.kr>
COPY ${PWD}/target/*.jar app.jar
ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar","/app.jar"]
간단하게 작성했고
FROM
: 우리가 사용할 베이스 이미지를 선택하는 부분입니다. 저의 경우 corretto를 사용하기 때문에 위와 같이 설정했습니다.MAINTAINER
: Dockerfile 작성자에 대한 정보COPY/ADD
: build를 하면서 폴더의 파일이나 폴더를 복사하는 역할을 한다- 다만 ADD의 경우 zip파일 등의 파일도 가능하게 해준다.
ENTRYPOINT/CMD
: 컨테이너를 생성 및 실행한 후 동작하게 하는 명령어이다.
- CMD : 컨테이너를 생성할 때만
- ENTRYPOINT: 컨테이너를 실행할 때마다
이 외에도
WORKDIR
: cd를 통한 작업공간 변경과 같다.EXPOSE
: 빌드로 생성된 이미지에서 열어줄 포트에서 사용VOLUME
: 마운트할 폴더를 지정할 수 있습니다. 여기서 진행하는 마운트는 실제 Volume, bind mount가 아니라 내부적으로 삭제하면 사라지는 공간입니다.
따라서 위 Dockerfile을 요약하자면,
corretto17의 이미지를 기반으로 Volume추가하고, jar파일 위치 옮기는 것까지 하고, 이미지를 실행시켜 컨테이너화하면 jar파일을 실행할 때마다 새로 시작해라
이런 말입니다.
이렇게 되면
docker run -p 8080:8080 --link gonggam-db gonggam-app
--link
: gonggam-db 컨테이너의 정보를 인식하여 연결할 수 있도록 해준다.
위와 같은 명령어로 실행이 가능하며

컨테이너들이 정상 동작하는 것을 확인할 수 있는데요
문제는 저 명령어들을 계쏙 cli로 작성을 하고 dockerfile을 만들어도 거기서 포트 설정해 주고 연결해주고 하느라 많은 시간 소요가 된다는 것입니다.
따라서 이러한 불편한 점을 해결하기 위해 여러 컨테이너들을 한 번에 관리할 수 있는 Docker-compose
가 존재합니다.
2. Docker-compose
이 docker-compose를 통해 컨테이너에 실행에 필요한 설정들을 docker-compose.yaml파일에 넣어서 간편화가 가능해졌습니다.
version: "3.7"
services:
# Spring boot
gonggam-app:
build:
dockerfile: be/Dockerfile
restart: always
ports:
- "8080:8080"
depends_on:
- gonggam-db
gonggam-db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: "qwe123"
MYSQL_DATABASE: "gonggam"
TZ: Asia/Seoul
LANG: "en_US.utf8"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db-init:/docker-entrypoint-initdb.d
- ./docker/database/datadir/:/var/lib/mysql
platform: linux/x86_64
ports:
- "3306:3306"
gonggam-test-db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: "test"
MYSQL_DATABASE: "gonggam-test"
TZ: Asia/Seoul
LANG: "en_US.utf8"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db-init:/docker-entrypoint-initdb.d
platform: linux/x86_64
ports:
- "3307:3306"
volumes:
logs_data: {}
하나하나 천천히 봐보겠습니다.
version: "3.7"
- version은 크게 3 이상과 3 이하로 나뉜다고 보면 될 거 같습니다. 또한 version에 따라 작성하는 규격이 다르므로 조심해야 할 부분 중 하나입니다.
# Spring boot
gonggam-app:
build:
dockerfile: be/Dockerfile
restart: always
ports:
- "8080:8080"
volumes:
- logs_data:/tmp/logs
depends_on:
- gonggam-db
# 마운트
volumes:
logs_data: {}
gonggam-app
: 컨테이너 이름build
: 사용하고자 하는 이미지를 가져오게 되는데 build를 통해 Dockerfile을 빌드하여 사용했습니다.- Image로 사용도 가능하지만, Jar의 특성상 코드가 계속 변경되면, package를 다시 해줘야 하기 때문에 docker-compse를 실행할 때마다 재 빌드 할 수 있도록 해놓았습니다.
restart
: 컨테이너가 어떤 이유로 종료가 될 수 있는데, 종료가 되면 다시 시작되도록 하였습니다.ports
: 호스트8080와 컨테이너8080을 연결하였습니다.volumes
: 마운트 할 저장소의 위치를 지정합니다.- 현재는 Volume을 통해 접근을 하였습니다.
- 따라서 logs_data를 추가적으로 volume을 추가해 준 것입니다.
- 마운트할 대상은 /tmp/logs입니다. app이랑 동일한 위치에 존재합니다.
depends_on
: jar파일 같은 경우 db가 실행되고 있는지의 상태에 따라 다르기 때문에 db가 실행된 뒤에 실행되게 하는 depends_on을 사용했습니다.
*추가적으로 Dockerfile에서 Volume을 제거했습니다.
gonggam-db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: "qwe123"
MYSQL_DATABASE: "gonggam"
MYSQL_USER: "yo"
MYSQL_PASSWORD: "test"
TZ: Asia/Seoul
LANG: "en_US.utf8"
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- ./docker/db-init:/docker-entrypoint-initdb.d
- ./docker/database/datadir/:/var/lib/mysql
platform: linux/x86_64
ports:
- "3306:3306"
db의 경우 위에서 설명했던 것과 전부 동일합니다. 다만 다른 점은 image
로 docker file을 가져온 다는 것입니다.
만약 mysql에 대한 image가 없다면 root 레포인 docker hub에서 다운로드하게 됩니다.
test db 또한 일반 db와 유사하므로 넘어가겠습니다.
이렇게 구성을 하게 되었으면, 남은 건 실행입니다.
docker-compose up -d
docker-compose -f docker-compose-test.yaml up -d
docker-compose는 up이라는 명령어로 실행이 가능한데요
크게 2가지 옵션을 알려드리겠습니다.
-f
: 특정 파일을 명시적으로 실행하고 싶을 때 사용, 원래는 docker-compose라는 파일을 자동으로 찾기 때문에 필요가 없지만, 만약 여러 파일로 나눠서 관리를 한다 하면 -f를 통해 실행이 가능합니다.-d
: docker-compose를 백그라운드로 실행하고자 할 때 사용하면 됩니다.
이렇게 실행하게 되면


위와 같이 잘 실행되는 것을 볼 수 있습니다.
변경해야 할 부분
1. Ports -> Expose
현재는 db를 외부에서 접근이 가능합니다. host Port를 열어줬기 때문이죠, 따라서 expose
라는 옵션을 통해 내부적으로만 접근할 수 있도록 해야 합니다.
ports:
- "3306:3306"
expose:
- "3306"
이렇게 하더라도 결과는 동일하게 나오지만, 외부에서 접근할 수 없다는 장점이 있습니다.
2. health check
mysql이 정상 동작 하는지를 확인하는 것이 depends_on
이었는데, 이것을 healthcheck
기능으로 cutomizing이 가능합니다. 관련 링크는 아래에 넣었으니 추가적으로 필요할 때 보시면 될 거 같습니다.
3. FE와 Nginx의 결합
이 부분은 추후 업데이트 하겠습니다.
4. Jenkins or Github action을 통한 CI & CD 구축
아직 정확히는 모르지만, 이 부분은 host자체를 overlays로 여러 개로 나누어 여러 서버를 분산시켜 볼 예정이라 좀 더 공부가 필요합니다. 따라서 시간이 좀 걸릴 수 있습니다.
참고 자료
Getting Started | Spring Boot Docker
MySQL samples | Docker Documentation
[ Dockerfile 관련 ]
Dockerfile을 작성하고 Docker 실행하기 — 한땀한땀 쑤코딩 (tistory.com)
[ Health check]
PYRASIS.COM: 이재홍의 언제나 최신 Docker - Unit 8.2 docker-compose.yml 파일 작성하기
[ Overlay & VXLAN ]
134. [Docker] Deep Dive into Docker Overlay Network 1편 (VXLAN) : 네이버 블로그 (naver.com)
'사용기 > 도커' 카테고리의 다른 글
[도커 사용기] 1-2. 도커 이미지 & Volumn & 네트워크 (0) | 2023.07.29 |
---|---|
[도커 사용기] 1 . 도커란? (0) | 2023.07.29 |