Docker, Docker Compose 정리
Docker
개요
Docker란 격리된 컨테이너에서 애플리케이션을 실행할 수 있도록 도와주는 소프트웨어입니다. 로컬 환경에서 개발하는 경우 각자의 취향과 시스템에 맞도록 설정이 이미 되어있는 상태에서 애플리케이션을 구동하기때문에 다른 사람에게 똑같은 환경을 구현하거나 클라우드 서버등 다른 환경에서 배포시에 환경을 고려하여 여러가지 설정을 해줘야하는 번거로움이 있습니다. 이를 해결하기 위하여 Docker를 사용하게되면 필요한 환경정보를 모두 포함한 "컨테이너"에서 애플리케이션은 어디서 구동하던지 같은 환경으로 실행될 수 있도록 도와줍니다.
Next.js 예제
Next.js 애플리케이션의 예로 들어보겠습니다. Next.js 서버를 구동하기 위해서는 다음과 같은 설정들이 필요합니다.
- 시스템에 필요한 버전의 Node.js가 설치되어 있어야합니다.
- 시스템에 필요한 버전의 패키지 관리자 (yarn, npm, pnpm 등)가 설치되어 있어야합니다.
- 해당 패키지 매니저를 사용한 의존성 모듈들이 설치되어 있어야힙니다. (node_modules)
- 실제 구동될 Next.js 코드가 필요합니다 (git pull 등)
- 외부 데이터베이스 연결 또는 내부 데이터베이스 연결 스트링 정보를 담은
.env
파일 등 환경 변수 설정이 필요합니다.
... 등등
위와 같이 "똑같은 상태"의 애플리케이션은 로컬 PC가 아닌 다른 PC에서 실행하기 위해서는 고려해야할 체크리스트가 매우 많습니다. 또한 여기에서 실행되는 PC의 운영체제가 변경되면 고려해야할 상황은 더욱 늘어납니다.
Docker는 "도커 이미지"라는 개념을 통해 위 환경을 모두 선언하여 "컨테이너"로 만들 수 있게 도와줍니다.
도커 이미지는 Dockerfile
파일로 명시를 해 줄 수 있습니다.
Dockerfile
은 아래와 같이 어떠한 환경에서 어떠한 커맨드로 애플리케이션이 실행되는지 선언해줍니다.
Dockerfile에 대한 공식 문서는 링크에 있습니다.
# 도커 이미지는 Node-18-Alpine 버전을 사용합니다
FROM node:18-alpine
# 도커 컨테이너 내부의 /app 경로를 시작 경로로 지정합니다
WORKDIR /app
# Yarn을 통하여 node_module 의존성 모듈을 설치합니다
COPY package.json yarn.lock ./
RUN yarn
# 소스 코드를 컨테이너로 복사합니다
COPY . .
# Next.js를 빌드합니다
RUN yarn build
# 특정 포트를 호스트에 노출합니다
EXPOSE 3000
# 필요한 환경 변수를 지정합니다
ENV NODE_ENV production
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
# 서버 실행을 위한 최종 커맨드를 실행합니다
CMD ["node", "server.js"]
해당 파일을 Next.js 프로젝트 루트에 넣고 아래 커맨드를 실행하면 도커 이미지가 생성됩니다. (문서)
docker build -t ${이미지이름} .
다음 커맨드로 "도커 이미지" 목록에 이미지가 빌드되었는지 확인합니다.
docker images
다음 커맨드로 "도커 이미지"로 "도커 컨테이너를 실행합니다" (문서)
docker run --name ${컨테이너 이름} -p ${호스트 포트}:${컨테이너 포트} -d ${이미지 이름}
도커 이미지 호스팅
위와 같은 방식으로 만들어진 docker 이미지는 호스팅되어 관리되어 다중 서버에 공유될 수 있습니다. 공유 방법의 예제는 다음과 같습니다.
-
- 도커에서 제공하는 허브로, 공개 도커 이미지에 대한 호스팅은 무료입니다.
-
AWS ECR (Elastic Container Registry)
- AWS에서 제공하는 도커 저장소로, 공개 도커 이미지에 대한 호스팅은 무료입니다.
-
수동 (Manual)
-
이미지를
.tar
파일로 변경하여scp
등의 커맨드로 서버에 공유할 수 있습니다.# TAR 파일로 저장 docker save ${이미지 이름} > ${저장한 파일명}.tar.gz # TAR 파일을 이미지로 로드 docker load < ${저장한 파일명}.tar.gz
-
Docker Compose
개요
Docker Compose는 다중 컨테이너가 필요한 애플리케이션 관리에 사용되는 툴입니다.
기존에 docker-compose
라는 별도의 커맨드라인으로 사용되었었지만, 추후 docker
의 하위 커맨드로 합쳐졌습니다. (docker compose
)
Next.js - 프론트엔드 / Nest.js - 백엔드 예제
만약 Nest.js 프론트엔드 그리고 Nest.js 백엔드 애플리케이션을 구동하기위해서는 두가지 애플리케이션이 동시에 구동되어야합니다.
위의 docker run
방식을 사용하는 경우 두개의 애플리케이션은 각각 컨테이너 별로 다른 커맨드로 관리해야하는 번거로움이 있습니다.
Next.js와 Nest.js를 동시에 실행하기 위한 docker run 커맨드 예제
# 프론트엔드 도커 이미지 빌드 (/app/frontend) docker build -t frontend:1.0 . # 백엔드 도커 이미지 빌드 (/app/backend) docker build -t backend:1.0 . # 프론트엔드 도커 실행 docker run --name docker-fe -p 3000:3000 -d frontend:1.0 # 백엔드 도커 실행 docker run --name docker-be -p 4000:4000 -d backend:1.0
대신 docker compose
를 사용하게되면 아래와 같은 yaml
파일을 생성하여 하나의 파일로 어떤 컨테이너들이 애플리케이션 구동을 위해서 필요한지 관리가 가능합니다.
docker-compose.yml
# Docker Compose YAML 버전 version: "3.7" # 서비스 목록 (컨테이너 목록) services: # 프론트엔드 컨테이너 frontend: # Dockerfile 빌드 컨텍스트 build: context: /app/frontend # 호스트에 노출할 포트 매핑 ports: - 3000:3000 # 환경변수 environment: NODE_ENV: production HOSTNAME: 0.0.0.0 # 도커 컨테이너간 네트워크 network: - webapp # 재시작 규칙 restart: unless-stopped # 백엔드 컨테이너 backend: # Dockerfile 빌드 컨텍스트 build: context: /app/backend # 호스트에 노출할 포트 매핑 ports: - 4000:4000 # 환경변수 environment: NODE_ENV: production HOSTNAME: 0.0.0.0 # 도커 컨테이너간 네트워크 network: - webapp # 재시작 규칙 restart: unless-stopped # 도커 컨테이너간 네트워크 선언 (bridge 네트워크) networks: webapp: driver: bridge
위 Docker Compose파일을 사용하여 아래 커맨드로 실행하여 컨테이너 일괄 관리가 가능합니다.
# 포그라운드에서 다중 컨테이너 compose 실행
docker compose up
# 백그라운드에서 다중 컨테이너 compose 실행
docker compose up -d
# 다중 컨테이너 compose 종료 및 정리
docker compose down
# 다중 컨테이너 compose 종료 및 정리 (매핑된 도커 볼륨도 정리)
docker compose down -v