Java/SpringBoot로 개발한 서비스를 도커 이미지로 컨테이너화해서 EC2 서버에 배포하기로 결정하였다.
1. 처음엔 t2.micro 서버 하나에 Redis, Mysql, Java 프로젝트를 한 번에 올리려고 했음
-> Dockerfile에 어떤 걸 작성해야 할지, 환경변수 설정을 어떻게 하는 지에 대한 개념 부족으로 시간 지체
-> 이슈 해결 후에는 서버가 부하가 발생해 자꾸 죽음
2. 서버를 분리하여 배포하기로 결정
-> 한 서버에는 Redis와 Mysql 실행
-> 다른 서버에는 Java 프로젝트 실행
1번에서 2번으로 바꾸고 성공하기까지는 장장 6시간이 걸렸ㄷr.. 까먹기 전에 우선 순서를 남겨놔야지
1. Dockerfile 작성
# Use OpenJDK 17 slim image as base for the build stage
FROM --platform=linux/amd64 openjdk:17-jdk-slim AS build
# Set the working directory in the container
WORKDIR /app
# Define an argument for the JAR file location
ARG JAR_FILE=build/libs/*.jar
# Copy the JAR file from the build context to the container
COPY ${JAR_FILE} app.jar
# Create a new stage for the runtime environment
FROM --platform=linux/amd64 openjdk:17-jdk-slim
# Set the working directory in the container
WORKDIR /app
# Copy the application configuration file to the container
COPY src/main/resources/application.yml /app/application.yml
# Copy the JAR file from the build stage to the runtime stage
COPY --from=build /app/app.jar app.jar
# Expose port 8080 for the application
EXPOSE 8080
# Define the entrypoint for the container
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dotel.resource.attributes=service.name=auth-server", "-jar", "app.jar"]
진행 중인 프로젝트의 버전에 맞게 FROM 절을 작성했고
application.yml을 COPY 한 이유는 Redis, Mysql과 환경설정을 따로 나누기 위해서이다.
2. Gradle에서 BootJar 를 실행해 Jar 파일을 생성
프로젝트의 build > libs 폴더에 [프로젝트명].jar 파일이 생성됨을 확인한다.
3. 해당 프로젝트의 Dockerfile이 있는 위치에서 terminal 창을 연뒤, 이미지 생성 후 docker hub에 push
docker buildx build --platform linux/amd64 -t {도커 계정명}/{이미지명} --push .
위 명령어는 --platform linux/amd64 로 구체화하여 build 한거고 보통은 아래 명령어로 해도 된다.
(필자의 경우 버전 충돌로 에러가 나서..ㅎ)
여기서 이미지명은 push하고자 하는 프로젝트의 이름으로 정했다.
docker build -t {도커 계정명}/{이미지명}:latest .
docker push {도커 계정명}/{이미지명}:latest
4. EC2 서버 연결하기
4-1. Redis와 Mysql 서버 설정
0. 서버 접속 방법
ec2 인스턴스 생성 시에 발급받은 key pair 저장 위치에서 terminal 또는 git bash 창을 연다.
ssh -i <키페어> <사용자이름>@<서버IP주소>
키페어 : 말 그대로 키페어 이름 작성 OR 드래그 드랍 해도 됨
사용자 이름 : 필자의 경우 ubuntu 서버를 사용했기 때문에 ubuntu로 사용
서버 IP 주소 : ec2 인스턴스 퍼블릭 IPv4 주소
1. 서버 접속 후 docker 설치
1-1. 시스템 패키지 업데이트
sudo apt update
sudo apt upgrade -y
1-2. 필수 패키지 설치
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
1-3. Docker GPG 키 추가
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
1-4. Docker 저장소 추가
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
1-5. Docker 설치
sudo apt update
sudo apt install docker-ce -y
1-6. Docker 서비스 시작 및 자동 실행 설정
sudo systemctl start docker
sudo systemctl enable docker
1-7. Docker 설치 확인
sudo docker --version
1-8. 비루트 사용자로 Docker 사용
Docker 명령어를 사용할 때마다 sudo를 입력하지 않으려면 현재 사용자를 docker 그룹에 추가합니다.
sudo usermod -aG docker $USER
1-9. 변경사항 적용을 위해 로그아웃 후 다시 로그인
newgrp docker
2. docker-compose 설치
sudo apt install docker-compose
2-1. docker-compose 버전 확인
docker-compose --version
3. docker-compose.yml 설정
3-1. 폴더 생성 후 열기
nano docker-compose.yml
3-2. 아래 내용 작성 (linux 환경에서는 띄어쓰기가 쉽지 않으니 다른 곳에 작성하고 붙여넣는 걸 추천)
> docker-compose.yml
version: "3.9"
services:
mysql:
image: mysql:8.0
container_name: 설정할 mysql container 이름
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: ${DB_NAME} # 데이터베이스 이름
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} # 데이터베이스 루트 비밀번호
volumes:
- mysql-vl:/var/lib/mysql
redis:
image: redis:latest
container_name: 설정할 redis container 이름
ports:
- "6379:6379"
volumes:
- redis-vl:/data
volumes:
mysql-vl:
driver: local
redis-vl:
driver: local
Ctrl(^) + X -> Y -> Enter 로 저장 (mac기준)
4. .env 파일 설정 (오타 아님. 필자의 경우 .env 로 파일을 생성함)
nano .env
> .env
DB_HOST=mysql
DB_PORT=3306
DB_NAME=설정할DB이름
DB_USER=root
DB_PASSWORD=비밀번호
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_PASSWORD=비밀번호
여기서 쓰이는 DB_HOST와 REDIS_HOST는 localhost가 아니다.
보통은 해당하는 이름을 쓴다하여 mysql과 redis로 정함.
아까와 똑같이 Ctrl(^) + X -> Y -> Enter 로 저장
5. docker-compose.yml 실행
docker-compose up -d
만약 내용을 수정한다면 내렸다가 다시 올려야 함
docker-compose down
docker-compose up -d
docker ps
로 잘 실행되고 있는 지 확인
이제 docker로 mysql과 redis를 띄워놨다. Java 프로젝트를 띄워보자.
6. Java 프로젝트 서버 설정
오히려 java는 간단하다.
방법은 여러가지가 있지만 나는 우선 docker-compose.yml 을 만들어 환경변수를 작성하는 방법을 택했다.
nano docker-compose.yml
version: '3.8'
services:
app:
image: {도커 계정명}/{이미지명}:latest
container_name: {사용할 컨테이너 이름}
ports:
- "8080:8080"
environment:
SPRING_PROFILES_ACTIVE: prod
DB_HOST: {아까 Mysql 띄운 서버 IP 또는 DNS}
DB_PORT: 3306
DB_NAME: {DB 이름}
DB_USER: {DB 사용자}
DB_PASSWORD: {DB 비밀번호}
REDIS_HOST: {아까 Mysql 띄운 서버 IP 또는 DNS}
REDIS_PORT: 6379
REDIS_PASSWORD: {Redis 비밀번호}
JWT_SECRET_KEY: {JWT 인증키}
API_KEY: {서울시공공데이터 openAPI 인증키}
API_URL: {인증 URL}
API_RESPONSE_TYPE: {응답데이터 타입}
API_SERVICE_NAME: {서비스명}
COORDINATE_API_KEY: {주소 검색 openAPI 인증키}
COORDINATE_API_URL: {주소 검색 openAPI 인증 URL}
DISCORD_WEBHOOK_URL: {DISCORD 웹훅 URL}
대부분의 데이터를 { } 안에 작성해놨지만 실제로는 문자, 숫자 값만 입력해야한다.
다만 해당 문자열 안에 띄어쓰기가 있고 띄어쓰기 까지 포함해야하는 경우 " " 안에 값을 입력한다.
다 작성했다면 Ctrl(^) + X -> Y -> Enter 로 저장
7. Java 프로젝트 서버 실행
docker-compose up -d
입력하고
docker ps
로 실행 중인 컨테이너 확인
만약 실행이 됐는데 중간에 오류로 서버가 종료돼서 안 보이면
docker ps -a
로 확인해보면 된다.
내가 삽질했던 가장 큰 이유는 JWT 비밀 키를 읽어오지 못했던 이슈인데 application.yml 에 위치가 잘못되어 있어 읽지 못했던 것이었다.
yml 파일은 들여쓰기가 정말 중요한 걸 다시 한 번 깨달았고, 그로 인해 많은 방법을 배워서 좋았다..!^^
참고로 jwt secretkey의 위치는 spring과 같은 depth, 최상단에 위치하는 게 맞다!
성공한 건 3시 20분이고 지금은 새벽 4시 20분. 한 시간 만에 작성한 내용이라 정제되지 않고 나만 보기 편하게 되어 있을 것 같다. 내일 좀 더 다듬고 정리해야지.!
그래도 끝까지 포기하지 않고 해내니 성취감이 이루 말할 수가 없이 기쁘다!!! 이제 오류를 마주하는 것쯤 오히려 좋아라는 마인드
'Server > docker' 카테고리의 다른 글
[Docker] 도커로 EC2에 서버 배포하기_ver 2. (10) | 2024.10.09 |
---|---|
Docker를 활용한 Redis 기본 세팅 및 Springboot 연결 확인 (0) | 2024.08.26 |
[원티드 프리온보딩 백엔드 챌린지] TIL 도커란?_실전편 (0) | 2023.08.05 |
[원티드 프리온보딩 백엔드 챌린지] TIL 도커란?_이론편 (0) | 2023.08.03 |
[Docker] M1에 Docker Desktop 설치하는 법 (0) | 2023.04.11 |