본문 바로가기
Projects/OpenRoadmaps

[OpenRoadmaps] 9. Docker 빌드 + AWS 배포하기

by DevJaewoo 2023. 2. 13.
반응형

우선 기능 구현은 잠시 보류하고, CI / CD를 위한 배포부터 먼저 하기로 했다.

배포 구상도는 다음과 같다.

배포 구상도

 

Backend는 EC2에, Frontend는 S3에 배포하고, NginX를 통해 SSL 인증과 사용자의 요청에 따른 프록시 작업을 수행한다.

/api 경로로 들어오는 요청은 Spring 컨테이너로 보내주고, 나머지는 S3으로 보내주게 설정했다.

HTTP 요청이 들어올 경우 HTTPS로 리다이렉트 시켜주도록 설정했다.


Docker 빌드

Backend는 Docker 이미지로 빌드해서 배포했다.

Docker-Compose로 묶은 채로 배포하고 싶었지만, 이미지를 빌드할 때 환경변수를 설정해야 하는데, Docker 이미지는 이를 plain text로 저장한다. 이런 값들은 노출되면 큰일나기 때문에, 환경변수는 서버에 두고 서버에서 환경변수를 통해 이미지를 새로 빌드하는 방식을 선택했다.

 

FROM openjdk:17-alpine
RUN mkdir -p /usr/app/backend
WORKDIR /usr/app/backend

COPY ./build/libs/*-SNAPSHOT.jar .

ENTRYPOINT [ "java", "-jar", "OpenRoadmaps-0.0.1-SNAPSHOT.jar"]
EXPOSE 8080

위와 같이 jar 파일을 복사해 실행만 해주는 간단한 Dockerfile을 만들어 이미지를 빌드했고, Hub에 배포했다.

 

https://hub.docker.com/repository/docker/devjaewoo/openroadmaps-develop/general

 

Docker

 

hub.docker.com

 

그 다음 Hub에서 Backend 이미지를 받아오고, Redis와 PostgreSQL과 함께 묶어서 실행하기 위해 docker-compose.yml을 작성했다.

version: "3"
services:

  # 세션 저장을 위한 Redis 컨테이너
  redis:
    image: redis:latest
    container_name: redis

  # Spring Backend 컨테이너
  backend:
    image: devjaewoo/openroadmaps-develop:latest

    container_name: backend
    ports:
      - 8080:8080
    environment:
      - SPRING_JPA_HIBERNATE_DDLAUTO=validate
      - SPRING_DATASOURCE_URL=jdbc:postgresql://database:5432/postgres # 내부 네트워크를 사용한다.
      - SPRING_DATASOURCE_USERNAME=${DATABASE_USERNAME}
      - SPRING_DATASOURCE_PASSWORD=${DATABASE_PASSWORD}
      - SPRING_REDIS_HOST=redis
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENTID=${GOOGLE_CLIENT_ID}
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENTSECRET=${GOOGLE_CLIENT_SECRET}
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GITHUB_CLIENTID=${GITHUB_CLIENT_ID}
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GITHUB_CLIENTSECRET=${GITHUB_CLIENT_SECRET}
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_REDIRECTURI=https://develop.openroadmaps.co.kr/api/{action}/oauth2/code/{registrationId}
      - SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GITHUB_REDIRECTURI=https://develop.openroadmaps.co.kr/api/{action}/oauth2/code/{registrationId}
      - SPRING_OAUTH2_SUCCESSURI=https://develop.openroadmaps.co.kr
      - FILE_ROOTDIR=/home/files/

    volumes:
      - /home/ubuntu/files:/home/files # 파일 볼륨 마운트

    depends_on: # Redis, Database 컨테이너가 실행된 이후에 Backend 컨테이너를 실행한다.
      - redis
      - database

  # Postgres DB 컨테이너
  database:
    image: postgres:latest
    container_name: database
    environment:
      - POSTGRES_USERNAME=${DATABASE_USERNAME}
      - POSTGRES_PASSWORD=${DATABASE_PASSWORD}
    volumes:
      - ./postgres:/var/lib/postgresql/data:rw

 

Backend, Redis, PostgreSQL 컨테이너를 묶어서 실행하지 않고 따로따로 실행해도 됐는데, 그럴 경우 컨테이너 관리가 힘들어진다. 또한 컨테이너 간 통신을 위해 포트를 열어놔야 하는데, 보안 관점에서 별로 좋지 않은것 같았다. 환경변수 등록도 번거롭다.

 

Docker Compose를 사용하면 up / down 명령어로 컨테이너들을 한번에 제어할 수 있고, 컨테이너 간 내부 네트워크를 사용해 외부에선 접근할 수 없기 때문에 해킹당할 위험이 낮아진다. 또한 .env 파일에서 환경 변수를 자동으로 가져오기 때문에 관리도 편하다.

 

이런 이유로 Docker Compose를 사용했고, 정상적으로 실행되는걸 확인할 수 있었다.

docker-compose 실행 결과


Backend 배포

백엔드는 EC2 컨테이너에 배포했다. 배포 과정에서 한 작업을 간단하게 요약하자면 다음과 같다.

 

  • EC2 Ubuntu 컨테이너 생성
  • SSH 키 다운로드 및 보안 그룹 인바운드 규칙 설정
  • Elastic IP 할당, 도메인 연결
  • SSH 접속 후 초기 세팅
  • Docker 설치 및 컨테이너 실행

 

우선 EC2 컨테이너를 생성하고, 아래와 같이 HTTP / HTTPS 포트를 열여놨다.

학교랑 집 PC의 SSH 접근도 허용으로 설정했다.

인바운드 규칙

 

그 다음 EC2 컨테이너가 실행될 때마다 IP 주소가 바뀌는걸 방지하기 위해 Elastic IP를 할당하고, 가비아에서 구매한 도메인을 해당 IP에 연결했다.

 

그 다음 발급받은 SSH 키를 통해 연결하고, Docker 공식 가이드를 따라 Docker 설치를 진행했다.

 

Install Docker Engine on Ubuntu

 

docs.docker.com

sudo apt-get -y update
sudo apt-get -y install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
    
sudo mkdir -m 0755 -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
  
sudo apt-get -y update
sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

sudo docker run hello-world

 

이후 docker-compose.yml과 .env 파일을 복사하고, sudo docker compose up을 통해 실행시켜 배포를 완료했다.


Frontend 배포

Frontend는 S3 버킷에 배포했다. 배포 과정이 생각보다 간단했다.

 

  • S3 버킷 생성 및 설정
  • React 빌드
  • S3 버킷에 빌드 결과물 업로드

 

아래와 같이 퍼블릭 액세스 차단을 해제하고, 정적 웹 사이트 호스팅을 활성화했다.

 

그 다음 아래 명령어로 Webpack 빌드를 진행하고,

npm run build

 

결과물을 업로드해 배포를 완료했다.


Backend, Frontend 각각은 배포됐고, 이제 NginX를 통한 프록시 작업과 SSL 인증을 적용해야 한다.

반응형