React + Docker 실습해보기

박상우·2024년 8월 12일
0
post-thumbnail

React + Docker

1. npx create-react-app으로 react app 세팅
2. docker hub에서 node를 검색 상단의 node image를 get 하는 코드 복사 ( docker pull node )

→ 리액트는 Node 환경에서 돌아가기 때문에 docker에서 Node 이미지를 통해 Node 환경의 을 구성하고, Node Container 내부에서 React 프로젝트가 돌아가게해야한다.

3. 프로젝트 폴더 내부의 루트 경로에 DockerFile 을 만들고 아래 내용을 삽입한다.

# node 이미지 사용
FROM node    
    
# 이후 명령어를 실행해 컨테이너 내부의 작업 디렉토리 설정
WORKDIR /app 
    
# package.json 파일을 경로(.)에 복사
COPY packakge.json . 

# package.json 내부의 의존성을 설치
RUN npm install

# 프로젝트의 모든 파일을 복사한다. [ 현재 작업 디렉토리의 루트 경로 : .] 에서 [ container 디렉토리의 루트 경로 : . ]로 복사
COPY . .

# 런타임에 사용할 포트 번호 설정
EXPOSE 3000

#  react 프로젝트 시작
CMD ["npm", "start"]

엥 그럼 package.json 왜 카피함? 뒤에서 모든 파일 복사할건데?

  • 도커의 명령어는 각 줄을 layer처럼 동작하고, 각 레이어가 실행되었을 때 그 결과 값이 캐싱된다. (이후 빌드 과정에서 빨리 됨)
  • package.json의 경우 상대적으로 바뀔 가능성이 적다.
  • 나머지 코드들은 docker를 실행하는 과정에서도 수정이 될 수 있기 때문에 변하지 않는 Package.json을 먼저 카피해서 의존성을 설치하여 캐싱해두고, 가장 최신의 코드를 복사하기 위해서 두 구간을 나눠서 작성한다.
  • 만약에 모든 파일을 복사한 후 Install 하면 코드의 변화 때문에 캐싱 기능을 제대로 사용하지 못할 가능성이 높기 때문이다.

4. docker build . 로 프로젝트 디렉토리를 docker에 빌드한다.

⚠️ ERROR: Cannot connect to the Docker daemon at unix:///Users/sangwoopark/.docker/run/docker.sock. Is the docker daemon running? 에러가 뜬다면.

sudo launchctl stop docker    
sudo launchctl stop docker.socket
sudo launchctl stop containered
 sudo launchctl start docker

5. (참고) docker image ls 를 해보면 가장 큰 크기의 이미지를 확인할 수 있다. 해당 image를 지우고 이름을 다시 설정할 수 있다.

	> docker image rm [IMAGE ID]
	삭제후 다시 docker에 프로젝트 폴더를 빌드한다.
    > docker build -t [CUSTOM IMAGE NAME] .
	위에서 설명했듯 Dockerfile 내부 명령어들은 실행시 결과를 caching 하기 때문에 첫번째 빌드이후 바로 다시 빌드해보면 각 명령어가 실행될때 이전에 caching 해둔 결과값을 사용하는 것을 확인할 수 있다.

6. 빌드로 생성한 docker image를 실행하여 새로운 컨테이너를 생성한다.

    > docker run -d --name react-app react-image

7. docker ps를 통해 컨테이너가 실행중인지 확인한다.

    > docker ps

→ 컨테이너가 실행중이지만 localhost:3000으로 다시 접속했을때는 페이지를 찾을 수 없다는 오류가 발생한다.

→ 우리가 docker file에 명시해준 포트번호(3000)은 사실 문서 그 이상의 역할을 하지 않는다. 지금 상태에서는 컨테이너에 접속할 방법이 없고, 3000번은 아직 우리 컴퓨터에서의 독립된 네트워크 안을 의미한다.

→ 컨테이너를 default로 생성하면, 외부에서는 우리 작업디렉토리에 접근하여 파일을 복사하고, 설치하고 가능하지만 반대로 안쪽, 작업 레포지토리에서 외부 컨테이너에는 접속할 수 없는 상태이다.


8. 기존의 docker container를 지우고, 아래의 커맨드로 새롭게 컨테이너를 생성한다.

    docker run -d -p 3000:3000 --name react-app react-image
3000:3000이 의미하는 바는 로컬 **3000**번 포트에서 발생하는 트레픽을 컨테이너의 **3000**번 포트로 연결한다는 것이다.

9. 아래의 커맨드로 docker의 컨테이너를 실행한다.

```bash
docker exec -it reach-app bash
```

  1. ls 명령어를 통해 내부 파일들을 확인해보면 Dockerfile에서 실행했던대로 파일들이 복사되어 있다.

  1. 위 파일들 중에 사실상 Dockerfile이나 node-modules는 필요하지 않다. 이렇게 굳이 복사하지 않아도되는 파일을 제외하기 위해 루트 경로에 .dockerignore 파일을 생성한다.

    # .dockerignore
    node_modules
    Dockerfile
    .git
    .gitignore
    .dockerignore
    .env
  1. 작업 디렉토리의 반영사항에 대해서 container에 실행중인 프로젝트 경로에 바로 반영되게 하고 싶다면 아래와 같은 커맨드를 사용하여 서로 싱크를 맞출 로컬 디렉토리와 container의 디렉토리를 매핑한다.

    docker run -v [local dir]:[container dir] -d -p 3000:3000 --name react-app react-image

    로컬 경로가 길어서 커멘드가 길어지면 아래와 같이 os의 현재 경로 커멘드와 함께 축약해서 쓸 수 있다.

    docker run -v ${pwd}/src:/app/src -d -p 3000:3000 --name react-app react-image

    추가한 -v 키워드는 도커의 voulme을 의미하고, volume은 컨테이너에서 생성되고 사용되는 데이터를 유지할 수 있는 방법을 제공한다.

  1. 지금까지 설정한 바에 따르면 컨테이너와 로컬 작업 레포지토리는 서로 연동되어있기 때문에 변경사항이 곧바로 반영된다. 그래서 혹시나 container 쪽에서 내가 원하지 않는 파일이 의도치않게 생성될 가능성이 있다. 이를 방지하기 위한 옵션을 추가해준다.

    	docker run -v ${pwd}/src:/app/src:ro -d -p 3000:3000 --name react-app react-image

환경 변수를 사용하는 방법

  1. Dockerfile 설정

    Dockerfile에서 환경 변수를 설정하여 컨테이너 내부에서 환경변수를 사용할 수 있다.

    # node 이미지 사용
    FROM node    
    
    # 이후 명령어를 실행하고 반영할 컨테이너 내 작업 디렉토리 설정
    WORKDIR /app 
    
    # package.json 파일을 경로(.)에 복사
    COPY package.json . 
    
    # package.json 내부의 의존성을 설치
    RUN npm install
    
    # 프로젝트의 모든 파일을 복사한다. [ 현재 작업 디렉토리의 루트 경로 : .] 에서 [ container 디렉토리의 루트 경로 : . ]로 복사
    COPY . .
    
    # 환경변수 추가
    **ENV REACT_APP_NAME=myName**
    
    # 런타임에 사용할 포트 번호 설정
    EXPOSE 3000
    
    #  react 프로젝트 시작
    CMD ["npm", "start"]

    환경변수 작성시 변수 할당 사이에 공백이 없게해야한다.

    아래와 같이 = 을 공백으로 구분해주었을 때 값으 제대로 할당하지 못하는 것을 확인했다.

    # 이렇게 하면 안됨
    **ENV REACT_APP_NAME = myName**

    docker run에 직접 입력

    그리고 아래와 같이 docker run ~ 커맨드 내부에서 설정해줄 수 있다.

    docker run -e CHOKDAR_USEPOLLING=true -e REACT_APP_NAME=sangwoo -v ${pwd}/src:/app/src -d -p 3001:3000 --name react-app react-image

    env 파일을 사용

    루트 디렉토리의 .env 파일에 환경변수를 넣고 커맨드 라인에서 해당 파일을 포함하여 실행하도록 입력한다.

    docker run --env-file ./.env -v ${pwd}/src:/app/src -d -p 3001:3000 --name react-app react-image

Doker Compose

dockerized된 여러 개의 앱을 테스팅하고 구동하고 이후 삭제하는 과정은 상당히 번거롭다.
Docker Compose는 이러한 상황에서 여러 개의 파일을 구동하는 커맨드를 가지고 있는 기술이다.

  1. 루트 경로에 docker-compose.yml 파일을 생성한다.

    version: "3.8"
    services:
      react-app:
        build: .
        ports:
          - "3001:3000"
        volums:
          - ./src:/app/src
        environment:
          - REACT_APP_NAME=park
          - CHOKIDAR_USEPOLLING=true
        # env_file:
        #   - ./.env

    docker-compose.yml 에는 여러 컨테이너의 구동 방법을 합쳐놓은 파일이라고 생각하면 이해하기 편했다.

  2. 작성 후 터미널에서 docker-compose up -d 으로 실행하면 된다.

    docker-compose up -d #새로운 컨테이너를 만들때 -d flag를 사용

  1. 가끔 docker run이 실행이 안되는 경우 docker의 i, t flag를 추가하면 될 수도 있다.

    docker run **-it** --env-file ./.env -v ${pwd}/src:/app/src -d -p 3001:3000 --name react-app react-image
    # docker-compose.yml
    version: "3.8"
    services:
      react-app:
    	  stdin_open: true,
    	  tty: true,
        build: .
        ports:
          - "3001:3000"
        volumes:
          - ./src:/app/src
        environment:
          - REACT_APP_NAME=park
          - CHOKIDAR_USEPOLLING=true
        # env_file:
        #   - ./.env
    
  2. docker-compose 를 활용하는 중에 컨테이너에 해당하는 Dockerfile이 수정하더라도, docker-compose가 자동으로 image를 갱신하지 않는다. 그래서 docker-compose flag중 —build를 활용해 docker-compose에게 해당 이미지가 다시 빌드되어야함을 알릴 수 있다.

    docker-compose up --build
  3. docker-compose down 을 통해 일괄적으로 컨테이너를 삭제할 수 있다.

    docker-compose down

profile
나도 잘하고 싶다..!

0개의 댓글