[Docker] Docker를 이용해 AWS EC2에 배포하기 (부제: 허무한 오류와 함께 보낸 이틀..)
1. Docker 회원가입 및 설치
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 비밀번호에 !(느낌표)가 포함되어 있었던 것
이렇게 네가지가 마음에 걸린다...
무튼 여러 가지 방법을 다 시도해보았는데 결국 캐시가 문제였던 것...!!!
누군가 이 글을 본다면 이러한 실수는 하지 않길 바라며 꼼꼼하게 적어보았다.
결국 배포에 성공했습니다용~ 오예