카테고리 없음

docker로 이미지 만들고 , EC2, EB, Travis CI 를 활용해 간단하게 리액트 앱 배포하기 (실습)

윤-찬미 2022. 2. 16. 23:14

🐥기본 리액트 앱을 로컬에 셋팅했다는 가정하에 진행 됩니다.

 

디렉토리 상단에 아래와 같이 Dockerfile.dev 파일을 생성해 준다.

.dev를 붙인 이유는 해당 도커파일이 개발용으로 쓰고 있음을 명시해 주기 위함.

// 베이스 이미지는 node:alpine 를 사용
FROM node:alpine

// 워크디렉토리는 우리가 생성한 이미지 안에서 어플리케이션 소스코드를 갖고 있을 디렉토리를 생성 하는 것
WORKDIR /usr/src/app

// package.json file을 카피해 줍니다. 이는 컨테이너 안에서 npm install을 하려면 package.json이 필요하기 때문 입니다.
COPY package.json ./

// 필요한 패키지를 다운 받습니다.
RUN npm install

// 현재 로컬 디렉토리에 있는 데이터를 워크디렉토리의 ./ 경로에 copy 합니다.
COPY ./ ./

// docker run 실행 시 실행할 명령어 입니다.
CMD ["npm", "run", "start"]

 

이 도커 파일을 이용해 이미지를 생성해 보자. -f 옵션을 줘서 이미지를 빌드 할 때 쓰일 도커 파일을 명시해준다.

-t 옵션으로 이름도 지정 해준다. (-t 뒤에 있는건 여러분이 원하는 이름으로 하심 됩니다.)

docker build -f Dockerfile.dev -t valley/docker-react-app ./

만약 Dockerfile.dev 가 아니라 그냥 Dockerfile을 빌드 할 때는 아래 처럼 하면 된다.

docker build . -t valley/docker-react-app ./

 

현재 로컬 머신에 node_modules 폴더가 있는데, 이는 지워도 된다.

왜냐하면 어차피 도커 컨테이너안에서 앱이 실행 될거고 ,

도커이미지에 npm install로 모든 모듈을 다운 받았기 때문이다.

 

이후 아래 명령어로 실행을 시켜 준다.

docker run valley/docker-react-app

 

📌 현재 노드 17버전에서 조금 문제가 있는 듯..

https://github.com/webpack/webpack/issues/14532

 

nodejs 17: digital envelope routines::unsupported · Issue #14532 · webpack/webpack

Bug report What is the current behavior? [webpack-cli] Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:67:19) at Object.createHash (node:crypto:1...

github.com

 

따라서 만약 해당 명령어 실행 시에 아래와 같은 에러가 발생한다면?

envelope routines::unsupported

1. package.json 에 아래 처럼 코드를 추가 하거나

"start": "react-scripts --openssl-legacy-provider start"

2. dockerfile 의 베이스 이미지를 아래와 같이 변경해준다.

FROM node:16.3.0-alpine

 

아무튼 제대로 실행이 된다면, 아래와 같이 뜰 것 이다.

 

그 후 http://localhost:3000/ 로 접속을 해보면?

위와 같이 안뜨는게 정상이다.

 

왜냐하면 포트 맵핑을 안해주었기 때문이다.

여기서 포트맵핑이란 포트 포워딩이라고도 하는데,

컨테이너 외부에서 컨테이너 내부 서버로 접속할 수 있도록 포트를 맵핑 해주는 것을 말한다.

명령어는 아래와 같다.

docker run -p <host port number>:<container port number> [image]

즉 서버를 종료 하고 아래와 같이 입력한다. (로컬 3000포트로 접속하면 도커 컨테이너 내부의 3000포트로 접속하겠다)

docker run -p 3000:3000 valley/docker-react-app

 

 

이제 다시 접속해 보면 제대로 나와 있는걸 볼 수 있다.

 

소스코드를 변경하면 다시 이미지 빌드 해줘야 하나 - 😓 volume 셋팅하기 with docker-compose

기존에 썼던 방식은 로컬에 있는 파일을 말그대로 “copy” 한 것이라,

소스코드를 변경 하고 나면 이미지를 다시 빌드해줘야 하는 번거로움이 있다.

이럴 때 볼륨을 사용해 주면 되는데, 볼륨을 사용하면 기존처럼 파일을 복사해서 들고 있는것이 아닌 우리의 파일들을 참조하고 있게 된다.

도커 볼륨을 셋팅하고.. 이런것들 모두 터미널에 직접 입력해서 하거나, docker desktop app 등을 활용해서 할 수 있는데 가장 간단한 방법은 docker-compose file을 생성하는 것이다.

아, 참고로 도커 컴포즈 는 다중 컨테이너 애플리케이션을 정의하고 공유할 수 있도록 개발된 도구다.

 

1. docker-compose-dev.yml 파일을 만든다. (실제 파일에선 주석을 제거 한다)

version: "3.7" // 도커 컴포즈의 버전
services: // 실행하려는 컨테이너 목록
  react: // 컨테이너 이름
    build:
      context: . // 도커 이미지를 구상하기 위한 파일과 폴더들이 들어있는 경로
      dockerfile: Dockerfile.dev // 도커 파일
    ports: // 포트 맵핑
    - "3000:3000" 
    volumes: // 볼륨 설정
    - /usr/src/app/node_modules
    - ./:/usr/src/app

2. 명령어를 입력한다.

docker-compose -f docker-compose-dev.yml up

 

이후에 소스코드를 변경 후 확인해보면 바로바로 잘 바뀌어 있는 걸 알 수 있다.

 

컴포즈 파일 작성은 아래 링크를 참고 하세요!

https://docs.docker.com/storage/volumes/

 

Use volumes

 

docs.docker.com

 

NginX

이번에는 실제 운영 환경에서 리액트 앱을 실행 시켜 보도록 하자.

운영 환경에 필요한 도커 파일도 생성해보자.

이번엔 nginX 서버를 사용하려고 한다.

 

Dockerfile (이번엔 실제 운영 시 사용할 도커 파일 이므로 dev 는 생략한다)

FROM node:16.3.0-alpine as builder
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY ./ ./
RUN npm run build

FROM nginx
COPY --from=builder /usr/src/app/build /usr/share/nginx/html

해당 파일을 이용해 운영용 이미지를 생성해 준다.

docker build . -t valley/docker-react-app

 

로컬에선 8080 포트를, 컨테이너 안에선 80 포트를 사용하여 리액트 앱을 실행 시켜 보자

(nginX 기본 포트 80)

docker run -p 8080:80 valley/docker-react-app

 

로컬에서 8080 포트로 열면 우리의 리액트 앱이 열리는 걸 볼 수가 있다.

 

그리고 우리는 docker-compose.yml 운영용 파일도 만들어 준다.

추후 EB 플랫폼 으로 linux2를 사용할 건데,

linux2는 docker-compose.yml을 바라보고 배포를 하기 때문이다.

version: "3.7"
services:
  react:
    build:
      context: .
      dockerfile: Dockerfile
    ports: 
    - "80:80"
    volumes:
    - /usr/src/app/node_modules
    - ./:/usr/src/app
    stdin_open: true

 

테스트하고 배포하기

사전에 방금까지 한 프로젝트를 깃헙에 올려두어야 한다

이번에 ci는 travis ci를 사용할 예정이다.

근데 나는 개인적으로 큰 프로젝트 아니면 사실 그냥 github actions 써도 매우 무방하다고 생각하는 입장이다.

 

우선 아래 사이트에 들어가서 회원가입을 먼저 하자 (깃헙 계정으로)

https://travis-ci.org/

 

Travis CI - Test and Deploy Your Code with Confidence

 

travis-ci.org

 

가입 한 후에 프로젝트를 연결해야한다.

setting file을 열고,

 

본인의 프로젝트를 클릭한다. (나는 docker-file 이라는 이름으로 깃헙에 프로젝트를 만들었다)

그럼 아래와 같이 대시보드가 열린다.

 .travis.yml  파일을 만들어보자.

sudo: required

language: generic

services:
  - docker

before_install:
  - echo "Start Creating an image with dockerfile"
  - docker build -t valley/docker-react-app -f Dockerfile.dev .

script:
  - docker run -e CI=true valley/docker-react-app npm run test -- --coverage

after_success:
  - echo "Test Success!"
  • sudo : 관리자 권한
  • language: 언어 선택
  • services: 도커 환경 구성
  • before_install: 스크립트를 실행 할 수 있는 환경
  • script: 실행할 스크립트
  • after_success: 테스트 성공 후 할일

여기까지 만들고 나면 해당 파일을 github 에 push를 해준다.

git add .
git commit -m "Add travis file"
git push origin <push 할 origin branch>

 

그 후 travis ci 와서 확인해보면, 테스트가 진행 > 완료 되고 있는걸 볼 수 있다.

이제 소스코드를 수정하고 origin branch 에 push 할 때마다 .travis.yml  파일에 따라서 테스트 등등등이 진행이 될 것 이다.

aws EC2에 배포해보자

aws 회원가입을 하지 않았다면, 회원가입을 먼저 해주자.

https://ap-northeast-2.console.aws.amazon.com/console/home?region=ap-northeast-2 

 

https://ap-northeast-2.console.aws.amazon.com/console/home?region=ap-northeast-2

 

ap-northeast-2.console.aws.amazon.com

 

aws 에 대해 간단하게 설명을 하고 넘어가자면,

 

EC2(Elastic Compute Cloud)란?

EC2는 AWS에서 제공하는 클라우드 컴퓨팅 서비스다**.**

→ 쉽게 말해, 아마존으로 부터 한 대의 컴퓨터를 임대 하는 것이다. AWS가 제공하는 URL(Public DNS)를 통해 이 컴퓨터에 접근할 수 있다.

→ 이렇게 한대의 컴퓨터를 ec2 인스턴스라 부른다.

 

EB(Elastic Beanstalk)란?

Docker 컨테이너를 기반으로 애플리케이션을 쉽게 배포하고, 운영하고, 관리하는걸 도와주는 AWS 서비스다.

 

가입까지 완료해서 들어왔다면 elastic beanstalk 를 검색해서 들어간다.

아래와 같은 정보를 입력 후 웹 앱 생성을 해준다.

→ 애플리케이션 이름: docker-react-app

→ 플랫폼: docker

→ 플랫폼 브랜치: Docker running on 64bit Amazon Linux 2(2022년 2월 기준)

→ 플랫폼 버전: 3.4.11 (Recommended)(2022년 2월 기준)

 

.travis.yml 파일에 아래 내용을 추가 하자. 배포 관련 된 부분이다.

deploy:
  provider: elasticbeanstalk
  region: "ap-northeast-2"
  app: "docker-react-app"
  env: "Dockerreactapp-env"
  bucket_name: "elasticbeanstalk-ap-northeast-2-168586129156"
  bucket_path: "docker-react-app"

  on:
    branch: main

→ provider: 외부 서비스 표시 (우리는 ELB 사용)

→ region: 현재 사용하고 있는 aws 서비스 위치

→ app: 어플리케이션 이름

→ env: 환경 설정 이름

→ bucket_name: s3 bucket 이름

→ bucket_path: 어플리케이션 이름과 동일

→ branch: 어떤 브랜치에 push 할 때 배포 프로세스가 진행 될지

 

Travis CI 가 AWS 에 접근 할 수 있도록 인증을 위한 KEY 를 생성하자!

travis ci 에서 aws 에 접근하고 배포를 진행 하려면, travis file 에 secret key 와 access key가 있어야 한다.

이건 IAM 에서 발급 받을 수 있는데 IAM 에 대한 설명은 공식 문서에서는 아래와 같이 설명 하고 있다.

AWS Identity and Access Management(IAM)은 AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스입니다. IAM을 사용하여 리소스를 사용하도록 인증(로그인) 및 권한 부여(권한 있음)된 대상을 제어합니다.

우리가 처음에 aws 에 가입하면 우리는 루트 사용자 이다.

AWS 계정을 처음 생성할 때는 해당 계정의 모든 AWS 서비스 및 리소스에 대한 완전한 액세스 권한이 있는 SSO(Single Sign-In) ID로 시작합니다. 이 자격 증명은 AWS 계정 루트 사용자 라고 하며, 계정을 생성할 때 사용한 이메일 주소와 암호로 로그인하여 액세스합니다.

하지만 보안을 위해 IAM 유저를 생성하라고 한다.

일상적인 작업, 심지어 관리 작업의 경우에도 루트 사용자를 사용하지 마실 것을 강력히 권장합니다.

 

사용자를 추가해 보자

AWS > IAM > 사용자 추가

사용자 이름은 원하는대로, aws 자격증명 유형은 프로그래밍 방식 엑세스를 클릭해 하면 된다.

그리고 다음 버튼을 눌러 준다.

 

기존 정책 직접 연결 > AdministratorAccess-AWSElasticBeanstalk 을 클릭해 준다.

 

그 후 다음을 누른 후(태그 생략) 아래 페이지가 나오면 최종적으로 사용자 만들기 를 클릭해 준다.

그 후 생성된 IAM을 보면 엑세스 키와 비밀 엑세스 키가 발급된 것을 볼 수 있다.

 

이제 이 키들을 travis 에 입력해줄건데, 파일에 직접 입력하면 우리의 소중한 키들이 노출 되기 때문에 travis 페이지에 가서 등록을 하도록 하자.

travis 페이지에서 우리의 프로젝트 대쉬보드로 가면 오른쪽에 more options > setting을 클릭해 준다.

해당 셋팅 화면을 쭉 내리면 Environment Variables 라는 곳에 아래 두개 name으로 각각 채워 준다.

  • AWS_ACCESS_KEY
  • AWS_SECRET_ACCESS_KEY

 

그 후 .travis.yml 파일에 아래 access_key_id, secret_access_key 환경변수 값을 입력 해 준다.

deploy:
  provider: elasticbeanstalk
  region: "ap-northeast-2"
  app: "docker-react-app"
  env: "Dockerreactapp-env"
  bucket_name: "elasticbeanstalk-ap-northeast-2-168586129156"
  bucket_path: "docker-react-app"

  on:
    branch: main
  access_key_id: $AWS_ACCESS_KEY
  secret_access_key: $AWS_SECRET_ACCESS_KEY

 

추가로 80 포트를 맵핑해 주어야 하는데, 아래처럼 Dockerfile 에 포트 맵핑을 해준다.

EXPOSE 80 추가 (Dockerfile)

FROM nginx
EXPOSE 80
COPY --from=builder /usr/src/app/build /usr/share/nginx/html

 

그 후 해당 파일을 다시 github 에 push 해주면 된다.

git add .
git commit -m "Update travis file"
git push origin main

 

그 후 다시 travis dashboard로 와서 확인을 해보면, 모두 정상적으로 동작한 것을 볼 수 있다.

 

AWS EB 와서 확인을 해보면, 배포중인걸 볼 수 있다. 그리고 조금 기다리면, success 가 될 수 있다.

배포 진행 중...

성공 하면 아래 표시한 링크로 접속하면 우리가 배포한 앱이 잘 올라가 있는 것을 볼 수 있다.

 

테스트가 완료된 후에는 EB 에 가서 작업 > 종료 를 해주어야 한다.

 

여기 까지 간단하게 dockerfile 로 리액트 앱의 도커 이미지를 만들어보고, 우리의 앱을 배포까지 해보았다.