도커 컴포즈 (docker compose) 3 tier 아키텍쳐 컨테이너 띄우기

그 전 포스팅에서 Mongodb는 컨테이너로 띄웠는데, 백앤드 서버와 프론트는 아직하지 않아서 두개를 마저 작업하여 도커 컴포즈 업 해볼것이다.

Build Node API Image
---------------------

docker build -t backend .

---------------------
Run Node API Container
---------------------

docker run --name backend \
  -e MONGODB_USERNAME=june \
  -e MONGODB_PASSWORD=secret \
  -v logs:/app/logs \
  -v /Users/maximilianschwarzmuller/development/teaching/udemy/docker-complete/backend:/app \
  -v /app/node_modules \
  --rm \
  -d \
  --network goals-net \
  -p 80:80 \
  backend

이런 명령어들로 backend를 구성했었는데 제일 먼저해야하는것은 build 이다. 왜냐하면 지금 바로 backend이름을 가진 image파일이 없기 때문이다.


backend:
    build: ./backend
   # build: 
     # context: ./backend
      #dockerfile: Dockerfile-dev
    ports:
      - '80:80' 
    volumes:
      - logs:/app/logs 
      - ./backend:/app
      - /app/node_modules
    env_file:
      - ./env/backend.env
    depends_on:
      - mongodb

build

build는 Dockerfile이 있는곳을 알고싶어한다. 그래서 편리하게 상대경로로 지정을 해주면 된다.

도커파일의 이름이 Dockerfile이니까 경로만 지정하고 이름은 지정하지 않아도 된다.

 

혹시 빌드할 파일이 도커파일이 아니라 다른 파일이면 이런식으로 표현하여 도커컴포즈에게 알릴 수 있다.

context는 Dockerfile이 참조할 수 있는 모든 폴더로 설정되어야한다.

backend 폴더안의 Dockerfile은 그 폴더안의 내용만 참조한다.


ports

목록으로 지정할 수 있다. 큰따옴표 혹은 작은 따옴표 안에 '{호스트 포트}:{컨테이너 포트}'로 매핑을 해주면 된다.

컨테이너가 여러 포트를 사용하여 노출하는경우 추가하면된다.


volumes

    volumes:
      - logs:/app/logs

저장하기 위한 명명된 볼륨인 logs를 컨테이너 내부경로와 함께 연결해주고

 

      - ./backend:/app

바인드 볼륨의 경우는 상대경로로 연결해주면되서 편하다.

바인드 마운트는 제일 밑에 최상위 volumes에 명명된 볼륨을 적는 곳에 적을 필요도 없고 적을수도 없다.

 

    - /app/node_modules

익명의 볼륨은 그냥 이렇게 적어주면된다. 이것 역시 최상위 볼륨에는 적지 않는다.


environment

MONGODB_USERNAME=june
MONGODB_PASSWORD=secret

backend.env 파일을 만들어서 이렇게 키 밸류값을 넣는다.

    env_file:
      - ./backend.env

그런 다음 이렇게 env_file을 사용하여 상대경로로 backend.env파일이 있는곳을 지정해준다.


depends on

    depends_on:
      - mongodb

도커 컴포즈를 사용하여 컨테이너를 시작하면 동시에 여러 컨테이너가 생성된다.

때로는 하나의 컨테이너가 이미 실행되고 있는 다른 컨테이너에 의존할 수 있는데, 예를 들어 나의 경우backend 컨테이너는 데이터 베이스에 연결해야하기 때문에 mongodb컨테이너에 의존한다. 그래서 mongodb를 먼저 불러와야 함을 컴포즈에 알려줘야한다.

depends_on 아래에 의존하는 컨테이너의 이름을 적어주면 된다


docker compose up (mongoDB and backend)

docker compose up

컨테이너가 실행이된다.

 

docker container ls
docker logs  multi-01-starting-setup-backend-1

내가 services에 넣은 이름이랑 약간 다르다. 일단은 표시되는 이름으로 backend의 로그를 볼 것이다.

이렇게 mongodb에 잘 연결된 것을 볼 수 있다.

mongoose.connect(
  `mongodb://${process.env.MONGODB_USERNAME}:${process.env.MONGODB_PASSWORD}@mongodb:27017/backend?authSource=admin`,
  {
    useNewUrlParser: true,
    useUnifiedTopology: true,
  },
  (err) => {
    if (err) {
      console.error('FAILED TO CONNECT TO MONGODB');
      console.error(err);
    } else {
      console.log('CONNECTED TO MONGODB!!');
      app.listen(80);
    }
  }
);

내가 backend 폴더에 가지고 있는 app.js의  몽고db연결 코드는 이것인데, 실제 내가 연결하려는 백앤드 서버 컨테이너와 이름이 다른데도 연결이 잘된다. 어떻게 이럴 수 있는걸까?

내가 도커 컴포즈에 적은 서비스들의 이름은 도커에 의해서 기억된다. 코드에서 이름을 기억하여 네트워크를 연결하는 것이다. 그리고 app.js에서 mongodb라는 이름에 연결하는 것이다. 도커 컴포즈에서 할당한 이름이 달라도 여전히 작동한다.


Frontend

Build React SPA Image
---------------------

docker build -t frontend .

---------------------
Run React SPA Container
---------------------

docker run --name frontend \
  -v /Users/maximilianschwarzmuller/development/teaching/udemy/docker-complete/frontend/src:/app/src \
  --rm \
  -d \
  -p 3000:3000 \
  -it \
  goals-react

---------------------
Stop all Containers
---------------------

docker stop mongodb backend frontend

frontend 실행 명령 모음이다. 인터렉티브 모드가 필요하다 :)


 frontend:
    build: ./frontend
    ports:
      - '3000:3000'
    volumes:
      - ./frontend/src:/app/src
    stdin_open: true
    tty: true
    depends_on:
      - backends

build

backend와 마찬가지로 이미 있는 이미지를 쓰는게 아니라서 build가 필요하다. Dockerfile에 이름이 다른게 아니라 Dockerfile이니까 경로인 ./frontend를 넣어주면 된다.

도커 컴포즈를 실행할 때 마다 빌드를 다시 하지는 않는다. 이미지가 변경되었을 때 마다 빌드를 한다. (예를들어 코드변경)


Ports

호스트 머신의 포트 3000번과 도커 컨테이너의 포트 3000을 매핑해준다.


volumes

바인드 마운트가 있는데, 상대 경로로 지정해주면 간편하다.


인터렉티브 옵션 (-it)

stdin_open: true로 하여서 개방형 입력 연결이 필요하다는것을 도커에게 알리는 것이다.

그리고 tty도 터미널에 연결하기 위해 true로 설정해주어야한다.


3 tier 아키텍쳐 docker compose up

version: '3.8'
services:
  mongodb:
    image: 'mongo'
    volumes:
      - data:/data/db
   # environment:
    #  MONGO_INITDB_ROOT_USERNAME: june
     # MONGO_INITDB_ROOT_PASSWORD: secret
    env_file:
      - ./env/mongo.env

  frontend:
    build: ./frontend
    ports:
      - '3000:3000'
    volumes:
      - ./frontend/src:/app/src
    stdin_open: true
    tty: true
    depends_on:
      - backend
  backend:
    build: ./backend
   # build: 
     # context: ./backend
      #dockerfile: Dockerfile-dev
    ports:
      - '80:80' 
    volumes:
      - logs:/app/logs 
      - ./backend:/app
      - /app/node_modules
    env_file:
      - ./env/backend.env
    depends_on:
      - mongodb


volumes:
  data:
  logs:

depends _on

backend가 시작된 경우에만 frontend를 시작하게 하는것이다.

docker compose up -d

이렇게 이미지 파일을 빌드하고 컨테이너들이 실행된다.

frontend에 매핑했던 3000번 포트로 접속하니 화면을 잘 보여준다.

docker compose down을 하더라도, 볼륨을 지우는 옵션인 -v를 같이한게 아니라면 다시 실행했을때 만들었던 볼륨들이 잘 붙어있어서 데이터가 남아있는것을 확인할 수 있을것이다.

JUNE .

20'S LIFE IN SYDNEY and BUSAN

    이미지 맵

    DevOps Study/Docker 다른 글

    이전 글

    다음 글