Programming/Network

[Docker] Docker를 이용해 AWS EC2에 배포하기 (부제: 허무한 오류와 함께 보낸 이틀..)

히히심 2025. 2. 19. 19:59
728x90


1. Docker 회원가입 및 설치

 

https://hub.docker.com/

 

Docker Hub Container Image Library | App Containerization

Increase your reach and adoption on Docker Hub With a Docker Verified Publisher subscription, you'll increase trust, boost discoverability, get exclusive data insights, and much more.

hub.docker.com

 

https://www.docker.com/products/docker-desktop/ 

 

Docker Desktop: The #1 Containerization Tool for Developers | Docker

Docker Desktop is collaborative containerization software for developers. Get started and download Docker Desktop today on Mac, Windows, or Linux.

www.docker.com

 

 

짜잔 맥에 Docker 설치 완료

 

 

 

2. AWS EC2 생성 (리눅스 서버)

1) EC2 인스턴스 생성

 

2) 보안그룹 생성 및 인바운드 규칙 구성 

여기서 바보같이 아웃바운드 규칙으로 추가했지만, 나중에 인바운드 규칙으로 바꿈!!

 

3) 이후 EC2 인스턴스의 보안그룹을 해당 보안그룹으로 변경해주면 된다.

 

3. 해당 EC2 서버에 접속하여 도커 설치하기

1) EC2 인스턴스를 만들 때 받은 keypair를 이용하여 서버에 접속한다. 

ssh -i /path/to/my-key.pem ec2-user@<EC2_PUBLIC_IP>
ssh -i Downloads/refrig-keypair.pem ec2-user@15.xxx.xxx.179

 

 

2) docker 설치하기

# 패키지 업데이트
sudo yum update -y

# Docker 설치
sudo yum install docker

# Docker 버전 확인
docker -v

#Docker 실행
sudo service docker start

#ec2-user를 docker 그룹에 추가 
sudo usermod -aG docker ec2-user

#추가 이후 변경사항 적용 위해 세션 갱신
newgrp docker

 

 

4. Dockerfile 생성

 

1) project/Dockerfile 프로젝트 폴더 내에 바로 Dockerfile 생성

 

2) Dockerfile 구성

FROM openjdk:17

ARG JAR_FILE=build/libs/*.jar

COPY ${JAR_FILE} /app.jar

ENV SPRING_PROFILE="DEV"

ENTRYPOINT ["java", "-jar", "/app.jar"]

 

⬇️ Dockerfile 지시어 참고

더보기
ADD 로컬 혹은 리모트 파일과 디렉토리 추가
ARG 빌드 시 변수 사용
CMD 기본 명령어 명시
COPY 파일과 디렉토리 복사
ENTRYPOINT 기본 실행 명령
ENV 환경 변수 설정
EXPOSE 해당 어플리케이션이 어떤 포트를 사용하는지 
FROM base image로부터 새로운 빌드 단계를 생성
HEALTHCHECK 시작 시 컨테이너의 헬스체크
LABEL 이미지에 메타데이터 추가
MAINTAINER 이미지 author 명시
ONBUILD 이미지가 빌드에 사용될 때를 위한 설명
RUN 빌드 명령 실행
SHELL 이미지의 기본 쉘 설정
STOPSIGNAL 컨테이너 중지 사인
USER 유저와 그룹 ID 설정
VOLUME 볼륨 마운트 생성
WORKDIR 작업 디렉터리 변경

 

5. 도커 이미지 생성 및 푸쉬

1) Gradle 빌드

./gradlew clean bootJar

 

 

2) Docker 로그인

docker login -u [username]
[password]

 

3) Docker 이미지 생성

# 이미지 생성
docker build --platform linux/amd64 -t simidot/demo .

# 생성된 이미지 확인
docker images

 

4) Docker Hub에 Docker Image 업로드

docker push simidot/demo

 

 

6. EC2에서 Docker 이미지 다운로드 및 실행

1) 실행되어 있는 EC2 서버에서 docker Image 다운로드

docker pull [dockerHubId]/[이미지명]

 

2) Docker 컨테이너 실행

docker run -d -p 8080:8080 simidot/demo

3) 실행중인 Docker 컨테이너 확인

# 실행중인 컨테이너 확인
docker ps

# 모든 컨테이너 확인
docker ps -a

 

4) 실행중인 Docker 컨테이너 끄기 및 삭제

# Docker 컨테이너 끄기
docker stop [container id/이름]

# Docker 컨테이너 제거
docker rm [container id/이름]

 

 

 

 

 


요렇게 성공적으로 한번에 되면 좋을텐데... 

나는 이 오류를 만 이틀 정도 헤맸다....

 

드 디 어 ! 해결을 했는데 

너무나도 허무한 도커 오류 이야기~~~~~ 하하

보면 로컬에서 실행 시에는 너무 너무 실행이 잘 된다.

 

 

그런데, 문제는 

도커 이미지 빌드해서 EC2에서 실행해도, 그리고 로컬에서 그 이미지 컨테이너를 실행해도 

지속적으로 이러한 오류가 났다. 

Communications link failure
The driver has not received any packets from the server.
Could not obtain connection to query metadata

영원히 이 오류에 갇혀서 못빠져나옴 ;;;;;; 

 

 

1) JDBC 설정이 잘못되었나? 아님

spring:
  config:
    active:
      on-profile: DEV
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://refrig-db.cc2zn7fmrxqy.ap-northeast-2.rds.amazonaws.com:3306/refrig?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
    username: root
    password: password

yml 파일 야무지게 잘 설정해둠. 그리고 오타도 없음.

 

2) RDS 인스턴스 접근 설정 공용 접근이 막혔나? 아님

Publicly Accessible YES!

 

3) 방화벽/보안 그룹 규칙이 해당 IP를 허용하는지?

넵 인바운드 규칙 다 넣어주었구요... ㅠㅠ

이외의 여러 가지 이유들이 있었음..

 

진짜 도대체 이유가 뭔지 모르겠어서 수십번 설정들을 바꿔보았지만, 아무리 생각해도 AWS 설정 측에 문제 없는거 같고...

그렇다고 스프링 부트에서도 여러 설정을 바꿔도 똑같았다 계속 같은 오류가 나는게 너무나 답답

해결 방법은 바로바로 ~ 

문제가 있던 그 이미지 푸쉬 이후에 다시 코드를 수정하고 clean build를 하지 않아서였다...

아무리 문제를 해결했어도 변경된 부분이 반영이 안되고 있었던 것.

 

정말 허무하쥬? 

./gradlew clean build

1) Clean : 이전 빌드의 결과물을 삭제한다. 

만약 코드, 설정 파일, 또는 의존성 변경이 있었는데 이전 빌드 결과물이 남아있다면 이로 인해 새로운 변경 사항이 제대로 반영되지 않을 수 있다.

2) 그 후 buid : 전체 프로젝트를 다시 컴파일하고, 테스트 실행하며, 새로운 빌드 아티팩트를 생성한다. 

즉, 캐시된 파일이 새로운 변경사항과 충돌할 경우 오류가 발생할 수 있다~~~

 

그래서 결국 진짜 이 문제의 해결방법을 못찾았는데, 

내가 예상하는 후보는 

1) yml 파일에서 spring.jpa.database-platform: org.hibernate.dialect.MySQLDialect 요 설정 안해준 것

2) Dockerfile에서 기본 프로파일 설정 안해준것

ENV SPRING_PROFILE="DEV"

3) 엔티티 중 Groups라는 엔티티가 있었는데 해당 엔티티 이름이 Group by 예약어와 겹쳤던 것

4) datasource 비밀번호에 !(느낌표)가 포함되어 있었던 것

 

이렇게 네가지가 마음에 걸린다...

무튼 여러 가지 방법을 다 시도해보았는데 결국 캐시가 문제였던 것...!!! 

누군가 이 글을 본다면 이러한 실수는 하지 않길 바라며 꼼꼼하게 적어보았다. 

 

 

결국 배포에 성공했습니다용~ 오예

728x90