DevOps/AWS

[AWS] ECR + ECS(Fargate)로 웹 앱 배포하기 (Windows 환경 기준)

view9269 2025. 5. 20. 22:26

1. 준비 과정 (Windows 기준)

1-1. AWS 계정 생성 및 기본 설정

  • AWS  IAM 사용자 생성, AdministratorAccess 정책 부여
  • Access Key ID / Secret Key 발급

 

정책 부여 후 사용자 생성

 

 

 

액세스 키 발급 받기

 

액세스 키 발급 중 ..

 

발급 완료

 

 

 

1-2. AWS CLI 설치

aws --version

 

1-3. AWS CLI 설정

aws configure
  • AWS Access Key ID: IAM에서 발급받은 키
  • Default region name: 예) ap-northeast-2  (서울)
  • Default output format: :  json

1-4. Docker 설치 (Docker Desktop + WSL2)

wsl --install

 

docker --version

 

정상 설치 완료

 

2. Docker 이미지 만들기 및 ECR 푸시

2-1. Dockerfile 작성

# Dockerfile
FROM nginx:alpine
COPY ./index.html /usr/share/nginx/html/index.html

 


FROM nginx:alpine nginx 웹서버가 설치된 경량 alpine 리눅스를 기반 이미지로 사용
COPY 내가 만든 index.html 파일을 nginx의 웹 루트로 복사

 

2-2. index.html 작성

<!-- index.html -->
<h1>Hello</h1>

2-3. ECR Repository 생성

aws ecr create-repository --repository-name my-web-app

 

AWS에 이미지를 저장할 저장소(버킷) 을 만듬

 

출력되는 repositoryUri 는 나중에 Docker 이미지에 태그를 붙일 때 필요함.

 

 

2-4. ECR 로그인

aws ecr get-login-password | docker login --username AWS --password-stdin <<2-3에서 얻은 repositoryUri 값>>

 

🔗 저장소 주소 구성 방식

<계정 ID>.dkr.ecr.<리전>.amazonaws.com/<저장소 이름>

 

 


계정 ID 계정아이디
리전 ap-northeast-2 (서울)
저장소 이름 my-web-app
저장소 URI 계정아이디.dkr.ecr.ap-northeast-2.amazonaws.com/my-web-app

 

 

💡 AWS 계정 ID 확인하는 법:

aws sts get-caller-identity
 
 

2-5. 이미지 빌드 & 태깅 & 푸시

 

이미지 빌드

docker build -t my-web-app .

 

이미지 태깅

docker tag my-web-app:latest <계정 ID>.dkr.ecr.<리전>.amazonaws.com/my-web-app:latest

 

태깅은 "ECR 저장소 주소를 Docker 이미지에 붙여주는 작업

 

 

Docker 이미지 푸시 (업로드)

docker push <계정 ID>.dkr.ecr.<리전>.amazonaws.com/my-web-app:latest

 

 

생성 확인!

 

3. ECS 설정 (Fargate)

 

🧠 ECS 관련 핵심 개념 정리

ECS
(Elastic Container Service)
AWS에서 도커 컨테이너를 실행할 수 있게 도와주는 서비스
클러스터 (Cluster) 컨테이너들이 모여 있는 공간
(하나의 ECS 프로젝트라고 생각하면 돼)
태스크 정의 (Task Definition) 어떤 Docker 이미지를, 어떤 설정(CPU, 포트 등)으로 실행할지 작성한 설정파일
태스크 (Task) Task Definition을 실제로 실행한 인스턴스 (하나의 컨테이너)
서비스 (Service) 태스크(Task)를 몇 개 실행하고, 꺼지면 다시 켜주고, ALB랑 연결도 해주는 자동 관리자
Fargate AWS가 서버를 알아서 관리해주는 컨테이너 실행 방식
서버 설치/관리 필요 없음!

 

3단계 흐름

 

(1) 클러스터 생성         →  컨테이너가 실행될 공간 만들기
(2) 태스크 정의 작성      →  어떤 이미지로 컨테이너 만들지 정의
(3) 서비스 만들기         →  그걸 몇 개 돌릴지, 퍼블릭으로 공개할지 설정
(4) ALB 연결              →  URL로 접속 가능하게 만들기

 

 

✅ 3-1. 클러스터 생성 (PowerShell)

aws ecs create-cluster --cluster-name my-cluster
 

하나의 프로젝트 공간이라고 생각하면 됨. 나중에 서비스나 태스크는 여기서 관리됨.

 

 

✅ 3-2. IAM 역할 만들기 (ECS가 ECR 접근할 수 있도록)

 

아래 JSON을 trust-policy.json 이라는 이름으로 저장

 
{
  "Version": "2012-10-17",          // 정책 버전 (항상 이 값 사용)
  "Statement": [{
    "Effect": "Allow",              // 허용(Allow) 정책
    "Principal": {
      "Service": "ecs-tasks.amazonaws.com" // 이 역할을 누가 사용할 수 있냐? → ECS 태스크!
    },
    "Action": "sts:AssumeRole"      // 이 역할을 사용할 수 있는 권한 (역할 위임 허용)
  }]
}

 

 

powerShell에서 실행

 

aws iam create-role \
  --role-name ecsTaskExecutionRole \                        # 역할 이름 설정
  --assume-role-policy-document file://trust-policy.json    # 위에서 만든 신뢰 정책 파일 지정


aws iam attach-role-policy \
  --role-name ecsTaskExecutionRole \                            # 방금 만든 역할
  --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
  
  한줄로 실행
  
  aws iam create-role --role-name ecsTaskExecutionRole --assume-role-policy-document file://trust-policy.json

  aws iam attach-role-policy --role-name ecsTaskExecutionRole --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

 

 

 3-3. 태스크 정의 만들기

태스크 정의(Task Definition) 은 ECS에게
👉 “이 이미지로 컨테이너를 실행해줘”
👉 “CPU, 메모리, 포트는 이렇게 설정해줘”
같은 실행 방법을 알려주는 설정 파일(JSON) 

 

🧱 태스크 정의가 포함하는 내용들


항목 설명
containerDefinitions 어떤 컨테이너를 쓸지, 이미지 경로, 포트 등
cpu / memory 실행할 때 쓸 리소스
executionRoleArn ECR에서 이미지 가져오고 로그 쓰기 위한 IAM 역할
networkMode 네트워크 방식 (Fargate는 awsvpc 고정)
requiresCompatibilities Fargate로 실행한다는 뜻

task-def.json

{
  "family": "web-task",                   // 태스크 이름 (자유롭게 지정)
  "networkMode": "awsvpc",                // Fargate에서 꼭 필요한 네트워크 모드
  "requiresCompatibilities": ["FARGATE"], // 실행 방식: EC2 아님, Fargate임
  "cpu": "256",                           // CPU 할당량 (0.25 vCPU)
  "memory": "512",                        // 메모리 할당량 (512 MiB)
  "executionRoleArn": "arn:aws:iam::<계정ID>:role/ecsTaskExecutionRole", // ECR 접근용 IAM 역할
  "containerDefinitions": [
    {
      "name": "web",                      // 컨테이너 이름 (원하는 대로)
      "image": "<계정ID>.dkr.ecr.ap-northeast-2.amazonaws.com/my-web-app:latest", // ECR 이미지 주소
      "portMappings": [
        {
          "containerPort": 80            // 컨테이너 내부에서 열리는 포트 (nginx는 80 기본)
        }
      ]<계정ID>
    }
  ]
}

 

powershell 에서 실행

 

aws ecs register-task-definition --cli-input-json file://task-def.json

 

4. 퍼블릭 배포를 위한 VPC, 서브넷, 보안그룹, ALB, ECS 서비스 만들기

이 단계에서 만들 것

VPC 네트워크 공간
퍼블릭 서브넷 2개 Fargate 컨테이너가 실행될 네트워크 (서로 다른 AZ에 있어야 함)
보안 그룹 80포트 오픈 (인터넷 접속 허용)
ALB (Application Load Balancer) 사용자 요청을 컨테이너로 전달
ECS 서비스 실제로 Fargate에 태스크를 실행시킴

🧭 전체 흐름

 
[사용자 브라우저]
        ↓
[ALB - 80 포트]
        ↓
[보안 그룹 - 80 허용]
        ↓
[퍼블릭 서브넷에 있는 ECS 태스크 (Fargate)]
        ↓
[내가 만든 Docker 컨테이너 실행됨]

4-1. 퍼블릭 VPC + 서브넷 만들기 

▶ 1) VPC 생성

  1. AWS 콘솔 → VPC 서비스 이동
  2. 좌측 메뉴 VPC 대시보드 > VPC 만들기
  3. VPC 및 추가 리소스 선택
  4. 아래처럼 입력:

이름 태그 my-vpc
IPv4 CIDR 블록 10.0.0.0/16
퍼블릭 서브넷 개수 2 (서울 리전이면 2개 AZ 자동 분배됨)
NAT 게이트웨이 없음
탄력적 IP 체크 X
Auto-assign public IP 체크 (중요!)

 

 

 

4-2. 보안 그룹 만들기 (80포트 오픈)

  1. VPC > 보안 그룹 > 생성
  2. 이름: ecs-web-sg
  3. VPC: 위에서 만든 my-vpc
  4. 인바운드 규칙 추가
    • 유형: HTTP
    • 포트 범위: 80
    • 소스: 0.0.0.0/0 (모든 외부에서 허용)

 

 

4-3. ALB (Application Load Balancer) 생성

  1. EC2 → 로드 밸런서 > 생성 > ALB
  2. 이름: ecs-web-alb
  3. 유형: Application Load Balancer
  4. 리스너: HTTP (포트 80)
  5. VPC: my-vpc
  6. 서브넷: 위에서 만든 2개 퍼블릭 서브넷 선택

 

 

대상 그룹을 선택해줘야 하니 

대상 그룹을 생성 한다.

 

  1. “대상 그룹 생성” 버튼 클릭 (리스너 아래쪽에 있어)
  2. 아래처럼 설정:
대상 그룹 이름 ecs-web-tg
대상 유형 IP 주소 (중요)
프로토콜 HTTP
포트 80
VPC my-vpc-vpc 선택
헬스 체크 경로 / (또는 /health 라우터가 있다면 그것도 가능)

5. ECS 서비스 생성 (Fargate + ALB 연결)

콘솔에서 ECS 서비스 생성

📍 경로:

AWS 콘솔 → ECS > 클러스터 > my-cluster 클릭 > 서비스 생성

 

 

▶️ 1. 기본 구성

항목값
런타입 FARGATE
태스크 정의 web-task:1 (버전은 1일 수도 있고 더 높을 수도 있음)
플랫폼 Fargate 그대로
서비스 이름 web-service
태스크 수 1 (기본 1개 실행)
 

▶️ 2. 네트워킹 설정

항목값
클러스터 VPC my-vpc-vpc
서브넷 2개 선택 ap-northeast-2a, ap-northeast-2b 퍼블릭 서브넷
보안 그룹 ecs-web-sg (ALB와 동일한 보안 그룹)
퍼블릭 IP 자동 할당 활성화(ENABLED) (중요!)
 

 

▶️ 3. 로드 밸런싱

항목값
로드 밸런서 유형 Application Load Balancer
로드 밸런서 이름 ecs-web-alb
리스너 HTTP:80 선택됨
대상 그룹 ecs-web-tg 선택
 
 
 


최종 확인

1. ECS 서비스 > 태스크(Task)가 실행 중인지 확인

  1. AWS 콘솔 → ECS > 클러스터 > my-cluster > 서비스 클릭
  2. 아래쪽 태스크 탭 → 실행 중인지 확인

 

2. ALB 대상 그룹 → 대상 상태 확인 (본인이 해당됨 )

  1. AWS 콘솔 → EC2 > 대상 그룹
  2. → ecs-web-tg 클릭
  3. → 대상 탭으로 이동

등록된 대상이 없었음 ..

 

 

 

✅ 해결 방법 (단계별 정리)

ECS 서비스 새로 생성하면서 ALB 대상 그룹 연결

  1. AWS 콘솔 → ECS → 클러스터 → my-cluster → 서비스 삭제 (선택)
  2. 서비스 생성 버튼 클릭
  3. 중간에 로드 밸런싱 설정 단계에서 꼭 아래 항목 확인:
항목설정 값
로드 밸런서 유형 Application Load Balancer
로드 밸런서 ecs-web-alb 선택
리스너 포트 HTTP:80
대상 그룹 ecs-web-tg 선택
컨테이너 이름 web
컨테이너 포트 80
 

이 단계에서 연결만 제대로 하면 ECS가 자동으로 컨테이너의 IP를 ALB 대상 그룹에 등록필요!!

 

서비스 생성 단계에서 

네트워킹 , 로드 밸런싱 세팅을 하지 않았음 ..

 

vpc 선택해주고..
로드 밸런싱 설정해준다..
대상 그룹도 설정 위에서 만든걸로

 

 

 

3. 보안 그룹 확인(본인이 해당됨 )

 

클러스터 태스크 보안 그룹은 위와 같이 되어 있는데 ,

 

ALB 보안 그룹 (ecs-web-sg) 로 되어 있음

 

❗ 문제 요약

항목 현재 상태 설명
ALB 보안 그룹 (ecs-web-sg) ✅ 80포트, 0.0.0.0/0 허용 외부에서 접근 가능함
ECS 태스크 보안 그룹 (sg-08e5b873e825321b2) ❌ ALB 소스를 허용 안 함 ALB → ECS 접근 차단됨
 

즉,
ALB가 ECS 컨테이너에 헬스 체크 보내는데, 방화벽에서 막힘 → timeout 발생 → Unhealthy 뜸

 

 

해결 방법

🔧 sg-08e5b873e825321b2 (ECS 태스크 보안 그룹) 에 다음 인바운드 규칙 추가:

HTTP TCP 80 sg-0b18c75d615f44300 (ALB 보안 그룹)

마지막 으로  서비스 업데이트