본문 바로가기
docker-kub

docker - Docker Compose, utility container

by 오우지 2022. 11. 13.

Docker Compose

지금까지 하나의 컨테이너 실행을 위해서 길고 긴 명령어를 사용해야 했다. 명령어가 길어지면 오류가 생길 가능성이 높다. 또한 배포 환경에서는 적합하지 않다.

 

Docker Compose란?

- docker build와 docker run 등의 명령을 대체할 수 있는 일종의 자동화 도구, 설정파일로 다중 컨테이너 애플리케이션을 시작하거나 중단할 수 있다.

- Dockerfile나 Image, Container 대체하는 개념이 아니다.

- 단일 호스트에서 멀티 컨테이너 환경을 구축하고자 할 때 적합하다

 

version: '3.8'
services:
  mongodb:
    image: 'mongo'
    # 몽고DB 이미지 이름 지정
    volumes:
      - data:/data/db # 명명된 볼륨
    container_name: mongodb # 원래 컨테이너 이름은 자동으로 지어지지만 이렇게 커스텀도 가능
    # environment:
      # MONGO_INITDB_ROOT_USERNAME: hojin
      # MONGO_INITDB_ROOT_PASSWORD: secret
      # - MONGO_INITDB_ROOT_USERNAME=hojin
      # - MONGO_INITDB_ROOT_PASSWORD=secret
      # key:value 형태인 경우 :만 사용해도 되지만 단일 값인경우 - 필요
    env_file:
      - ./env/mongo.env
      # 외부 환경변수 파일을 이용하기 위한 설정
    # networks:
      # - goals-net
    # 자체 네트워크를 사용하려면 명시하면 되고 그게 아니라면 자동으로 동일 네트워크에 지정된다.
  backend:
    # image: 'goals-node' # 도커 컴포즈는 이미지 빌드 단계도 대체할 수 있다.
    build: ./backend # 빌드해야 하는 Dockerfile을 찾을 수 있는 위치
    # build:
      # context: ./backend # context는 항상 Dockerfile과 빌드할 이미지 폴더의 상위 루트여야 한다.
      # dockerfile: Dockerfile
      # args:
      #   some-arg: 1
    ports:
      - '80:80'
    volumes:
      - logs:/app/logs
      - ./backend:/app # 기존 명령어에서 사용했던 바인트마운트 절대 경로를 docker-compose에서는 상대경로를 사용 가능
      - /app/node_modules
    env_file:
      - ./env/backend.env # 환경변수를 가져올 루트
    depends_on: # 의존성을 가지고 있는 컨테이너가 있을 경우를 위한 의존성 지정
      - mongodb
  frontend:
    build: ./frontend # 도커 컴포즈는 코드 변경을 감지해 자동으로 리빌드된다
    ports: '3000:3000'
    volumes:
      - ./frontend/src:/app/src # 코드 변경사항을 유지하기 위한 바운드마운트
    stdin_open: true # 개방형 서비스에 개방형 입력 연결이 필요함을 알림
    tty: true # 해당 터미널에 연결하기 위함
    depends_on:
      - backend

volumes:
  data:
  logs:
  # 도커가 services를 위해 생성해야 하는 명명된 볼륨을 생성하기 위한 명령어

 

docker-compose up                  docker-compose 파일을 실행
docker-compose up -d               detached 모드로 실행
docker-compose down                docker-compose를 종료
docker-compose down -v             data 볼륨도 제거
docker-compose up --build          build를 강제
docker-compose build               이미지를 build만 하고 실행은 X

위대로 도커컴포즈를 실행하면 자동으로 docker-compose_backend_1이라는 이름으로 컨테이너가 실행된다. 하지만 코드상의 env로 접근한 mongodb를 그대로 사용할 수 있는데 이는 mongodb를 서비스 이름으로 사용했기 때문에 자동으로 하나의 네트워크 안에서 접근 가능하다.

 

utility container

기본적인 도커의 사용법은 어플리케이션 하나당 Dockerfile을 통해 각각의 컨테이너를 띄우고 컨테이너들을 docker compose 등을 이용해 run 하는 것이다. 하지만 도커에는 다른 용도가 있을 수 있다. 그 대표적인 예시가 유틸리티 컨테이너다.

 

도커를 이용하면 시스템에 노드를 설치하지 않고 노드 어플리케이션을 사용할 수 있는데 

docker run -it node

이렇게 입력하면 interactive 모드로 node를 실행할 수 있다.

docker exec

컨테이너 안에서 dockerfile에서 명시한 명령어들 외에 추가로 execute할 수 있다.

이렇게 실행중인 컨테이너에서도 프로젝트를 설치할 수 있다.

 

이제 어떤 프로젝트를 빌드한다고 생각해보자.

FROM node:14-alpine

WORKDIR /app

CMD npm init

기본 설정이 다음과 같을 때 사용자에게 init을 강요하지 않고 더 자유로운 사용성을 주기 위해서 npm init을 제거하고 이미지를 빌드해보자.

 

docker build -t node-util .

이제 컨테이너를 시작해보자.

 

docker run -it node-util npm init

이렇게 시작해주면 npm init 명령어는 위에서 설정한 /app 디렉토리 내부에서 실행되게 된다. 그걸 바인드 마운트로 로컬 폴더메 미러링해보자.

 

docker run -it -v /Users/hojin/Desktop/git_local/docker-study/utility_setup:/app node-util npm init

이렇게 사용하면 로컬 머신에 어떤 프로그램을 설치할 일 없이 도커를 이용해 간단하게 어플리케이션을 제작할 수 있다.

 

여기에 Dockerfile에 ENTRYPOINT라는 속성을 사용할 수 있는데

 

Dockerfile을 다음과 같이 작성하고

FROM node:14-alpine

WORKDIR /app

ENTRYPOINT [ "npm" ]

이미지를 생성해주면 뒤에 적은 npm init 대신 init만 적어줘도 실행 가능하다.

docker run -it -v /Users/hojin/Desktop/git_local/docker-study/utility_setup:/app mynpm init

이제 이걸 이용해서 해당 node 프로젝트에 express를 추가해보면

docker run -it -v /Users/hojin/docker:/app mynpm install express --save

이렇게 모듈들이 들어온 것을 볼 수 있다. 이제 docker run 뒤에 들어가는 귀찮은 명령어들을 dockerCompose로 이식해보자.

 

version: '3.8'
services:
  npm:
    build: ./
    stdin_open: true
    tty: true
    volumes:
      - ./:/app

명령어는 다음과 같이 적어주면 된다.

단일 컨테이너를 docker compose로 실행해주는 경우 

docker-compose run npm init

이렇게 npm에서 init을 해달라고 요청 가능하다