🐳 Docker

Docker를 활용해 AWS EC2에 Spring Boot 배포하기 (feat. Nginx)

MNY 2024. 10. 1. 12:47
728x90
반응형
Keyword
  1. docker
  2. dockerfile
  3. compose(app, db)
  4. nginx(react deploy) -> 현재 적용되지 않은 사안
  5. nginx(reverse proxy)

 

 Docker 이란? 

왜 사용할까? (장점)

  • 환경 일관성: 개발, 테스트, 프로덕션 환경에서 동일한 컨테이너 이미지를 사용하기 때문에 "내 로컬에서는 잘 돌아가는데..." 같은 문제가 발생하지 않습니다.
  • 이식성: 컨테이너는 운영체제에 독립적이기 때문에, 어디에서나 동일하게 동작합니다. AWS, GCP, Azure 등 어떤 클라우드 환경에서도 동일한 컨테이너를 실행할 수 있습니다.
  • 신속한 배포: 애플리케이션과 종속성을 하나의 패키지로 묶어 배포하기 때문에, 새로운 환경에서 빠르게 애플리케이션을 배포할 수 있습니다.

 

핵심 개념

  • 컨테이너: 소프트웨어와 그 실행에 필요한 모든 것(코드, 라이브러리, 설정 파일 등)을 포함한 독립된 패키지.
  • 이미지: 컨테이너를 만들기 위한 설계도. 이미지를 기반으로 여러 개의 컨테이너를 생성할 수 있음.
  • 레지스트리: Docker 이미지를 저장하고 배포하는 저장소입니다. Docker Hub가 대표적인 예시.
  • 가상화와의 차이점: Docker는 OS 레벨에서 격리된 환경을 제공하기 때문에 가상 머신보다 더 가볍고 빠르게 동작합니다.

 

 Dockerfile 만들기 

프로젝트 디렉토리 구조

: 프로젝트의 루트 디렉토리에 위치

today-space-back/
├── build.gradle
├── settings.gradle
├── src/
│   └── main/
│       ├── java/com/complete/todayspace
│       │   └── Application.java
│       └── resources/
│           └── application.properties
└── Dockerfile

 

Dockerfile 만들기

: 검색 keyword → Springboot Dockerfile

# Use an official OpenJDK runtime as a parent image
FROM openjdk:17-jdk-slim

# Set the working directory in the container
WORKDIR /app

# Copy the project’s build artifact (JAR file) to the container
COPY build/libs/*.jar app.jar

# Make port 8080 available to the world outside this container
EXPOSE 8080

# Run the JAR file
ENTRYPOINT ["java", "-jar", "app.jar"]

 

프로젝트 빌드 및 이미지 푸시

// 1. Project build
./gradlew clean build

/* 
zsh: permission denied: ./gradlew 발생
chmod +x ./gradlew // 해당 명령어로 실행 권한 추가 후 다시 빌드
*/

// 2. Docker image build
docker build -t [docker account ID]/[project name] .
ex) docker build -t ysy561356/today-space-back .
// -t, --tag: 빌드된 이미지에 태그를 지정. 이미지이름:태그 형식으로 사용.

// 3. Docker image push
docker push [docker account ID]/[project name]
ex) docker push ysy561356/today-space-back
/*
denied: requested access to the resource is denied 발생
참고 자료: https://nirsa.tistory.com/53
*/

 

1. 인텔리제이에서 터미널 열고 프로젝트 빌드(window & mac)

 

2 & 3. Dockerhub 확인

 

 EC2 생성 

EC2 인스턴스 설정

EC2 인스턴스 생성:

  • AWS 콘솔에 로그인하고 EC2 서비스를 선택합니다.
  • "인스턴스 시작" 버튼을 클릭하여 새로운 인스턴스를 생성합니다.
  • Ubuntu AMI를 선택합니다.
  • 인스턴스 유형 & 용량을 선택합니다.
    • t2.micro & 30GB까지는 무료 티어로 사용할 수 있습니다.
  • 키 페어를 설정하고 다운로드합니다.
  • 인스턴스를 시작합니다.

보안 그룹 설정:

  • SSH (포트 22), HTTP (포트 80), HTTPS (포트 443) 및 애플리케이션 포트 (예: 8080)를 허용합니다.

 

EC2 인스턴스에 접속 (2가지 방법)

1번 방법 : 터미널을 사용하여 EC2 인스턴스에 접속 → mac 추천(window는 짜증날 수 있음)

  • 다운로드한 키 페어 파일(.pem)을 사용하여 SSH를 통해 EC2 인스턴스에 접속합니다.
  • 터미널을 열고 다음 명령을 실행합니다:
chmod 400 your-key-pair.pem
ssh -i "your-key-pair.pem" ubuntu@your-ec2-public-ip
  • your-key-pair.pem은 다운로드한 키 페어 파일의 이름으로, your-ec2-public-ip는 EC2 인스턴스의 퍼블릭 IP 주소입니다.

2번 방법 : AWS의 EC2 Instance Connect을 사용하여 연결 → window 추천(그냥 쉬움)

  • 생성한 EC2에서 연결을 클릭합니다.
  • EC2 인스턴스 연결 화면에서 다시 연결을 클릭합니다.

  • 다음과 같은 화면이 나오면 연결 성공입니다.

 

 EC2 기본 세팅 

시스템 업데이트 및 업그레이드

sudo apt update -y
sudo apt upgrade -y

 

Docker 및 Docker Compose 설치

  • Docker 설치:
sudo apt install -y docker.io
sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker $USER

 

Docker Compose 설치:

sudo apt install -y curl
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

 

Docker 및 Docker Compose 설치 확인:

docker --version
docker-compose --version

 

EC2 재시작:

// 1번 방법 : 터미널을 사용하여 EC2 인스턴스에 접속
exit
ssh -i "your-key-pair.pem" ubuntu@your-ec2-public-ip

// 2번 방법 : AWS의 EC2 Instance Connect을 사용하여 연결
해당 페이지 새로고침

 

 프로젝트(Docker image) 업로드 

* 해당 과정은 EC2 인스턴스에서 진행

 

Docker image pull

Docker image pull:

docker pull [docker account ID]/[project name]:tag
ex) docker pull ysy561356/today-space-back:latest
// tag를 따로 지정하지 않았다면 기본적으로 latest

 

Docker image 확인:

docker images

 

 

 Docker Compose 실행 

* 해당 과정은 EC2 인스턴스에서 진행

app.conf(nginx.conf) 작성

디렉토리 만들기:

mkdir data/nginx // 꼭 해당 위치로 안해도 됌
/* 
permisson denied 발생
sudo mkdir data/nginx // root 권한으로 생성
*/

cd ./data/nginx // 해당 파일로 이동

 

app.conf 파일 작성:

* app.conf 생성 경로

  • pwd 명령어로 현재의 경로 확인
  • 전체 경로 : home/ubuntu/data/nginx
  • 상대 경로(home/ubuntu 기준) : ./data/nginx
    * home/ubuntu 경로는 EC2 인스턴스에 로그인하자마자 나오는 경로이며, 표시되지 않을 수 있음
vi app.conf // app.conf 파일 생성하기

i // 작성 모드

// app.conf 파일 내용
server {
    listen 80;
    server_name today-space.kro.kr;

    location / {
        proxy_pass http://app:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

------------------------------------------------------------------------------------

ESC(버튼) + :wq // 작성 모드 종료 후 저장하고 나가기
w // 저장
q // 나가기

 

Docker Compose 만들기

Docker Compose 작성:

* docker-compose.yml 생성 경로

  • pwd 명령어로 현재의 경로 확인
  • 전체 경로 : home/ubuntu
vi docker-compose.yml // app.conf 파일 생성하기

i // 작성 모드

// docker-compose.yml 파일 내용

version: '3.8'

services:
  app:
    image: today-space-back:latest
    container_name: today-space-back
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - DB_URL=${POSTGRES_URL}
      - DB_USERNAME=${POSTGRES_USER}
      - DB_PASSWORD=${POSTGRES_PASSWORD}
      - JWT_SECRET_KEY=${JWT_SECRET_KEY}
      - JWT_ACCESS_TOKEN_EXPIRATION=${JWT_ACCESS_TOKEN_EXPIRATION}
      - JWT_REFRESH_TOKEN_EXPIRATION=${JWT_REFRESH_TOKEN_EXPIRATION}
    depends_on:
      - db

  db:
    image: postgres:14
    container_name: today-space-db
    environment:
      - POSTGRES_DB=${POSTGRES_DB}
      - POSTGRES_USER=${POSTGRES_USER}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
      
  nginx:
	 image: nginx:latest
	 container_name: today-space-nginx
	 ports:
		 - "80:80"
	 volumes:
		 - ./data/nginx/app.conf:/etc/nginx/conf.d/default.conf
	 depends_on:
		 - app

volumes:
  db_data:
  
------------------------------------------------------------------------------------
  
ESC(버튼) + :wq // 작성 모드 종료 후 저장하고 나가기
w // 저장
q // 나가기

 

application-secrets.yml:
* inteliJ에 포함되어야 하는 내용

POSTGRES_URL : // ex: jdbc:postgresql://today-space-db:5432/space
POSTGRES_DB : // ex: space
POSTGRES_USER : // 작성
POSTGRES_PASSWORD : // 작성

JWT_SECRET_KEY: // 작성
JWT_ACCESS_TOKEN_EXPIRATION: // 작성
JWT_REFRESH_TOKEN_EXPIRATION: // 작성

 

배포 완료 된 거 확인하기:

  • 브라우저 통해서 접근
http://your-ec2-public-ip
// 페이지 들어가면 인증/인가 때문에 401 response로 뜨는데 그러면 완료된 것

 

  • docker container 확인
docker ps
// 2개의 container이 제대로 동작하고 있어야 함

 

  • 포트 확인
curl -I http://localhost:8080
// 아래의 사진과 같이 동작되었다면 완료된 것

 

  • EC2에서 Docker Compose 재실행(선택):
    이미 실행 중인 Docker Compose를 중지한 후 다시 시작합니다.
docker-compose down // 중지
docker-compose up -d // 백그라운드에서 시작

 

 참고자료 

  • 프로젝트 빌드에서 참고
 

리눅스 권한 설정 (chmod, chown, chgrp)

1. 파일 권한 확인 ls -al 2. 파일 권한 설정 -rw-r--r-- 1 root root 0 2월 24 16:20 testfile2 testfile2파일의 소유자는 root이고 권한은 소유자(읽기/쓰기)권한, 그룹(읽기)권한, 다른 사용자(읽기)권한 - 파일표시

danmilife.tistory.com

 

  • docker container에서 참고 → 중복 port
 

🐧 리눅스 주요 포트 번호 종류

리눅스 포트 자주 쓰이는 포트 종류를 표로 나열해 보았다. 보라색으로 강조된 부분만 봐도 충분하다. 이밖의 자세한 포트 종류들은 리눅스 디렉토리 /etc/services 에서 확인할 수 있다. 윈도우 포

inpa.tistory.com

 

기술자료실-[Linux] 리눅스 방화벽 firewalld의 소개 및 활용

서버몬 HPE, LENOVO(=IBM), DELL, 슈퍼마이크로 서버, 기업용 PC, 스토리지 및 소프트웨어 (MS, 레드햇, 오라클), 문서보안솔루션(시큐어디스크, 인터넷디스크) 을 유통 판매하는 IT 통합솔루션 전문 회사

www.servermon.kr

 

  • aws 방화벽에서 참고
 

리눅스 네트워크 포트 상태 확인

만일 웹 서버를 생성하고, 데몬(Daemon)프로세스로 실행하여 웹 서비스를 개시하려고 할때, 현재 시스템의 네트워크 포트 상태를 확인할 필요가 있다. (만약 서버의 포트로 지정된 번호가 이미 사

bumday.tistory.com

 

  • dockerfile에서 참고
 

[Docker] 도커 파일 생성하고 업로드하기

도커 이미지 파일을 생성하는법, DockerHub에 push하는 법을 매우 쉽게 설명한다.

velog.io

 

  • docker compose에서 참고
 

[Docker] 도커 컴포즈(Docker compose) - 개념 정리 및 사용법

이번 포스트에서는 도커 컴포즈에 대해 정리하겠습니다. 도커 컴포즈란? 도커 컴포즈는 단일 서버에서 여러개의 컨테이너를 하나의 서비스로 정의해 컨테이너의 묶음으로 관리할 수 있는 작업

seosh817.tistory.com

 

728x90
반응형