Docker - ECR - EC2 실행 명령어 정리
*<> 괄호 안에 내용은 본인 것으로 바꿔여 함
0. ECR 리포지토리 만들기
AWS ECR(Elastic Container Registry) 이동 > 리포지토리 생성
프라이빗 or 퍼블릭으로 만들 수 있음
ECR은 AWS에서 지원하는 서비스 중 하나인데, docker image를 저장할 때 쓸 수 있음
EC2 instance(서버)는 ECR에 올라온 이미지를 pull 해서 container를 실행하기만 하면 됨
이렇게 하면 EC2 서버 안에는 full code가 아닌 docker image만 있기 때문에 더 가벼움
git code를 전부 pull해서 직접 실행하는 방식보다 훨씬 가벼움
여기 뜨는 URI를 잘 복사해두자. 이후에 계속 필요함
1. 로컬에서 현재 코드를 바탕으로 Docker 이미지 빌드하기
1) fastify: Dockerfile.fastify 파일로 빌드
docker build -t <레포지토리-퍼블릭 리포지토리 URI>:<태그-fastify임을 식별 가능한 이름> -f Dockerfile.fastify .
* Fastify의 환경 변수는 docker 실행 시 동적으로 가져올 예정
2) next.js: Dockerfile로 빌드
docker build --build-arg NEXT_PUBLIC_BASE_BFF_API_URL="<EC2 인스턴스 퍼블릭 IP:포트번호>" -t <레포지토리-퍼블릭 리포지토리 URI>:<태그-nextjs임을 식별 가능한 이름> -f Dockerfile .
* Next.js 도커 이미지 빌드할 때 env를 직접 넣는 이유:
env 파일을 실행 시 동적으로 불러왔더니 환경 변수를 인식하지 못하기 때문. 이건 Next.js 특성..
.env 파일을 run 할 때 읽어올 수 있도록 시도했는데, 시도한 방법들은 모두 실패했음. 추후 성공 시 추가 글 작성 에정.
* ECR로 push 할거면 도커 이미지 빌드할 때 <퍼블릭 레포지토리 URI>:<이미지 태그> 형태로 꼭 해줘야 함
퍼블릭 리포지토리로 만든 이유는 비용 때문이고, 프라이빗 리포지토리로 만드는 게 더 안전하긴 할듯
(AWS 설명 상으로는 퍼블릭 리포지토리인 경우 500MB 기본 무료 용량에 추가적으로 더 무료를 제공한다고 함)
(근데 AWS 비용 뒤통수를 많이 맞아봐서 이것도 다음달 인보이스 봐야 증명 가능;;ㅋㅋㅋ)
2. AWS CLI 설치
(0) AWS CLI 설치 맟 계정 세팅
AWS CLI 명령어 쓸 거라서 안깔았으면 설치해야 함. 이미 있으면 패스!!
https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html
최신 버전의 AWS CLI 설치 또는 업데이트 - AWS Command Line Interface
이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이
docs.aws.amazon.com
나는 윈도우라서 AWSCLIV2.msi 파일을 설치하는 형태로 진행함
그 후 aws 계정을 내 로컬 컴에 세팅하는 과정이 필요함
루트 사용자를 직접 갖다 박는 건 비추하는 방법이라고 하니, IAM 사용자를 만들도록 합시다
AWS IAM(Identify and Access Management) 접속
좌측 메뉴 -> 엑세스관리 > 사용자 -> 사용자 생성
사용자 이름 클릭 -> 권한 -> 권한 정책 -> 권한 추가
"AmazonElasticContainerRegistryPublicFullAccess" 권한 부여
로컬에서 ECR로 이미지를 push하는 권한이 필요하기 때문에 해당 권한 부여
엑세스 키를 안만들었다면 엑세스 키1에 "엑세스 키 만들기"가 뜰 것
그걸 눌러서 키를 만든다
AWS AccessKeyId와 AWSScretKey 두가지 값을 따로 저장해둔다
cmd 창을 켜서 aws configure를 입력한다
AWS Access Key ID [None]: 위 엑세스 키 id
AWS Secret Access Key [None]: 위 엑세스 키 pw
Default region name [None]: 난 서울로 해줬다 (ap-northeast-2)
Default output format [None]: 안해도 상관은 없는 것 같은데 나는 json으로 했다
3. AWS CLI로 ECR 로그인하기
AWS CLI로 ECR 로그인
aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin <퍼블릭 리포지토리 URI>
여기서 오류가 많이 난다
aws ecr-public get-login-password --region us-east-1 하면 ecr에 접근할 수 있는 pw가 생성되는데,
이걸 파이프(|) 명령어로 넘기는 과정에서 문제가 생기는 것 같다
여러 해결책이 있는데.. 해결책이라고 하기엔 애매하지만
C:\Users\<본인의 user 프로필>\.docker
이 경로로 들어가면 config.josn 파일이 있음
이걸 열어보면 "credsStore" 속성이 "wincred"로 되어 있다.
저 속성 때문에 생성된 비번을 저장하는 과정에서 오류가 나고, 이걸 제대로 불러오지 못해서 오류가 나는 것 같다
사실 좋은 해결책은 아닌 것 같지만 작동은 하는 방법은 아래와 같다
docker login: error storing credentials `The stub received bad data.`
First, I installed AWS-CLI and I already used "AWS configure" to set up my secret key and I also used "Docker login" command to log in and I got success and when I typed Get-ECRLoginCommand. It wor...
stackoverflow.com
위 글을 부분부분 참고했는데
* 주의! docker 원래 설정을 건드리면, 본인 환경에서는 복잡한 side effect가 발생할 수 있음!
1. C:\Users\<본인의 user 프로필>\.docker
- config.json 파일의 credsStore 속성 아예 삭제
2. C:\Program Files\Docker\Docker\resources\bin
docker-credential-desktop.exe 파일 삭제
docker-credential-wincred.exe 파일 삭제
3. docker context use default 를 cmd에 입력
이렇게 하면 config.json에 비밀번호를 하드 텍스트로 저장하고, 이를 ECR 로그인에 직접 가져와서 사용한다
그래서 보안적으로는 문제가 있지만, 로그인을 할수는 있다
하지만, 기본 설정에 원래 있던 파일을 삭제하는 것인 만큼, 경로 참조 오류가 발생하고 꼬일 수 있다
stack overflow에서 이걸 해결책으로 많이 제시하고 있는데 좋은 방법은 아닌 것 같다
로그인이 성공하면 "Login Succeded"라는 문구가 떠야 한다
4. 로컬의 Docker 이미지 ECR(Elastic Container Registry)로 push하기
본인이 Docker 이미지 빌드할 때 썼던 리포지토리:태그 이름 그대로 쓰면 된다
(1) fastify 도커 이미지 push
docker push <레포지토리-퍼블릭 리포지토리 URI>:<태그-nextjs임을 식별 가능한 이름>
(2) nexjs 도커 이미지 push
docker push <레포지토리-퍼블릭 리포지토리 URI>:<태그-nextjs임을 식별 가능한 이름>
같은 이름으로 push하면 이미 존재하는 레이어말고 업데이트 된 부분만 덮어 씌운다
그리고, 나는 한 ECR에 fastify, next.js 이미지 두 개를 올리고 있는데
두 코드가 한 레포 안에 있다보니 겹치는 레이어가 있는 것 같다. 그래서 그 부분을 빼고 올리는 것 같다
그래서 로컬에서는 1.04GB가 나오는 fastify의 이미지가 856MB로 줄어들었다
5. EC2에서 ECR의 Docker 이미지 가져오기
EC2은 프리티어를 지원하는 세팅으로 맞췄다
Ubuntu 22.04, t2.micro로 세팅했다
그리고 내 로컬 컴에서 EC2에 접속하기 위해 .pem 키를 세팅했다
인스턴스 생성 시에 .pem 키가 생기는데, 이걸 내 컴에 세팅하면 된다
자동으로 Downloads 폴더에 저장되는데, 좀 더 안전한 곳으로 옮기도록 하자
mkdir -p ~/.ssh
mv ~/Downloads/<내 키 이름>.pem ~/.ssh/
이걸 이용해서 EC2에 접속해보자
ssh -i ~/.ssh/<내 키 이름>.pem ubuntu@<EC2-퍼블릭-IP>
이렇게하면 접속된다
EC2 서버 내에 기본 패키지들을 일단 업데이트 해주자
sudo apt update && sudo apt upgrade -y
그리고 docker 이미지를 가져오자
sudo docker pull <레포지토리-퍼블릭 리포지토리 URI>:<태그-fastify임을 식별 가능한 이름>
sudo docker pull <레포지토리-퍼블릭 리포지토리 URI>:<태그-nextjs임을 식별 가능한 이름>
아까 도커 이미지 만들었던 태그 그대로 불러오면 된다
6. EC2 내에서 기존에 실행 중인 도커 컨테이너 멈추고 지우기
이미 실행 중인 다른 도커 컨테이너가 있다면 멈추고 지워야 한다
그리고 도커 컨테이너를 멈추고 지운 후, 도커 이미지도 같이 지워줘야 한다
안그럼 기껏 도커 이미지를 써서 용량 최적화를 한 의미가 없어진다(계속 ec2 인스턴스에 이미지 쌓임)
sudo docker ps #컨테이너 목록 확인
sudo docker stop <컨테이너 id>
sudo dokcer rm <컨테이너 id>
sudo docker images #이미지 목록 확인
sudo docker rmi -f <이미지 이름>
만약 이미지를 지웠는데 tag만 지워지고 <none> 태그가 남았다면 강제로 지워줄 수 있다
for /f "tokens=*" %i in ('docker images -q -f "dangling=true"') do docker rmi -f %i
7. EC2 내에서 새로운 도커 이미지 실행하기
fastify는 run 단계에서 환경 변수 파일을 넘겨주기 때문에, run 키워드에 껴넣어야 한다
sudo docker run --env-file=.env --env-file=.env.secret -d -p <설정한 포트 번호>:<설정한 포트 번호> 리포지토리 URI>:<태그-fastify임을 식별 가능한 이름>
next.js는 빌드할 때 환경변수를 이미 넘겨줬다 그냥 실행한다
sudo docker run -d -p <설정한 포트 번호>:<설정한 포트 번호> 리포지토리 URI>:<태그-nextjs임을 식별 가능한 이름>
앞으로 해야할 것
프론트엔드 - 백엔드 HTTPS 접속 지원 및 CORS 에러 해결
이렇게 하면 <퍼블릭 IP>:<포트번호>로 접속할 수 있다
하지만 EC2는 http로 실행되기 때문에 https 지원을 위해 추가작업이 필요하다
우선 가비아에서 도메인을 사서, cloudflare의 NS(네임서버)와 연결했다
프론트엔드까지는 잘 접속이 되지만, https로 접속한 프론트엔드가 http로 실행된 백엔드(Fastify)로 api 요청을 넘기며 cors에러가 발생했다
이건 프론트엔드가 https://<퍼블릭ip>:<포트번호>로 요청을 넘긴다고 해결되는 문제가 아니다
근본적으로 백엔드 자체가 HTTP로 실행되는 걸 HTTPS로 실행되도록 만들어야 해결됨
let's ecrypt로 백엔드에 ssl 인증서를 붙이는 방법이 있음
그리고, cloudflare는 인식할 수 있는 포트가 제한적이기 때문에 nginx로 특정 포트로 들어온 요청을 프론트 or 백엔드로 나눠주는 방법도 있음
백엔드에서 nginx, let's encrypt 없이 해결할 수 있을까 싶어서
cloudflare에서 origin rule도 적용해보려고 했다(특정 포트로 들어오는 요청을 잡아서 특정 경로로 넘겨줌)
그런데 cloudflare에서 도메인이 next.js로 리다이렉션을 시켜서 실행 중인 fastify를 도메인으로 감지하는 것 자체가 잘 안되었다
그래서 해결책을 찾아보니 docker-compose로 프론트+백엔드를 한 이미지 안에 빌드해서
프론트-백엔드 요청이 같은 docker 네트워크 상에서 일어나도록 해 cors 에러를 극복하는 해결책을 확인했다
nginx로 각 포트에 들어오는 요청을 잡아서 프 or 백으로 보내는 과정은 필요한데,
docker-compose 파일로 한 파일 빌드하는 방법은 맨 처음에 docker 이미지 크기 최적화를 시도하기 전에만 해봤기에
지금 이 상태에서 다시 시도해보는 것도 의미있을 것 같다
NGINX, React, FastAPI Docker-compose 구성(환경 변수 문제 해결)
nginx-react 컨테이너와 fast-api 컨테이너를 따로 분리를 하니, 두 컨테이너 사이에서 CORS 이슈가 발생할 뿐더러 유지보수에서의 불편함이 생겨 하나의 docker-compose 파일로 nginx, react, fast-api를 배포합
velog.io
이 글을 참고해서 다른 이슈에서 다시 시도해보려고 한다
CICD 적용
지금은
docker 이미지 빌드 -> ECR에 push -> EC2에서 pull ->기존 docker 컨테이너 삭제 -> docker 이미지 실행
을 손으로 하고 있지만
터미널 창도 여러개 켜야 하고 너무 오래걸린다
이걸 github action으로 자동화 할 예정이다
작성: 2025.02.18. 16:48
'개발자 강화 > 프론트엔드' 카테고리의 다른 글
[개발][BFF 도전기] 부동산 공공데이터 API 뜯어보고 BFF API 설계하기 (0) | 2025.02.20 |
---|---|
[공부] 자바스크립트 함수의 this 바인딩 (1) | 2025.02.20 |
[개발][BFF 도전기] Fastify 서버 - 폴더 구조화 (0) | 2025.02.18 |
[개발][BFF 도전기] Next.js 구축, Fastify에 Swagger 안 붙는 문제 해결하기 (1) | 2025.02.16 |
🌟[매일메일] 이벤트 전파(Event Propagation)란? (FE.250106) (0) | 2025.02.14 |