
docker-compose로 project의 작동을 확인 해 봤다.
▶Project를 배포 해보자 #1 (docker-compose)
project를 배포하기 위해 EC2 인스턴스를 생성 해줘야 한다.

인스턴스 명과 사용할 AMI(Amazon Machine Image)를 선택해야 한다.
AMI로 Ubuntu를 선택 했으며 기호에 맞게 변경하면 좋을 것 같다.


미리 만들어둔 키 페어가 존재하지 않았기에 새로 생성을 해서 적용 했다.

네트워크는 딱히 수정할 필요 없이 default로 설정


인스턴스 생성이 정상적으로 완료 되었음을 확인 할 수 있다.
인스턴스를 생성할 때 항상 새 IP를 할당한다.
인스턴스를 중지하고 재시작하면 새로운 IP가 할당되기 때문에 고정적인 IP를 가질수 있도록 탄력적 IP 주소를 할당해 줘야 한다.
안 해줘도 실행 하는데 문제는 없다.
**
탄력적 IP를 만들고 ec2에 연결해주지 않으면 과금이 되기때문에 반드시 연결해야 한다.
생성에는 과금이 되지 않으며 생성 후 방치 하면 요금이 부과 되는 것 같다.



생성한 고정 IP주소를 인스턴스와 연결


정상적으로 IP 주소가 고정 됨을 확인 했다.


생성한 인스턴스 정보를 통해 보안그룹 이름을 확인 할 수 있으며, 보안그룹 이름을 통해 인바운드 규칙을 설정한다.
9091포트를 사용하는 spring boot 프로젝트에 접속 하기 위해 9091포트를 인바운드 설정 해줬다.
본인이 사용하는 spring boot port 번호에 맞게 변경하여 개방 해주면 된다.

인스턴스가 중지 된 상태라면 시작 상태로 변경 해주면 연결이 가능하다.

프리티어로 사용 할 수 있는 t2.micro는 RAM 1GB(GiB)의 제한이 있기 때문에 프로젝트를 실행 할 때 뻗는 경우가 있었다.
CPU 점유율이 99 ~ 100이 되면 자체적으로 ec2에서 연결을 끊어버리기 때문에 용량을 늘릴 필요가 있었다.
docker-compose로 실행 하려는 프로젝트는 기본 용량을 한참 넘어서기 때문에 어쩔 수 없이 대안을 찾아 봐야 했다.
ec2 램 메모리가 가득 찰 경우 실제 디스크의 용량을 이용하여 부족한 메모리를 대체할 공간을 생성 할 것이며 이를 swap memory(스왑 공간)이라 한다.
swap메모리는 ec2 램을 대체 하는 것은 아니기 때문에 램에 직접 접근 하는 것 보다 속도가 느려지지만 테스트 목적 이기 때문에 감당 하기로 했다.
sudo dd if=/dev/zero of=/swapfile bs=128M count=16
sudo : 'Super User Do'의 줄임말로, 관리자 권한으로 명령을 실행하는 데 사용
dd : 파일을 복사하거나 변환하는 데 사용되는 명령어
if=/dev/zero : /dev/zero를 사용, /dev/zero는 모든 위치에서 읽을 때마다 null 바이트를 생성하는 특수 파일이다.
of=/swapfile : 출력 파일로 /swapfile을 사용한다는 의미
bs=128M count=16 : 2GB(128MB x 16)의 용량을 할당 한다.

sudo chmod 600 /swapfile
읽기, 쓰기가 가능하도록 chmod 600으로 설정 해줬다.
sudo mkswap /swapfile
mkswap : /swapfile을 스왑 공간으로 설정.
sudo swapon /swapfile
swapon : /swapfile 스왑 공간을 즉시 활성화 한다.
sudo vi /etc/fstab 명령어를 입력 후 /etc/fstab vi 에디터 열어주고 파일의 맨 아래에 /swapfile swap swap defaults 0 0 를 추가 해준다.
ec2환경에서 docker와 compose를 작동하기 위해 docker 설치 및 docker compose 사전 작업을 해주자.

패키지 업데이트
sudo apt update
https관련 패키지
sudo apt install apt-transport-https ca-certificates curl software-properties-common
docker repository gpg 키 설정
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
docker repository 등록
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
패키지 업데이트
sudo apt update
도커 설치
sudo apt install docker-ce
확인
docker --version
sudo docker-compose up -d 명령어 실행 시에
ubuntu@ip-172-31-32-137:~/mere-dev-merona$ sudo docker-compose up
sudo: docker-compose: command not found
와 같은 에러가 발생 한다면
docker-compose 설치
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
실행 권한 부여
sudo chmod +x /usr/local/bin/docker-compose
Spring Boot를 jar파일로 변환 해주기 위해서 Dockerfile-server.yml 파일을 작성 한다.
FROM openjdk:8-jdk
EXPOSE 9091
ARG JAR_FILE=./build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Dockerfile-server.yml 파일을 작성 후 dokcer-compose.yml 파일과 동일한 경로에 위치 하게 둔다.
server:
build:
context: .
dockerfile: Dockerfile_server
container_name: dev_merona_spring_boot ## 컨테이너 이름
restart: always # 매번 프로젝트를 다시 실행한다.
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/{database 명}?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: {USERNAME}
SPRING_DATASOURCE_PASSWORD: {PASSWORD}
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
SPRING_RABBITMQ_HOST: rabbitmq
SPRING_RABBITMQ_PORT: 5672
SPRING_RABBITMQ_USERNAME: guest
SPRING_RABBITMQ_PASSWORD: guest
spring.profiles.active: local ## 스프링 active profile 설정
ports:
- 9091:9091
depends_on:
- mysql
- redis
- rabbitmq
networks:
- dev_merona
rabbitmq:
image: rabbitmq:3.12.11-management
hostname: rabbitmq
container_name: dev_merona_rabbitmq
restart: unless-stopped
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
ports:
- 5672:5672
- 15672:15672
networks:
- dev_merona
# rabbit image 버전 3.12.11
# 5672작동 , 15672 시각화
mysql:
container_name: dev_merona_mysql
image: mysql:8.0.22
environment:
MYSQL_DATABASE: {database 명}
MYSQL_ROOT_PASSWORD: {PASSWORD}
MYSQL_ROOT_HOST: '%'
# MySQL root 계정이 어떤 호스트에서든지 접근 가능하도록 설정
TZ: 'Asia/Seoul'
# 컨테이너의 시간대를 'Asia/Seoul'로 설정.
ports:
- 3306:3306
# 호스트의 3306 포트와 컨테이너의 3306 포트를 연결
volumes:
- ./mysql-file/dev_merona_mere.sql:/docker-entrypoint-initdb.d/dev_merona_mere.sql
#mysql 덤프 파일
networks:
- dev_merona
restart: always
redis:
container_name: dev_merona_redis
image: redis:6.2.5
command: redis-server
restart: always
networks:
- dev_merona
ports:
- 6379:6379
volumes:
elasticsearch:
networks:
dev_merona:
#네트워크 명
#동일한 네트워크를 설정
driver: bridge
docker-compose 파일 경로로 이동해서 docker-compose up 명령어를 작동 한다면 container와 image가 생성 될 것이다.

원래 계획은 git hub를 통해서 프로젝트를 통째로 내려받은 후 docker-compose 파일을 작동 시켜 ec2환경에서 그대로 돌려버릴 생각 이였다.
하지만 막상 ec2환경에서 docker-compose 파일을 실행 시켜보니 spring boot Dockfile이 정상 작동 하지 않았다.
git ignore로 위험성이 있는 폴더 들을 제외 했었기 때문에 해당하는 폴더 및 파일들은 git에 업로드가 되지 않았으며 jar파일의 폴더도 포함되어 있었다.
ignore된 project를 git에 업로드 했기 때문에 git 프로젝트를 그대로 받은 ec2 project 역시 ignore된 상태 였던 것이다.
git ignore를 전부 수정 하려고도 시도 해봤지만 워낙 많은 설정들이 되어 있어 수정하기 난감 했다.
프로젝트를 수정하지 않고 ec2환경에 내려받기 위해 Docker hub에 spring boot image를 업로드 하기로 했다.
hub에 image를 업로드 후 docker-compose 파일로 해당 이미지를 다운 받을 수 있도록 설정 한다면 가능 할 것 같았다.

먼저 repository를 생성 해준다.

cmd창 또는 teminal에 접속 후 docker login 명령어 입력을 통해 docker에 접속한다.
만약 username , password를 요구한다면 docker hub 가입 시 입력했던 값을 넣어 주면 될 듯 하다.

현재 image들을 전부 확인 후 hub에 업로드 하길 원하는 spring boot server image id를 기억해둔다.
docker image tag {이미지 id} {변경할 이미지명} 명령어를 통해 이미지 tag명을 변경 해 복사 한 후
docker push {변경 된 이미지 명} 명령어를 통해 hub에 push한다.

업로드 할 이미지 명을 repository명 과 동일하게 설정 해줬기 때문에 정상적으로 push 되었다면 repository명으로 pull 할 수 있다.

기존의 Spring Boot 프로젝트를 local 환경에서 작성 해왔기 때문에 모든 url이 local로 잡혀 있었다.
url: jdbc:mysql://localhost:3306/mere_test?useSSL=false&serverTimezone=Asia/Seoul
mysql, rabbitmq, redis 등 container가 분리된 환경이라
url: jdbc:mysql://mysql:3306/mere_test?useSSL=false&serverTimezone=Asia/Seoul 와 같이 host를 지정 해줘야 한다고 생각했었다.
host를 지정한 application.yml 파일과 지정하지 않은 파일을 비교 해보니 정상 작동 했었다.
host를 지정하지 않아도 정상 작동 한 원인은 동일한 network를 설정 했기에 container간 local 접근이 가능 하기 때문이다.
version: '3.2'
services:
server:
image: {docker hub에 업로드한 이미지 명}
container_name: dev_merona_spring_boot ## 컨테이너 이름
restart: always # 매번 프로젝트를 다시 실행한다.
environment:
SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/{database 명}?useSSL=false&allowPublicKeyRetrieval=true
SPRING_DATASOURCE_USERNAME: {USERNAME}
SPRING_DATASOURCE_PASSWORD: {PASSWORD}
SPRING_REDIS_HOST: redis
SPRING_REDIS_PORT: 6379
SPRING_RABBITMQ_HOST: rabbitmq
SPRING_RABBITMQ_PORT: 5672
SPRING_RABBITMQ_USERNAME: guest
SPRING_RABBITMQ_PASSWORD: guest
spring.profiles.active: local ## 스프링 active profile 설정
ports:
- 9091:9091
depends_on:
- mysql
- redis
- rabbitmq
networks:
- dev_merona
rabbitmq:
image: rabbitmq:3.12.11-management
hostname: rabbitmq
container_name: dev_merona_rabbitmq
restart: unless-stopped
environment:
- RABBITMQ_DEFAULT_USER=guest
- RABBITMQ_DEFAULT_PASS=guest
ports:
- 5672:5672
- 15672:15672
networks:
- dev_merona
# rabbit image 버전 3.12.11
# 5672작동 , 15672 시각화
mysql:
container_name: dev_merona_mysql
image: mysql:8.0.22
environment:
MYSQL_DATABASE: {database 명}
MYSQL_ROOT_PASSWORD: {PASSWORD}
MYSQL_ROOT_HOST: '%'
# MySQL root 계정이 어떤 호스트에서든지 접근 가능하도록 설정
TZ: 'Asia/Seoul'
# 컨테이너의 시간대를 'Asia/Seoul'로 설정.
ports:
- 3306:3306
# 호스트의 3306 포트와 컨테이너의 3306 포트를 연결
volumes:
- ./mysql-file/dev_merona_mere.sql:/docker-entrypoint-initdb.d/dev_merona_mere.sql
#mysql 덤프 파일
networks:
- dev_merona
restart: always
redis:
container_name: dev_merona_redis
image: redis:6.2.5
command: redis-server
restart: always
networks:
- dev_merona
ports:
- 6379:6379
volumes:
elasticsearch:
networks:
dev_merona:
#네트워크 명
#동일한 네트워크를 설정
driver: bridge


ec2 puplic ip에서 정상적인 swagger의 작동을 확인 할 수 있었으며 CPU 사용률 역시 swap메모리를 적용한 이후 안정된 모습을 보여줬다.
프로젝트가 마무리 되어가는 이 시점에서, 지금까지 미루고 있던 EC2 배포 작업에 손을 대게 되었다.
배포를 시도하는 과정에서 Docker 설정과 관련된 에러가 발생하여 상당히 많은 시간을 소비하게 되었는데 원인은 Docker에 대한 기본적인 이해가 부족하여 필요한 설정을 보충할 필요성이 있었기 때문이다.
YouTube와 Google 등에서 많은 정보를 얻을 수 있었지만, 그 정보를 프로젝트에 맞게 적용하고 이해하는 과정은 여전히 험난했다.
지금 생각해 보면 docker hub를 사용하지 않고도 spring boot 프로젝트를 통째로 옮겨준 다음 jar로 변환 해줄 수도 있었을 것 같다.
당시에는 ec2 환경이 익숙하지 않아 local에서 최대한 많은 작업을 한 후 ec2에서 실행만 하려 했었디.
지금도 ec2 환경이 익숙하지는 않다.
프리티어를 사용하는 t2.micro 용량으로는 프로젝트 규모를 감당하지 못했다.
sudo docker-compose up -d 명령어를 실행하면 서버가 뻗어버리고 명령어 입력도 되지 않아 인스턴스 삭제 및 재생성도 굉장히 많이 했다.
아직 팀원들의 작업이 모두 완료되지 않아 모든 작업물을 배포해 보지는 못해서 아쉽지만 배포를 경험했다는 것에 의미를 두고 싶다.
docker hub upload : https://yeko90.tistory.com/entry/how-to-upload-image-in-docker-hub