본문 바로가기

프로그래밍/AWS

[AWS 배포] : Docker Compose와 ECS

반응형

나의 서비스 구조

Mac 또는 Ubuntu 서버

docker compose up

그러면

┌────────────────────────────┐
│ Docker                     │
│                            │
│  frontend                  │
│      │                     │
│      ▼                     │
│  backend                   │
│      │                     │
│      ▼                     │
│ postgres                   │
└────────────────────────────┘

Compose는

services:

  frontend:

  backend:

  postgres:

이 세 개를 한 번에 띄운다.

backend는

http://backend:8000

으로 접근한다.

왜?

Compose가 내부 DNS를 만들어주기 때문이다.

backend

라는 이름을 Docker가 자동으로 IP로 바꿔준다.

그래서 nginx에서

proxy_pass http://backend:8000;

이 가능한 것이다.


그런데 ECS는 다르다

ECS는

Docker Compose

를 그대로 실행하지 않는다.

AWS는

Task Definition

이라는 개념을 사용한다.

예를 들어

Frontend Task

Backend Task

혹은

Application Task

Frontend Container

Backend Container

처럼 정의한다.

Compose처럼

backend:

라는 이름이 존재하지 않는다.


왜 nginx를 수정해야 하나?

현재는

proxy_pass http://backend:8000;

일 것이다.

그런데 ECS에서

Frontend와 Backend를

같은 Task 안에 넣으면

둘 다 같은 네트워크를 공유한다.

localhost

가 된다.

그래서

proxy_pass http://127.0.0.1:8000;

로 바꾸는 것이다.

이게

backend:8000

↓

127.0.0.1:8000

를 의미한다.


Compose에서는 DATABASE_URL은 어떻게 들어갈까?

Compose에서는 보통

environment:

DATABASE_URL=...

이 있다.

혹은

.env

파일을 읽는다.

예를 들어

DATABASE_URL=postgres://...

Docker가

자동으로

backend에 넣어준다.


ECS에서는 .env를 안 쓴다

AWS에서는

Secrets Manager

가 환경변수를 대신한다.

예를 들어

DATABASE_URL

이라는 Secret을 만든다.

안에는

postgres://...

가 저장된다.

Task Definition에서는

DATABASE_URL

↓

Secrets Manager

를 연결한다.

그러면

컨테이너가 시작될 때

os.environ["DATABASE_URL"]

이 자동으로 들어온다.

.env

↓

Secrets Manager

로 바뀌는 것이다.


Docker Volume은?

Compose에서는

volumes:

erp-data:

를 사용한다.

이건

서버 하드디스크

를 의미한다.

예를 들어

/var/lib/docker/...

에 저장된다.


AWS에서는

컨테이너가 언제든 삭제될 수 있다.

오늘

Server A

에서 돌다가

내일은

Server B

에서 실행될 수도 있다.

그러면

Server A

에 저장한 파일은 사라진다.

그래서

Docker Volume

↓

EFS

로 바꾸는 것이다.

EFS는

AWS가 제공하는

공유 NAS(Storage)이다.

모든 ECS Task가

같은 파일을 본다.

          EFS

      ┌────┴────┐
      │         │

 ECS Task1   ECS Task2

      │         │

      같은 파일

Migration Task를 따로 만드는 이유

Compose에서는

배포 후

docker exec

python manage.py migrate

를 실행한다.

하지만 ECS에서는

이미 서비스가 실행 중이다.

여기서

docker exec

를 할 수 없다.

그래서

Migration Task

라는

일회성 컨테이너를 만든다.

흐름은

Backend Image

↓

Migration Task

↓

manage.py migrate

↓

종료

↓

Application Deploy

이다.

이게 ECS에서 권장하는 방식이다.


왜 AWS CDK나 Terraform이 필요한가?

처음에는 AWS 콘솔에서 클릭해서 만들 수도 있다.

하지만 서비스가 커지면

다음 리소스들을 모두 기억해야 한다.

  • VPC
  • Subnet
  • Security Group
  • ECS Cluster
  • ECS Service
  • ECS Task Definition
  • ECR
  • RDS
  • EFS
  • Route53
  • ACM
  • IAM
  • CloudWatch

콘솔에서 하나씩 만들면 재현이 어렵고 실수가 발생하기 쉽다.

그래서

infra/

    aws/

        vpc.ts

        ecs.ts

        rds.ts

        alb.ts

        efs.ts

처럼 코드로 관리한다.

이걸 Infrastructure as Code(IaC) 라고 한다.


결국 ERP 프로젝트에서 변경되는 것은?

현재 구조는

docker-compose.yml

↓

docker compose up

중심이다.

AWS에서는

Docker Image

↓

GitHub Actions

↓

ECR

↓

ECS Task

↓

ALB

↓

RDS

↓

EFS

중심으로 바뀐다.

즉, 애플리케이션 코드(Django/React)는 거의 그대로 유지되고, 배포와 운영을 담당하는 계층만 AWS 방식에 맞게 변경되는 것이다.


내가 이 ERP 프로젝트를 처음부터 구축한다면, 다음 순서로 진행할 것이다.

  1. Docker Compose로 로컬 개발 환경 완성
  2. GitHub Actions(CI) 구축
  3. ECR 자동 이미지 업로드
  4. ECS Fargate 자동 배포
  5. RDS 연결
  6. EFS 연결
  7. ALB + HTTPS 구성
  8. CloudWatch 모니터링
  9. Blue/Green 또는 Rolling Deployment 적용

이 순서대로 가면 로컬에서 개발한 환경을 거의 그대로 유지하면서도 운영 환경은 AWS의 관리형 서비스를 최대한 활용할 수 있다.

이 부분은 AWS의 네트워크(VPC) 를 이해해야 왜 이렇게 구성하는지 이해할 수 있어.

많은 사람들이 AWS를 처음 배우면

"EC2 하나 만들고 Docker 올리면 되는 거 아니야?"

라고 생각하는데, 실제 운영 환경은 그렇게 하지 않아.


 

반응형