# Docker Compose

# Docker Compose

## Docker Compose란?

이전에 도커 이미지를 빌드하고 컨테이너를 빌드할 때 다양한 옵션이 달린 상당히 복잡한 명령어들을 입력해서 굴리고는 했다.

그런데 아무래도 복잡한 명령어로 여러 개의 컨테이너로 구성된 시스템을 실행하는 것은 조금 불편할 수 있다.

이를 위해 사용될 수 있는 것이 `Docker Compose`인데, 시스템 구축과 관련된 명령어를 하나의 텍스트 파일(`Compose 파일`)에 적어 복잡한 명령어 대신 한 번의 명령어로 시스템 전체를 실행하고 관리할 수 있게 하는 것이다.

도커가 사용되는 프로그램들을 보면 항상 있는 `yaml`파일들이 바로 이것이다.

여기서도 전에 옵션으로 붙여주었던 포트, 환경변수, 볼륨, 네트워크에 대한 처리도 물론 가능하다.

## Compose 파일 만들기

Compose 파일은 `docker-compose.yaml` 파일을 만들어주는 것으로 시작한다.

아래는 compose파일의 일부로

```yaml
version: "3.8"
services:
  mongodb:
    image: "mongo"
    volumes:
      - data:/data/db
    #environment:
      #MONGO_INITDB_ROOOT_USERNAME: max
      #MONGO_INITDB_ROOOT_PASSWORD: secret
    env_file:
      - ./env/mongo.env
  backend:
  frontend:
```

파이썬처럼 들여쓰기와 콜론으로 작성된다.

가장 첫 줄의 compose의 버전을 적어주는 것으로 시작해서 서비스에는 기존에 구성해놨던 디비, 백엔드, 프론트엔드를 각각 넣어준다.

보이는 것처럼 이미지와 볼륨을 위와 같이 추가해줄 수 있다. 환경변수를 하드코딩할 수도 있지만 env\_file: 를 통해 .env파일을 불러올 수도 있다.

보면 볼륨과 env\_file의 아래 요소에만 `-`가 붙어있는데, 콜론과 공백이 없는 단일 값의 경우 `-`를 붙여주어야한다.

Compose 파일 없이 작업할 때 네트워크를 설정해주었었는데, Compose파일에도

```yaml
network:
	- goals-network
```

네트워크를 추가할 수는 있으나 대부분의 경우 이 작업을 할 필요가 없다고 한다.

컴포즈 파일을 이용할 경우 도커가 이 컴포즈 파일에 특정된 모든 서비스에 대해 새 환경을 자동으로 생성하고 모든 서비스를 네트워크에 추가하기 때문에, 따로 설정해주지 않아도 하나의 네트워크 아래에서 작동한다는 것이다.

그나저나 볼륨은 따로 최상위에

```yaml
version: "3.8"
services:
  mongodb:
    image: "mongo"
    volumes:
      - data:/data/db
    #environment:
    #MONGO_INITDB_ROOOT_USERNAME: max
    #MONGO_INITDB_ROOOT_PASSWORD: secret
    env_file:
      - ./env/mongo.env
  # backend:
  #frontend:

volumes:
  data:
```

와 같이 적어줘야한다. 볼륨에 대한 정보가 있는데 이렇게 쓰는 것이 이상해보일 수 있지만 이는 명명된 볼륨을 인식하기 위해 필요한 구문이다.

### +) 리눅스에 Docker Compose 설치하기

맥과 윈도우에는 기본적으로 도커와 함께 설정되나 리눅스의 경우 따로 설치해줘야한다.

그런데 이제 `docker compose`는 도커의 cli 플러그인으로 동작하기 때문에 플러그인으로 다운받아주고

```bash
DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}                                                                                                  ─╯
mkdir -p $DOCKER_CONFIG/cli-plugins
curl -SL https://github.com/docker/compose/releases/download/v2.34.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 71.4M  100 71.4M    0     0  9696k      0  0:00:07  0:00:07 --:--:-- 11.2M

  ~ ──────────────────────────────── ✘ 255  max-env at  23:11:24 ─╮
❯ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose                 ─╯


  ~ ──────────────────────────────────────  max-env at  23:12:19 ─╮
❯ docker compose version                                             ─╯

Docker Compose version v2.34.0
```

하면 위와 같이 나온다.

## Docker Compose Up Down

현재 플러그인으로 설치되어있으므로

```bash
docker compose up
```

으로 실행해주면 된다.

이를 실행하면 뭔가 많이 쏟아져 나오는데 위로 올려보면

```bash
❯ docker compose up                                                                                                                              ─╯
WARN[0000] /home/max/devops/study_docker/section6/docker-compose.yaml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 3/3
 ✔ Network section6_default      Created                                                                                                       0.3s
 ✔ Volume "section6_data"        Created                                                                                                       0.0s
 ✔ Container section6-mongodb-1  Created                                                                                                       0.0s
Attaching to mongodb-1
```

네트워크를 컴포즈 파일에서 지정하지 않았음에도 생성된 것을 확인 가능하다. 디폴트로는 이걸 attached모드로 실행한다.

detached모드로 실행하고 싶다면

```bash
 docker compose up -d                                                                                                                           ─╯
WARN[0000] /home/max/devops/study_docker/section6/docker-compose.yaml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion
[+] Running 1/1
 ✔ Container section6-mongodb-1  Started
```

로 옵션을 붙여준다.

반대로

```bash
docker compose down
```

을 써주면 모든 컨테이너가 내려가고 생성된 디폴트 네트워크와 모든 것이 종료된다. 그러나 `-v` 플래그를 써주지 않으면 볼륨은 날아가지 않는다. 볼륨까지 날려버리려면

```bash
docker compose down -v
```

면 된다.

## 다중 컨테이너 작업하기

이제 남은 백엔드와 프론트엔드를 처리할 차례다.

가장 먼저 도커 이미지 빌드에 대한 정보를 제공할 수 있는데,

```yaml
 backend:
    #build: ./backend
    build: 
      context: ./backend
      dockerfile: Dockerfile
```

사실 도커파일이 상대경로상 백엔드 디렉토리에 있기에 주석처리된 저 부분으로도 현재 상황에선 충분하다.

볼륨과 환경변수 정보, 포트와 depends on을 적어주면 된다.

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

와 같이 적어주면 되는데, 다른 것은 특별할 게 없고 `depends on`은 도커 컴포즈에만 있는 옵션인데, 도커 컴포즈는 동시에 여러 컨테이너를 만들게 되는데 이 중 어떤 컨테이너는 이미 실행중인 특정 컨테이너에 의존할 수 있기 떄문에(여기서는 백엔드가 MongoDB에 의존하는) 적어주는 부분이다. 그러면 컨테이너 생성 순서에서 몽고DB를 우선으로, 이후에 백엔드 컨테이너를 만들어주게 된다.
