본문 바로가기

[Docker] React 웹 Docker로 배포하기

@hyeon.s2024. 11. 1. 10:12

배포하기 전

도커 환경 설치가 필요하다.
아래 블로그를 참고해 설치를 완료 해야한다.

[Docker] 0. 🐳 도커 환경 설치하기 (Docker Desktop) 🐳

설정 방법

만들어 둔 React 웹 프로젝트 루트에 DockerFiledocker-compose.yaml 파일을 생성합니다.

DockerFile

DockerFile이란?

  • DockerImage를 생성하기 위한 설정파일(스크립트)이다.
  • 여러가지 명령어로 DockerFile을 작성한 후 빌드를 진행한다.
  • 빌드하게 되면 Docker는 DockerFile에 나열된 명령어를 차례대로 수행하며 DockerImage를 생성한다.
  • DockerFile을 읽을 줄 안다는 것은 이미지가 어떻게 구성되어 있는지 알 수 있다는 의미이다.
  • DockerFile은 배포에 용이하다.
  • 어떤 이미지를 배포할 때, 이미지 파일 자체를 배포하기 보다 이미지를 만들 수 있는 스크립트인 DockerFile만 배포하면 매우 편리하다.
  • 사용자는 DockerFile(스크립트)만 실행시켜도 스스로 DockerFile에 해당하는 이미지를 얻을 수 있기 때문이다.

React의 DockerFile

# 가져올 이미지를 정의 Node의 이미지를 가져온다는 뜻. 
FROM node:14
# 경로 설정하기
WORKDIR /demo-web/demo-web
# package.json 워킹 디렉토리에 복사 (.은 설정한 워킹 디렉토리를 뜻함)
COPY package.json .
# 명령어 실행 (의존성 설치)
RUN npm install
# 현재 디렉토리의 모든 파일을 도커 컨테이너의 워킹 디렉토리에 복사한다.
COPY . .

# 각각의 명령어들은 한줄 한줄씩 캐싱되어 실행된다.
# package.json의 내용은 자주 바뀌진 않을 거지만
# 소스 코드는 자주 바뀌는데
# npm install과 COPY . . 를 동시에 수행하면
# 소스 코드가 조금 달라질때도 항상 npm install을 수행해서 리소스가 낭비된다.

# 3000번 포트 노출
EXPOSE 3000

# npm start 스크립트 실행
CMD ["npm", "start"]

# 그리고 Dockerfile로 docker 이미지를 빌드해야한다.
# $ docker build .
  • FROM : 베이스 이미지
    • 어느 이미지에서 시작할건지를 의미한다.
  • MAINTAINER : 이미지를 생성한 개발자의 정보 (1.13.0 이후 사용 X)
  • LABEL : 이미지에 메타데이터를 추가 (key-value 형태)
  • RUN : 새로운 레이어에서 명령어를 실행하고, 새로운 이미지를 생성한다.
    • RUN 명령을 실행할 때 마다 레이어가 생성되고 캐시된다.
    • 따라서 RUN 명령을 따로 실행하면 apt-get update는 다시 실행되지 않아서 최신 패키지를 설치할 수 없다.
    • 위 처럼 RUN 명령 하나에 apt-get update와 install을 함께 실행 해주자.
  • WORKDIR : 작업 디렉토리를 지정한다. 해당 디렉토리가 없으면 새로 생성한다.
    • 작업 디렉토리를 지정하면 그 이후 명령어는 해당 디렉토리를 기준으로 동작한다.
    • cd 명령어와 동일하다.
  • EXPOSE : Dockerfile의 빌드로 생성된 이미지에서 열어줄 포트를 의미한다.
    • 호스트 머신과 컨테이너의 포트 매핑시에 사용된다.
    • 컨테이너 생성 시 -p 옵션의 컨테이너 포트 값으로 EXPOSE 값을 적어야한다.
  • USER : 이미지를 어떤 계정에서 실행 하는지 지정
    • 기본적으로 root에서 해준다.
  • COPY / ADD : build 명령 중간에 호스트의 파일 또는 폴더를 이미지에 가져오는 것
    • ADD 명령문은 좀 더 파워풀한 COPY 명령문이라고 생각할 수 있다.
    • ADD 명령문은 일반 파일 뿐만 아니라 압축 파일이나 네트워크 상의 파일도 사용할 수 있다.
    • 이렇게 특수한 파일을 다루는 게 아니라면 COPY 명령문을 사용하는 것이 권장된다.
  • ENV : 이미지에서 사용할 환경 변수 값을 지정한다.
    • path 등
  • CMD / ENTRYPOINT : 컨테이너를 생성 및 실행 할 때 실행할 명령어
    • 보통 컨테이너 내부에서 항상 돌아가야하는 서버를 띄울 때 사용한다.
    • CMD
      • 컨테이너를 생성할 때만 실행됩니다. (docker run)
      • 컨테이너 생성 시, 추가적인 명령어에 따라 설정한 명령어를 수정할 수 있습니다.
    • ENTRYPOINT
      • 컨테이너를 시작할 때마다 실행됩니다. (docker start)
      • 컨테이너 시작 시, 추가적인 명령어 존재 여부와 상관 없이 무조건 실행됩니다.
    • 명령어 형식
      • CMD ["<커맨드>", "<파라미터1>", "<파라미터2>"]
      • CMD <커맨드> <파라미터1> <파라미터2>
      • ENTRYPOINT ["<커맨드>", "<파라미터1>", "<파라미터2>"]
      • ENTRYPOINT <커맨드> <파라미터1> <파라미터2>
    • 참고

docker-compose.yaml

version: "3.2"
services:
  frontend:
    restart: always
    command : npm start
    container_name: front
    build:
      context: ./
      dockerfile: Dockerfile
    ports:
      - "80:3000" 
    stdin_open: true
  • version : docker-compose 파일의 버전 지정
  • services : 프로젝트에서 사용 할 컨테이너 지정 섹션
    • 각 서비스는 하나의 Docker 컨테이너를 나타내며, 개별적으로 설정가능하다.
    • 이 섹션에서는 frontend라는 이름의 서비스를 정의하고 있다.
  • image : 사용할 Docker 이미지 지정한다. Docker Hub의 이미지나, 직접 빌드한 이미지를 사용할 수 있다.
  • restart: always : 컨테이너가 중지되면 항상 다시 시작하라는 설정이다.
    • 서버나 애플리케이션이 충돌했을 때 자동으로 다시 시작하여 가용성을 높인다.
  • command: npm start:
    • 컨테이너가 시작될 때 실행할 명령어입니다. 여기서는 npm start를 실행하여 Node.js 애플리케이션을 시작합니다.
  • build: DockerFile을 사용해 이미지를 빌드할 경우 사용합니다.
    • context./ : 빌드를 위한 컨텍스트 디렉토리를 현재 디렉토리로 설정
    • dockerfile : 사용된 Dockerfile의 이름을 지정 → 위에서는 현재 디렉토리에 있는 DockerFile 사용한다.
  • ports: 컨테이너의 포트를 로컬 머신의 포트에 매핑해, 서비스에 접근할 수 있도록 한다.
  • stdin_open : true
    • 컨테이너에서 표준 입력 (STDIN)을 열어두오 사용자가 컨테이너 터미널에 입력할 수 있도록 한다. 이 옵션이 설정되어 있으면 docker exec 명령어를 사용하여 컨테이너에 접속할 때 유용하다.

ports : “host port: container port”

  • 호스트에서 접속하는 port : 컨테이너가 생성되는 port 로 대응해야 한다.
  • 즉 외부에서 80 port로 접속하여 컨테이너 내에 3000 port 에서 npm start를 한다는 의미이다.

Dockerfile vs docker-compose.yaml

기능 Dockerfile docker-compose.yaml
대상 단일 컨테이너 이미지 정의 여러 컨테이너 구성 및 관리
주요 역할 이미지 빌드 애플리케이션을 서비스 단위로 정의하고 실행 관리
필요성 개별 컨테이너 설정 서비스 간 의존성 관리 및 실행 환경 설정
실행 명령어 docker build, docker run docker-compose up
네트워크 설정 기본적으로 필요하지 않음 서비스 간의 네트워크를 정의 및 설정 가능

Dockerfile은 이미지를 만드는 설계도이고, docker-compose.yaml은 그 이미지와 다른 이미지를 조합해 서비스를 정의하고 실행하는 방법이라고 생각하면 됩니다

Docker 이미지 생성 및 배포

1. 이미지 빌드

docker build -t seohyeonshin/demo-web-frontend:latest .

2. Docker Hub에 이미지 업로드

docker login
docker push seohyeonshin/demo-web-frontend:latest
  • 이미지를 빌드하고 Docker Hub에 배포하여 다른 환경에서 쉽게 가져올 수 있습니다.

3. 가상화 서버에 이미지 가져오기

docker pull seohyeonshin/demo-web-frontend:latest
  • 가장 최신에 docker hub에 올린 demo-web-frontend의 이미지를 가져오도록 하였다.

4. 배포한 Docker 이미지 실행

docker run -d -p 80:3000 demo-web-frontend:latest
명령어 설명
docker run Docker 이미지를 실행하는 명령어
-d 컨테이너를 백그라운드에서 실행하도록 설정
--name simple-react-app 실행하는 컨테이너의 이름을 'simple-react-app'으로 지정
-p 3000:3000 호스트 기기의 3000번 포트와 컨테이너의 3000번 포트를 연결
simple-react-app 실행할 Docker 이미지의 이름

트러블 슈팅

docker: Error response from daemon: driver failed programming external connectiv                          ity on endpoint kind_poitras (c63a0c35c766ddbd968dccbb8a724729d2878ce5b53f17df95                          8ecbf87cd1e6e1): Bind for 0.0.0.0:80 failed: port is already allocated.

해당 에러가 발생하였다.
이는 이전에 pull 받은 이미지를 80 포트에서 실행중이기 때문에 80 포트에서 실행할 수 없다는 뜻이다.
따라서 현재 컨테이너를 중단하고, 새로운 이미지를 올려서 80 포트에 실행하였다.

hyeon.s
@hyeon.s :: 개발로그
목차