[Docker] docker-compose를 이용한 Spring boot, MySQL 배포 환경 구성 + .env를 통한 민감정보 숨기기
1. jar 파일 준비
bootJar 빌드
인텔리제이 우측 상단에 Gradle 탭 > Tasks > build > bootJar 를 마우스 우클릭 하여 Run 한다.
jar 파일 생성 확인
빌드가 성공하면 좌측 프로젝트 build > libs 경로에 jar 파일이 생성된다.
2. Dockerfile
작성
FROM openjdk:11
ARG JAR_FILE=build/libs/server-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE} app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app.jar"]
- FROM: 이미지를 생성할 때 사용할 기반 이미지입니다. openjdk:8-jdk-alpine 이미지에서 레이어를 생성합니다.
- ARG: 변수 선언
이때,JAR_FILE
우측에 이전에 생성한 jar 파일 경로를 적어준다.
(ARG JAR_FILE=build/libs/*.jar
로 적어도 무방하다.) - COPY 실행할 jar파일을 도커 컨테이너 내부에 myboot.jar라는 이름으로 복사합니다. 상대 경로로 위치도 같이 설정 가능합니다.
- ENTRYPOINT 컨테이너가 시작될 때 실행할 스크립트 혹은 명령을 정의합니다.
3. 도커 네트워크 생성
도커 환경에서 여러 컨테이너를 동일한 환경에서 연동시키기 위해서 네트워크 설정이 필요하다.
여기서는 MySQL 과 springboot app이 동일한 네트워크에서 구동되도록 해주어야 한다.
일단 네트워크부터 하나 생성해준다.
docker network create springboot-mysql-net
생성된 네트워크는 아래 명령어로 확인 가능하다.
docker network ls
4. docker-compose.yml
작성
version: "3.8"
services:
db-mysql:
container_name: naem_database
image: mysql
env_file: ./.env
environment:
- MYSQL_ROOT_PASSWORD=$MYSQLDB_ROOT_PASSWORD
- MYSQL_DATABASE=$MYSQLDB_DATABASE
ports:
- $MYSQLDB_LOCAL_PORT:$MYSQLDB_DOCKER_PORT
volumes:
- ./docker/data:/var/lib/mysql
networks:
- springboot-mysql-net
application:
container_name: naem_application
build:
context: ./
dockerfile: Dockerfile
env_file: ./.env
ports:
- $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT
environment:
SPRING_APPLICATION_JSON: '{
"spring.datasource.url" : "jdbc:mysql://localhost:$MYSQLDB_DOCKER_PORT/$MYSQLDB_DATABASE?serverTimezone=UTC&characterEncoding=UTF-8",
"spring.datasource.username" : "$MYSQLDB_USER",
"spring.datasource.password" : "$MYSQLDB_ROOT_PASSWORD",
"spring.jpa.properties.hibernate.dialect" : "org.hibernate.dialect.MySQL8Dialect",
"spring.jpa.hibernate.ddl-auto" : "create"
}'
depends_on:
- db-mysql
networks:
- springboot-mysql-net
networks:
springboot-mysql-net:
driver: bridge
.env
파일
MYSQLDB_USER=testuser
MYSQLDB_ROOT_PASSWORD=testpassword
MYSQLDB_DATABASE=testdb
MYSQLDB_LOCAL_PORT=3306
MYSQLDB_DOCKER_PORT=3306
SPRING_LOCAL_PORT=8080
SPRING_DOCKER_PORT=8080
🌟 .env
파일에는 민감 정보들이 있기 때문에 .gitignore
에 등록해 깃헙에 올라가지 않도록 해야한다!
Volume 마운트
db 컨테이너를 삭제했을 때, 컨테이너 내부에 쌓였던 데이터베이스 데이터들도 모두 사라지는 문제를 해결할 수 있다.
volumes:
- ./docker/data:/var/lib/mysql
:
를 기준으로 앞쪽이 로컬 파일시스템의 경로이고 뒤쪽이 컨테이너 내부의 경로이다.
설정해준 컨테이너의 경로를 지정한 로컬 경로로 마운트 시키는 것이다.
데이터베이스 데이터가 저장되는 컨테이너 내부의 디렉터리인 var/lib/mysql
를 로컬 컴퓨터의 디렉터리./docker/data
로 연결하면,
컨테이너 삭제와 상관 없이 데이터를 유지할 수 있다.
docker-compose up
으로 실행하면 프로젝트의 루트경로에 docker
폴더가 생길 것이다.
😡 Trouble Shooting - 1
정말 고생한 에러였다..
[Full Error]
눈에 띄게 확인할 수 있는 에러는 아래와 같았다.
- Caused by: com.mysql.cj.exceptions.CJCommunicationsException: Communications link failure
- Caused by: java.net.ConnectException: Connection refused (Connection refused)
- Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
- Caused by: org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when ‘hibernate.dialect’ not set
수많은 래퍼런스를 찾아 전부 시도해보았지만 에러는 해결되지 않았다.
결론적으로 아래 글을 참고하여 에러를 해결했다.
원래는 application.yml
파일에 db 연결 정보를 넣었었는데, 위 글을 참고하여 docker-compose.yml
파일의 environment
부분에 연결 정보를 모두 넣었다.
5. 도커 명령 실행
docker-compose up --build
docker-compose up -d
docker-compose ps
docker-compose ps
명령으로 구동중인 컨테이너를 보면, 아래와 같이 mysql과 springboot 두 개 컨테이너가 구동되는 것을 확인할 수 있다.
😡 Trouble Shooting - 2
아래와 같은 에러가 발생했다..
3306 포트가 이미 실행중이라는 것 같아 아래처럼 3306 포트를 사용중인 프로세스를 찾아 kill 했다.
그런데 아래와 같은 오류가 발생했다.. 아무래도 83717은 kill 하면 안되는건가보다..
아래 명령으로 도커를 다시 실행하니 위 에러가 발생하지 않았다.😌
Ref
- https://ssyoni.tistory.com/m/22: jar 파일 준비
- https://velog.io/@dhk22/Springboot-MySQL-Docker-Volume-%EB%B3%BC%EB%A5%A8-%EB%A7%88%EC%9A%B4%ED%8A%B8: 볼륨 마운트 (심플)
- https://joonhwan.github.io/2018-11-14-fix-mysql-volume-share-issue/: 볼륨 마운트 (자세히)
- http://raccoonyy.github.io/docker-usages-for-dev-environment-setup/: 도커 컴포즈 (자세히)
💛 개인 공부 기록용 블로그입니다. 👻