일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 백준#boj#16932#모양만들기
- 백준#boj#12755
- 백준#BOJ#14501#퇴사#브루트포스
- 백준#BOJ#12865#평범한배낭
- 백준#BOJ#8012#한동이는영업사원
- 백준#BOJ#2615#오목
- 백준#BOJ#1939#중량제한
- Today
- Total
순간을 성실히, 화려함보단 꾸준함을
[Docker] docker-compose 첫 사용기! 본문
안녕하세요.
오늘은 글또 9기 2번째 글을 적으려고 합니다.
주제는 Dockerfile 과 docker-compose 를 활용한 개발환경 세팅하기 입니다.
docker-compose 가 무엇인지도 몰랐지만 이번 기회에 공부도 하면서 직접 토이 프로젝트에 적용해보았습니다.
반드시 docker 가 로컬 컴퓨터에 설치가 되어 있어야 합니다.
windows, mac 같은 경우는 docker desktop 을 설치하면 docker compose 를 자동으로 사용할 수 있습니다.
배경
왜 갑자기 docker-compose 를 사용하게 된걸까요??
토이프로젝트 api 들이 개발이 어느정도 진행 된 상황에서 aws ec2 에 배포를 할 예정입니다.
배포환경에서는 db 를 mysql 을 사용할 예정인데, 로컬환경에서는 H2 database 를 사용하고 있습니다.
현재 프론트개발자 1명, 백엔드 개발자 2명 이렇게 개발을 하고 있는 상황인데 개발환경이 바뀌면 함께 개발하고 있는 분들 또한 변경이 발생하게 됩니다.(각자 로컬에서 프론트 프로젝트/백엔드 프로젝트 를 각각 띄워서 진행하고 있거든요,,,ㅠㅠ)
그래서 이를 어떻게 하면 최소화 할 수 있을까? 고민하다가 백엔드 프로젝트를 이미지화 시켜서 도커환경에서 컨테이너로 띄워버리면 각 로컬 환경에서 docker desktop 만 설치하여 실행시키면 될 것 같다는 생각이 들었습니다.
과정
먼저 spring boot 프로젝트를 이미지화 시킬 수 있는 Dockerfile 을 정의하였습니다.
# Use the official OpenJDK base image
FROM openjdk:11-jdk
# Copy the jar file into the image
COPY ./build/libs/diray-0.0.1-SNAPSHOT.jar app.jar
# Set the entry point to start the application
ENTRYPOINT ["java","-jar","/app.jar"]
FROM : 해당 프로젝트를 실행시키기 위해 토대가 되는 이미지를 지정합니다. 전 java 11
버전을 사용하고 있으니 openjdk:11-jdk
라는 이미지를 정의하였습니다.
COPY : 이미지에 파일이나 폴더를 추가하는 역할입니다. (build 가 완료된 .jar 파일 위치) (복사할 경로 위치), 전 gradle
로 build 하고 있으므로 .jar 파일이 위치한 경로를 입력해주었고, app.jar 라는 파일명으로 복사할 것을 명시해주었습니다.
ENTRYPOINT : 컨테이너를 실행할 명령어를 정의해줍니다. 제가 정의한 명령어들은 결국 java -jar /app.jar
라는 명령어로 실행됩니다. 즉, jar 파일을 실행시키는 것 입니다.
첫번째 단계는 끝났습니다. 그 다음은 정의한 Dockerfile 을 가지고 docker-compose.yml 을 정의해봅시다.
version: '3'
services:
mysql:
image: mysql:8.0
container_name: mysql_db
ports:
- "3306:3306" # HOST:CONTAINER
environment:
MYSQL_DATABASE: diarydb
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: admin
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- D:/mysql/data:/var/lib/mysql
networks:
- app_network
backend:
build:
dockerfile: Dockerfile
context: ./
container_name: app_backend
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql_db:3306/diarydb?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: admin
depends_on:
- mysql
ports:
- "8080:8080"
volumes:
- ./:/app
networks:
- app_network
networks:
app_network:
mysql 컨테이너와 제 프로젝트 (jar) 컨테이너를 정의해주었습니다.
mysql 에서 주의할 점은 개인 로컬 환경에서 3306 port 를 이미 사용하고 계시는 분들이 있습니다. 이때는 기존 3306 port 를 죽이던가 아니면 HOST port 를 변경 해야합니다.
mysql:
image: mysql:8.0
container_name: mysql_db
ports:
- "3307:3306" # HOST:CONTAINER
environment:
MYSQL_DATABASE: diarydb
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: admin
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
volumes:
- D:/mysql/data:/var/lib/mysql
networks:
- app_network
위 처럼 3307 로 변경하시면 됩니다.(꼭 3307 이 아니어도 다른 포트면 됩니다)
또한, environment
부분인데요. 해당 내용은 mysql 유저에 관한 정보들을 정의해주면 되는데 전 root 로 정의하였습니다.
다른 유저로 접속하고 싶다 하시면
environment:
MYSQL_DATABASE: diarydb
MYSQL_USER: user
MYSQL_USER_PASSWORD: userpwd
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: admin
위와 같이 따로 추가를 해주면 되는데, 이때 정의만 한다고 유저가 생성되는 건 아닌 것 같더라구요. 전 위와 같이 user 를 정의하고 docker compose 를 실행시켜보았을때 mysql 에 접속이 되지 않았습니다.
그리고 mysql8.0 을 사용하시고 계시다면 반드시 command
부분을 정의해주어야 합니다.
volumn
은 백업을 굳이 안하고 싶다고 하시면 빼도 되지만 networks
는 반드시 정의해주어야 합니다. 그래야지 독립되어 있는 mysql container
와 jar container
가 동일한 네트워크를 통해 커넥션을 맺을 수 있기 때문입니다.
mysql 에 관한 주의할 점은 여기까지 적으면 충분할 것 같습니다.
다음으로는 backend project 에 대해서 말씀드리겠습니다.
가장 중요한 부분은 depends_on
입니다. 생각해보시면 jar
컨테이너는 mysql 컨테이너가 먼저 실행이 되어야지만 db connection 을 맺을 수 있습니다. 그런데 mysql 컨테이너 보다 jar 컨테이너가 먼저 실행되면,,,,???낭패겠죠?
그래서 docker compose 에서는 이를 위해 depends_on
이라는 명령어를 통해 순서를 정의해줄 수 있습니다.
app_backend
라는 컨테이너는 mysql
에 의존하고 있습니다. 그러니 mysql
을 먼저 실행시켜주세요. 라는 뜻입니다.
절대 빼먹으면 안됩니다!!
또, 해맸던 부분이 있었는데 datasource 를 정의해주는 부분이었습니다.
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql_db:3306/diarydb?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: admin
url 을 어떻게 정의해줘야하는지 조금 해맸는데요 아래와 같습니다.
jdbc:{database 정의}://{mysql container 이름}:{실행시킨 port number}/{mysql database 이름}?useSSL=false&allowPublicKeyRetrieval=true
docker compose 에 관한 간단한 명령어를 알아보겠습니다.
docker compose up
: 컨테이너를 생성하고 실행시킵니다. 보통 백그라운드로 실행시키기 때문에 맨 마지막에 -d
를 붙여줍니다.
ex) docker compose up -d
docker compose down
: 컨테이너와 네트워크를 종료하고 삭제합니다. 이때, 정말 주의할 점은 docker images 를 삭제하는 것이 아닙니다. 따라서 application.yml
을 변경한다던가 소스 수정이 발생했을때는 기존 image 들을 삭제한 뒤 다시 clean - build 를 실행시켜주어야 합니다.
docker compose logs
: 실행중인 컨테이너의 log 들을 확인할 수 있습니다. 다만 docker desktop 을 사용하시고 계시다면 desktop 에서도 간단하게 확인하실 수 있으십니다.
자 그럼 다 끝났습니다. 한번 실행시켜 볼까요?
docker compose up -d
명령어를 입력하였습니다.
터미널에 정상적으로 create 된걸 확인할 수 있습니다.
docker desktop 에서도 확인해보죠.
잘 실행된거 같죠??ㅎㅎ
한번 postman 으로 요청을 직접 보내봅시다.
응답값이 없어서 response body 에 아무값도 없긴 하지만 200 status code 가 잘 내려온 것 같습니다!!
혹시 모르니 log 를 확인해보도록 하죠
멋지네요.이로써 성공했습니다.
결과 및 느낀점
사실 하루종일 삽질해 가면서 세팅했었습니다....문제의 원인은 전 docker compose down
하면 아에 초기화가 되는 줄 알고 소스를 수정하고 저 명령어만 입력했었거든요...근데 절대 아니라는거,,,image 들은 그대로 남아있기 때문에 반드시 image 들도 삭제하고 다시 build 를 실행해주어야 합니다. ㅋㅋ
docker 에 관하여 익숙치 않았긴 했는데 이번 기회에 재밌게 진행했던 것 같습니다.ㅎㅎ
얼른 팀원들에게도 같이 공유를 해야겠네요 ㅎㅎㅎ
감사합니다.
'나의 개발 메모장' 카테고리의 다른 글
대용량 데이터는 어떻게 관리해야 되는 걸까? (0) | 2024.01.20 |
---|---|
2023년 회고 (3) | 2023.12.30 |
동시성 문제에 관하여... (0) | 2023.12.10 |
MultipartFile 은 어떻게 validation 체크를 해야할까?(ConstraintValidator.class) (2) | 2023.09.03 |
인텔리제이 .http 파일로 MultipartFile 전송해보기 (0) | 2023.08.19 |