EC2에 Docker로 스프링 부트 애플리케이션 배포하기

유방현·2025년 2월 20일

사전 준비사항

  • AWS 계정
  • 스프링 부트 애플리케이션
  • 기본적인 VPC 구성
  • CloudFront와 S3 연동 설정

목차

  1. EC2 인스턴스 생성
  2. EC2 기본 설정
  3. Docker 설치
  4. 스프링 부트 애플리케이션 Docker 설정
  5. 배포 프로세스
  6. 운영 관리
  7. 추가 고려사항

1. EC2 인스턴스 생성

AMI 선택

  • Amazon Linux 2 AMI 선택
    • 안정성이 검증된 AWS 공식 이미지
    • AWS 서비스들과의 호환성이 뛰어남

인스턴스 유형

  • 개발/테스트 환경: t2.micro 또는 t3.micro (프리티어 사용 가능)
  • 프로덕션 환경: 애플리케이션 요구사항에 따라 선택

네트워크 설정

  • VPC 선택
  • 퍼블릭 서브넷 선택 (외부 접근 필요)

보안 그룹 설정

- SSH (22번 포트): 관리자 IP
- HTTP (80번 포트): 0.0.0.0/0
- HTTPS (443번 포트): 0.0.0.0/0
- 애플리케이션 포트 (8080): 필요한 IP 대역

2. EC2 기본 설정

서버 초기 설정을 위한 명령어입니다:

# 시스템 업데이트
sudo yum update -y

# 서울 타임존 설정
sudo rm /etc/localtime
sudo ln -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

3. Docker 설치

Docker 설치 및 기본 설정:

# Docker 설치
sudo yum install -y docker

# Docker 서비스 시작
sudo systemctl start docker

# 시스템 재시작시 자동 시작 설정
sudo systemctl enable docker

# 현재 사용자에게 docker 권한 부여
sudo usermod -aG docker $USER

# 권한 적용을 위해 재접속
exit

4. 스프링 부트 애플리케이션 Docker 설정

Dockerfile 작성

프로젝트 루트 디렉토리에 다음 내용으로 Dockerfile을 생성합니다:

FROM openjdk:17-jdk-slim

WORKDIR /app

COPY build/libs/*.jar app.jar

EXPOSE 8080

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

.dockerignore 설정

불필요한 파일이 이미지에 포함되는 것을 방지합니다:

.git
.gradle
.idea
build
!build/libs/*.jar

5. 배포 프로세스

방법 1: 직접 EC2에 소스코드 복사 후 빌드

# 로컬에서 EC2로 JAR 파일 복사
# Windows의 경우
scp -i "C:\Users\사용자이름\Downloads\키페어이름.pem" \
    프로젝트경로/build/libs/*.jar \
    ec2-user@ec2-xx-xx-xx-xx.region.compute.amazonaws.com:/home/ec2-user/app

# Linux/Mac의 경우
scp -i "~/.ssh/키페어이름.pem" \
    ./build/libs/*.jar \
    ec2-user@ec2-xx-xx-xx-xx.region.compute.amazonaws.com:/home/ec2-user/app

# EC2 접속
ssh -i "키페어.pem" ec2-user@EC2_IP

# Docker 이미지 빌드 및 실행
cd app
docker build -t springapp .
docker run -d -p 8080:8080 --name springapp springapp

방법 2: Docker Hub 활용

# 로컬에서 실행
docker build -t 사용자명/springapp .
docker push 사용자명/springapp

# EC2에서 실행
docker pull 사용자명/springapp
docker run -d -p 8080:8080 --name springapp 사용자명/springapp

6. 운영 관리

주요 Docker 명령어

# 컨테이너 상태 확인
docker ps -a

# 컨테이너 로그 확인
docker logs springapp

# 컨테이너 중지/시작/재시작
docker stop springapp
docker start springapp
docker restart springapp

자동 재시작 설정

docker run -d \
  --restart unless-stopped \
  -p 8080:8080 \
  --name springapp \
  springapp

7. 추가 고려사항

모니터링

  • Amazon CloudWatch 설정
    • 시스템 메트릭 모니터링
    • 컨테이너 로그 수집

보안 강화

  • SSL/TLS 인증서 적용 (AWS Certificate Manager)
  • VPC 보안 그룹 규칙 최적화
  • WAF 설정 검토

CloudFront 연동

  • EC2를 CloudFront의 오리진으로 추가
  • 정적 리소스는 S3, API는 EC2로 라우팅

마무리

이상으로 EC2에 Docker를 사용하여 스프링 부트 애플리케이션을 배포하는 방법에 대해 알아보았습니다. 실제 운영 환경에서는 위 내용을 기반으로 하되, 보안, 가용성, 확장성 등을 추가로 고려하여 구성하시기 바랍니다.

8. Nginx 설정

EC2에 Nginx 설치

# Nginx 설치
sudo yum install nginx -y

# Nginx 시작
sudo systemctl start nginx

# 시스템 부팅시 자동 시작 설정
sudo systemctl enable nginx

# Nginx 상태 확인
sudo systemctl status nginx

Nginx 기본 설정

기본 설정 파일 위치: /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;
}

스프링 부트 애플리케이션 연동 설정

/etc/nginx/conf.d/app.conf 파일 생성:

server {
    listen 80;
    server_name your_domain.com;

    access_log /var/log/nginx/app.access.log;
    error_log /var/log/nginx/app.error.log;

    location / {
        proxy_pass http://localhost: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;
    }
}

SSL 설정 (HTTPS)

server {
    listen 443 ssl;
    server_name your_domain.com;

    ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://localhost: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;
    }
}

Nginx 관리 명령어

# 설정 문법 검사
sudo nginx -t

# Nginx 재시작
sudo systemctl restart nginx

# 설정 리로드 (무중단)
sudo nginx -s reload

# 로그 확인
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log

성능 최적화 설정

# Worker 프로세스 설정
worker_processes auto;
worker_rlimit_nofile 65535;

# Keepalive 설정
keepalive_timeout 65;
keepalive_requests 100;

# Gzip 압축 설정
gzip on;
gzip_comp_level 5;
gzip_min_length 256;
gzip_proxied any;
gzip_vary on;
gzip_types
    application/javascript
    application/json
    application/x-javascript
    application/xml
    text/css
    text/javascript
    text/plain
    text/xml;

# 버퍼 크기 설정
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;

# 타임아웃 설정
client_body_timeout 12;
client_header_timeout 12;
send_timeout 10;

0개의 댓글