Vapor Elastic Beanstalk 배포기
- Vapor
- Docker
- AWS
- EC2
🛫 ## 목표
git push를 통해 자동 배포(CI/CD)를 시키는 것Github → Github Actions → AWS Elastic Beanstalk → EC2 Upload
→ Elastic Beanstalk이 자동으로 EC2를 생성
→ Github Actions이 Elastic Beanstalk로 Vapor의 Build Zip 업로드
→ Elastic Beanstalk은 받은 Zip 파일을 EC2로 던져서 배포 진행
목표
git push를 통해 자동 배포(CI/CD)를 시키는 것
Github → Github Actions → AWS Elastic Beanstalk → EC2 Upload
→ Elastic Beanstalk이 자동으로 EC2를 생성
→ Github Actions이 Elastic Beanstalk로 Vapor의 Build Zip 업로드
→ Elastic Beanstalk은 받은 Zip 파일을 EC2로 던져서 배포 진행
1. IAM에서 역할 생성하기

1-1. 역할 생성

1-2. 사용 사례 선택

- 신뢰할 수 있는 엔터티 유형 →
AWS 서비스설정 - 사용사례 →
EC2지정
1-3. 환경 설정

🤔 왜 정책 설정을 해야하지?
→ EC2가 AWS 리소스에 접근하기 위해선 필수다!
- 역할 이름 :
aws-elasticbeanstalk-ec2-role - AWSElasticBeanstalkWebTier → Web 서버가 가져야하는 기본 권한
- AWSElasticBeanstalkWorkerTier → Worker 환경일 때 사용하는 큐, 백그라운드 처리 권한
- AWSElasticBeanstalkMulticontainerDocker → Docker 기반 EB 환경에서 필수적
- 역할 설명 : Elastic Beanstalk assigns this role to EC2 instances so they can access the necessary AWS resources while running within the environment. (Elastic Beanstalk 환경에서 실행되는 EC2 인스턴스가 AWS 내부 리소스에 접근할 수 있도록 부여하는 역할입니다.)
2. Elastic Beanstalk 환경 설정하기


2-1. 환경 구성하기

- 환경 티어 :
웹 서버 환경 - 애플리케이션 정보(이름) :
iOS06-BangBang-Vapor - 환경 정보(이름) :
IOS06-BangBang-Vapor-env - 플랫폼 :
Docker - 브랜치 :
Docker running on 64bit Amazon Linux 2023 - 버전 :
4.8.0 - 애플리케이션 코드 :
샘플 애플리케이션 - 사전 설정 :
단일 인스턴스(프리티어)
2-2. 서비스 액세스 구성

- EC2 인스턴스 프로파일 :
1-3. 환경 설정에서 설정한 IAM 인스턴스(역할) 입력
2-3. 인스턴스 트래픽 및 크기 조정 구성

- 루트 볼륨 유형 :
컨테이너 기본값 10GiB - 인스턴스 모니터링 : 5분 간격, 기본값
- IMDSv1: 비활성화
- EC2 보안 그룹 : 현재 시점에선 비활성화, 추후
8080과443만 인바운드로 오픈하기 - 용량 : 단일 인스턴스(프리티어)
- 아키텍처 :
x86_64 - 인스턴스 유형
- 1순위 :
t3.micro→ 12월 4일 기준 t3.미디움으로 수정 - 2순위 :
t3.small

3. Elastic Beanstalk 초기화
❗아래 작업은 로컬 환경에서 진행할 것
3-1. Vapor 프로젝트를 Elastic Beanstalk로 지정하기
그 전에 root 계정이 아니라 반드시
배포 전용 IAM User의 계정을 활용한다.
IAM User를 생성한 뒤 최소한의 권한을 부여한 뒤 Access Key와 Secret Access Key를 저장한다. (절대 노출 금지) → AWS IAM 자격증명에 활용된다.
# AWS CLI 설치
brew install awscli
# AWS IAM 자격증명 설정
aws configure
# AWS Access Key ID [None]: {IAM User 엑세스 키)
# AWS Secret Access Key [None]: {IAM User 시크릿 엑세스 키)
# Default region name [None]: ap-northeast-2 # 대한민국 리전
# Default output format [None]: json # json 포맷
# Elastic Beanstalk CLI 설치
brew install awsebcli
# Vapor 프로젝트로 이동
cd BANGBANG_Server
# Elastic Beanstalk 초기화
eb init
# Select a default region
#(default is 3): 10 -> 10번은 대한민국 리전
# Select an application to use
# 1) iOS06-BangBang-Vapor
# 2) [ Create new Application ]
# (default is 2): 1 -> AWS Console에서 미리 설정한 Elastic Beanstalk 로드
- 그 후 생성된
config.yml
# .elasticbeanstalk/config.yml
branch-defaults:
default:
environment: IOS06-BangBang-Vapor-env
environment-defaults:
IOS06-BangBang-Vapor-env:
branch: null
repository: null
global:
application_name: iOS06-BangBang-Vapor
default_ec2_keyname: null
default_platform: Docker running on 64bit Amazon Linux 2023
default_region: ap-northeast-2
include_git_submodules: true
instance_profile: null
platform_name: null
platform_version: null
profile: null
sc: null
workspace_type: Application
3-2. Elastic Beanstalk에 Docker 기반 Vapor 배포하기
이미 Vapor로 생성된 프로젝트 루트에는 _
Dockerfile_과 _docker-compose.yml_같은 세팅이 전부 되어있다.
EB는 이 도커파일을 자동으로 읽고 배포함으로Dockerfile이 서버 프로젝트 루트에 있는지 반드시 확인할 것.
# Dockerfile 유무 확인, EB 연결 확인 후 배포
eb deploy
# 1. 로컬 코드를 Zip으로 압축한 뒤 EB에 업로드 진행
# 2. EB가 Dockerfile 기반으로 이미지를 빌드
# 3. EC2 인스턴스 재시작
# 4. Vapor 서버 run
3-3 ❗(트러블슈팅) FileTooLargeError
eb deploy
위 deploy 명령을 실행하니 아래와 같이 오류가 발생하였다.
ERROR: FileTooLargeError - Archive cannot be any larger than 512MB
이는 빌드 결과물(Zip)이 512BM을 초과하였을 때 발생되는 에러 메세지다.
현지 시점에서 빌드된 zip 파일의 크기를 확인하니 1.32GB가 나왔다.
_Elastic Beanstalk_는 업로드 가능한 애플리케이션의 ZIP 최대 크기가 512MB로 제한된다.
- 현재 Dockerfile이 “로컬에서 Vapor”빌드를 전부 진행한 뒤
빌드된 실행 파일까지 전부 포함한 채로EB에 업로드되고 있어서 EB가512MB가 넘었으니 못한다.하고 거부하는 것으로 이해했다. - 따라서
.build파일이나 바이너리 파일을 제외한 소스 코드 자체만 EB에 올라가도록.ebignore파일을 생성해서 적용한다.
🤔 **`.`**`ebignore`이란?
.gitignore과 .ebignore은 완전 별개의 파일이므로 유의한다.
.ebignore는 AWS Elastic Beanstalk의 EB CLI에서 사용하는 파일- 프로젝트 디렉터리 내에서 특정 파일이나 폴더를 배포 시
무시하도록 지정한다. - 즉, EB CLI가 소스 번들을 생성할 때 _
.ebignore_에 명시된 파일들은 포함하지 않고 빌드한다!!
EB CLI 구성 - AWS Elastic Beanstalk
# ============================
# Git & IDE
# ============================
.git/
.gitignore
.vscode/
.idea/
.DS_Store
# ============================
# Build Artifacts (SwiftPM)
# ============================
.build/
*.swiftpm
DerivedData/
# ============================
# Xcode Project
# ============================
*.xcodeproj/
*.xcworkspace/
# ============================
# Logs & Temp
# ============================
*.log
*.sqlite
db.sqlite
# ============================
# Docker (로컬용만 제외)
# ============================
Dockerfile.local
docker-compose.yml
# ============================
# Elastic Beanstalk
# ============================
# 기본적으로 EB 설정 디렉토리는 제외
.elasticbeanstalk/*
# 단 아래 2개 파일은 포함
!.elasticbeanstalk/config.yml
!.elasticbeanstalk/*.global.yml
# ============================
# Tests (배포에 불필요)
# ============================
Tests/
# ============================
# Mac spotlight trash
# ============================
.Spotlight-V100
.Trashes
eb deploy
# Creating application version archive "app-251204_011137138635".
# Uploading iOS06-BangBang-Vapor/app-251204_011137138635.zip to S3. This may take a while.
# Upload Complete.
# 2025-12-03 16:11:38 INFO Environment update is starting.
# 2025-12-03 16:12:02 INFO Deploying new version to instance(s).
# -- Events -- (safe to Ctrl+C) Use "eb abort" to cancel the command.
3-4. ❗(트러블슈팅, 해결 실패) FileTooLargeError
db deploy
# ... ERROR Instance deployment failed. For details, see 'eb-engine.log'.
# ... ERROR Instance deployment failed to build the Docker image. The deployment failed.
# ServiceError - Failed to deploy application.
이럴수가.. 또 에러가 발생했다.
로그(eb-engine.log)를 확인하기 위해선 EC2에 접근할 수 있어야 하는데 현재 EC2 키페어가 설정되어있지 않으므로 EB의 환경 구성에 EC2 키페어를 추가한다.

그 후 eb logs를 통해 에러를 확인하니 아래와 같이 나왔다…
8.007 error: 'build': target 'BANGBANG_ServerTests' has overlapping sources
17 ERROR: process "/bin/sh -c swift build -c release
--product BANGBANG_Server
--static-swift-stdlib
-Xlinker -ljemalloc && cp \"$(swift build -c release --show-bin-path)/BANGBANG_Server\" /staging && find -L \"$(swift build -c release --show-bin-path)\" -regex '.*\\.resources$' -exec cp -Ra {} /staging \\;"
did not complete successfully: exit code: 1
------
- 해당 오류는
SPM가 프로젝트를 빌드할 때 타겟 간 소스 파일 경로가중복(overlapping)되어 발생하는 오류라고 한다..(이게 무슨 소리지) - 즉, 어디선가 중복 경로가 발생하고 있다는것 이며 오류메세지를 확인하니
테스트 타겟(BANGBANG_ServerTests)이 메인 타겟(BANGBANG_Server)과 동일한 소스 파일을 포함하고 있다고 나오고 있었다. - 제일 유력한
Package.swift파일.testTarget에 명시적으로 경로를 지정해보았다.
// BANGBANG_Server/Package.swift
.testTarget(
name: "BANGBANG_ServerTests",
dependencies: [
.target(name: "BANGBANG_Server"),
.product(name: "VaporTesting", package: "vapor"),
],
path: "Tests/BANGBANG_ServerTests", // 명시적으로 경로 지정
swiftSettings: swiftSettings
)
하지만 여전히 에러가 뜬다…
다시 한 번 에러메세지를 확인해보았다.
error: 'build': invalid custom path 'Tests/BANGBANG_ServerTests'
for target 'BANGBANG_ServerTests'
테스트 경로가 없다는 것이었는데.. 생각해보니까 .ebignore에서 Tests/를 제외하고 있었다..!!!
# ============================
# Tests (배포에 불필요)
# ============================
Tests/
아.. 내 2시간
.ebignore에서Tests/를 제거하였다.- 또한, 현재 Dockerfile에는 데이터베이스 마이그레이션 스크립트가 존재하지 않는 상태여서 아래와 같이 마이그레이션 스크립트를 추가하였다.
RUN echo '#!/bin/bash\n\
set -e\n\
echo "Running migrations..."\n\
./BANGBANG_Server migrate --yes || echo "Migration failed or already up to date"\n\
echo "Starting server..."\n\
exec ./BANGBANG_Server serve --env production --hostname 0.0.0.0 --port 8080' > /app/start.sh && \
chmod +x /app/start.sh && \
chown vapor:vapor /app/start.sh
- 하지만 이번엔 아래와 같이
Timeout이 나버린다..
ERROR: TimeoutError - The EB CLI timed out after 10 minute(s). The operation might still be running. To keep viewing events, run 'eb events -f'.
- 아마 EC2의 인스턴스가 프리티어(t3.micro/t3.small)이어서 그런 거 같다..
- 하지만 t3.medium은 프리티어에선 사용할 수 없으므로 차라리 스토리지를 범용 gp3에 20기가를 할당해서 Swap으로 꼼수를 부려보자.
# 스왑 여부 확인 (아무것도 안나오면 가능)
sudo swapon --show
# 스왑 파일 생성 (2GB)
sudo fallocate -l 2G /swapfile
# 스왑 파일 권한 설정
sudo chmod 600 /swapfile
# 스왑 영역 초기화
sudo mkswap /swapfile
# Setting up swapspace version 1, size = 2 GiB (2147479552 bytes)
# 스왑 활성화
sudo swapon /swapfile
# 영구 적용
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# /swapfile none swap sw 0
# 스왑 여부 확인
free -h
- 하지만.. 여전히 타임아웃 오류가 발생해서.. 영빈님의 DockerHub 이용 작전으로 변경하려했지만..?

- 배포가 성공했다..! → CLI에서는 타임아웃이 떠도 실제 Console에서는 배포되는 경우가 많다고 한다.
