[Project] docker 사용해보기

do_Rang·2025년 6월 13일

Project

목록 보기
2/7

정신없이 프로젝트를 진행하느라 오랜만에 블로그를 작성해본다.
프로젝트는 이미 종료되었지만, 하면서 기억에 남는 내용을 작성해보려 한다. 이번엔 정말 성실하게..!!

가장 먼저 Docker에 대한 내용을 다뤄보겠다.
현재 진행하고 있는 프로젝트의 디렉토리 구조는 다음과 같다.

📦 
├─ README.md
├─ backend
├─ frontend

프로젝트를 진행하면서 불편했던 점이 두 가지 존재했다.

🤔 문제

  1. 각 파트별 작업에서는 문제가 없었지만, 연결해서 작업할 때 cmd창을 두개 열어서 각 폴더 내에서 build, start 해야하는 번거로움이 있었다.

  2. 백엔드에서는 redis를 사용했기 때문에 개발 코드 외적으로 redis를 설치 후 실행시켜줘야 했다.

🚀 Docker를 사용해보자

Docker란?

Go언어로 작성된 리눅스 컨테이너 기반의 오픈소스 가상화 플랫폼이다.

Docker를 사용하기 전 여러 자료들을 찾아봤지만 이해가 쉽게 되지는 않았다. 그래도 이해한 내용을 몇 자 적어보자면

  1. 개발한 프로그램들을 컨테이너 안에 넣어서 관리한다.

  2. 이 여러 개의 컨테이너를 한 번에 실행시켜도 각각 독립적으로 실행되기 때문에, 서로 영향을 주지 않는다.

  3. 내가 로컬 환경에서 실행시켰을 때 내 로컬 포트번호와 매칭된 도커 이미지의 포트번호, 컨테이너 내부의 포트번호로 실행이 되는 것이다. 이는 로컬 환경에 아무런 영향을 주지 않는다.

그럼 이제 본격적으로 Docker 사용 방법에 대해 작성해보자.

Dockerfile이란?

내 프로젝트의 구조는 backend, frontend 가 분리되어 있다.
각각 build해서 실행해야 하기 때문에, 먼저 각 폴더에 Dockerfile을 작성해주어야 한다.

Dockerfile에 들어가야 하는 내용
FROM : 베이스 이미지 (ex) Node, ubuntu
WORKDIR : Docker 이미지 안에 작업할 디렉토리 (ex) /app
RUN : 컨테이너 안에서 실행할 명령어
CMD : 컨테이너가 시작될 때 실행할 명령어

이 외에도 많지만 일단 이정도만 작성하겠다.

실제 Dockerfile 작성해보기

  • backend Dockerfile
FROM node:18 AS builder 

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . . 

RUN npm run build 

FROM node:18-slim

WORKDIR /app

COPY --from=builder /app/build /app/build 

COPY package*.json ./
RUN npm install --only=production 

CMD ["npm", "start"]

Dockerfile에 COPY부분을 보면 알겠지만 내 파일을 다 COPY하고 이런저런 작업을 실행하다 보니 image 실행할 때는 시간이 꽤 걸리는 편이다.

이 때 Docker는 레이어 캐싱을 하기 때문에 COPY한 파일에 변경이 있을 때만 새로 RUN 작업을 한다.
package.json은 잘 변하지 않는 파일이기 때문에 기존 캐싱된 내용을 불러올 수 있도록 하기 위해 분리해서 작업해주었다.

‼️물론 COPY . . 으로 전체 파일을 복사하기보다 필요한 파일을 지정해주는 것이 좋다!!

또한, 타입스크립트를 사용하고 있기 때문에 앞서 npm run build를 한 뒤 조금 더 가벼운 베이스 이미지로 변경해서 build된 파일만 복사한 뒤 npm start하도록 했다.

docker-compose.yml 작성

frontend 폴더에도 비슷하게 Dockerfile을 작성해준 뒤 두 이미지를 하나로 묶는 docker-compose.yml 파일을 작성해야 한다.

services:
  backend: 
    build: ./backend
    ports:
      - "5000:5000"
    networks:
      - mynetwork
    env_file:
      - ./backend/.env
    environment:
      REDIS_HOST: redis 
      REDIS_PORT: 6379 
    depends_on:
      - redis
    # extra_hosts:
    #   - "host.docker.internal:host-gateway"

  redis: 
    image: redis:latest 
    ports:
       - "6379:6379"
    networks:
      - mynetwork

  frontend:
   build: ./frontend
   ports:
     - "5173:80"
   networks:
      - mynetwork
   depends_on:
     - backend 

networks:
  mynetwork:
    driver: bridge

docker-compose 파일은 yarn 문법을 사용한다.
주요한 것만 나중에 다시 볼 수 있도록 작성하겠다.

  • build : 이미지를 생성할 때 build할 폴더
    전 단계에서 만든 Dockerfile을 바탕으로 새로 build
  • image : 미리 생성해 둔 이미지가 있다면 image이름을 작성해서 바로 불러올 수 있다. build보다 빨리 된다.
  • ports : 내 로컬 포트 : 도커 컨테이너 내부의 포트 매칭
  • depends_on : 해당 이미지가 참조하는 이미지 (참조할 경우 그 이미지의 실행이 선행되었을 때 실행한다.)

실행

이렇게 실행했을 때 backend, redis, frontend 각각의 이미지가 만들어서 하나의 컨테이너 안에서 돌아갈 수 있도록 설정해보았다. 실행은 정말 간단한다. docker-compose.yml 파일이 위치해있는곳에서 다음 명령어를 입력하자.

docker compose up -d
# d는 백그라운드 실행 옵션
# 터미널에서 다른 작업을 하고 싶을 때 추가

# 만약 아까 언급했던 레이어 캐싱을 날리고 싶다면
#  --build 옵션도 추가해보자.
# 새로 이미지를 build 할 수 있다.

결과

  • 이미지들이 모두 실행되는 것을 확인 (터미널과 Docker desktop)

  • backend, redis, frontend가 정상 연결되는 것을 확인

🤗 결론

  • 최근 왜 핫하고 많이들 사용하는지 느낄 수 있었다.
  • 도커 이미지를 이용해서 다른 개발 환경에 가도 다른 사람과 동일한 환경 (컨테이너) 위에서 돌아가니, 개발 변수를 줄일 수 있을 것 같다.
  • 다른 개발 환경에서도 별도의 설치가 필요 없다는 것이 가장 큰 장점인 듯 하다!! Docker는 설치해야 한다..

앞으로의 프로젝트에서는 docker를 많이 사용할 것 같다!

profile
공부하자

0개의 댓글