Docker기반 Redis 구축하기 - (4) Docker-Compose 설치 및 사용방법

Docker-Compose 이란?

기존에는 Docker를 이용해서 1개의 이미지를 바탕으로 하나의 소프트웨어에 대한 컨테이너를 만들 수 있었습니다. 하지만 목표는 Web Server도 설치하고, DB도 설치하고, IDE도 설치해서 한 세트로 배포를 해주고 싶은데... 지금까지 배운 방법으로는 Docker image를 내가 필요한 것만큼 다운받아서 Container를 생성해야 합니다.

이때 필요한 개념이 Docker-Compose입니다. Docker-Compose는 사용자에게 한번에 여러가지 소프트웨어에 대한 이미지 정보를 담아 빌드 할 수 있습니다. 사용자는 Docker-Compose로 만든 파일을 다운받아 이미지 내에 포함된 소프트웨어에 대한 Container를 한번에 만들 수 있습니다.

Docker-Compose 설치

1
2
#docker 공식 github에서 다운로드
sudo curl -L "https://github.com/docker/compose/releases/download/1.23.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

다운로드 받은 docker-compose 파일을 실행 가능한 파일로 만듭니다. (보통의 리눅스 실행파일 path는 /usr/local/bin입니다. OS별로 다를 수 있습니다.)

1
chmod +x /usr/local/bin/docker-compose

Docker-compose.yml

Docker-compose.yml 파일은 생성하고자 하는 Container들의 image 정보들을 담고 있는 설정 파일입니다. 여기에 설치하고자 하는 소프트웨어들의 빌드정보를 지정 할 수 있습니다. 또한 Docker에서 사용한 설정정보를 기술 할 수 있어 사용자는 파일을 받아 별도의 옵션 없이 Container만 생성하면 됩니다.

Docker-Compose.yml에서 자주 사용하는 options

build

build는 해당 이미지가 빌드 될 때 사용 할 Dockerfile을 지정할 수 있는 options입니다.

1
2
3
4
5
6
7
8
redis1:
image: redis:5.0-alpine
build:
context: ..
dockerfile: Dockerfile
args:
- buildno : 1
- username : carrey

  • context : dockerfile의 위치를 지정합니다. Default는 현재위치 (./) 입니다.

  • dockerfile : dockerfile명을 지정합니다 Default는 Dockerfile 입니다.

  • args : Dockerfile내에서 사용할 Arguments를 설정합니다.

command

command는 Dockerfile에서 CMD역할을 했던 명령을 Override합니다. (Dockerfile과 같이 사용하는 경우 Dockerfile의 CMD명령이 아닌 Docker-compose의 command명령이 실행)

1
2
redis1:
command : startup.sh -p 3000

depends_on

Docker-compose 내의 이미지가 2개 이상인 경우 실행 의존성을 줄 수 있습니다. 예를들어 DB가 먼저 실행된 다음에 WAS가 실행되어야 하는 경우 Docker-Compose에서는 depend_on 설정에 따라 다른 이미지를 먼저 빌드 합니다.

1
2
3
4
5
6
7
8
9
10
services:
web:
build: .
depends_on: //web 이미지에 대한 Container는 redis와 db가 생성되고 시작되기 전에는 빌드되지 않습니다.
- db
- redis
redis:
image: redis
db:
image: postgres

entrypoint

Container가 run 또는 start 시, entrypoint 로직을 실행 합니다. entrypoint와 Dockerfile이 함께 사용되는 경우, Dockerfile의 ENTRYPOINT설정은 무시됩니다.

1
2
3
redis1 : 
image: redis:5.0-alpine
entrypoint: /code/entrypoint.sh

env_file

Env 파일을 Container 내부에 import 하는 경우에 사용합니다.

1
2
3
ubuntu:
image: ubuntu
env_file : ../env/environments.env

environment

Container 내부에서 사용할 환경 변수를 등록합니다.

1
2
3
4
5
6
7
redis1:
environment:
- REQUIREPASS=1234
- CLIENTHOST=192.168.130.93
- CLIENTPORT=6380
- MASTERHOST=192.168.130.93
- MASTERPORT=6379

expose

Container내의 내부 포트만 설정 (외부 노출은되지 않습니다.) link된 Container끼리는 expose에 설정된 포트로 통신이 가능

1
2
3
4
web:
expose:
- "3000"
- "8000"

ports

Host OS 포트와 Container 내부포트 매핑 (포트포워딩) Host OS 포트를 사용할 수 있으므로 외부접속이 가능

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
tomcat:
ports:
- "80:8080" # <Host OS포트> : <컨테이너 내부포트>

#Short Syntax --> 권장하는 방식
ubuntu:
ports:
- "3000" #이 구문은 "3000:3000" 과 동일
- "3000-3005" #이 구문은 "3000-3005:3000-3005"와 동일
- "8000:8000"
- "9090-9091:8080-8081"
- "49100:22"
- "127.0.0.1:8001:8001"
- "127.0.0.1:5000-5010:5000-5010"
- "6060:6060/udp"

#Long Syntax --> 권장하지 않는 방식
tomcat2:
ports:
- target : 8080 #Container 내부포트
- published : 80 # 외부 OS 포트
- protocol : tcp # tcp 또는 udp
- mode : host #host: 각각의 Container 노드와 1:1로 매핑

포트 매핑 시 주의 할 점 Host : Container 형식으로 포트를 매핑하면 YAML이 xx:yy 형식은 구문 분석시에 default를 60으로 주기 때문에 60번 이하 포트에 대해서 잘못된 결과가 초래될 수 있음. (8000 : 22 와 같이 숫자만 적는 경우 문제가 발생) 따라서, 포트 매핑은 항상 문자열로 적어야 합니다. ( "8000 : 22"와 같이 문자열로 선언해야 안전합니다. ) ==> 60번 이하 포트를 쓰지말라는 소리가 아님.

image

어떤 image를 바탕으로 생성할 것인지 지정합니다.

1
2
3
4
redis: 
image: redis
ubuntu:
image: ubuntu:14.04

  • 다른 Container와 연결하기 위해 설정합니다.
  • 외부 Port노출이 안되어도 Expose명령으로 노출된 Port로 연결
  • network_mode가 host인 경우 사용할 수 없습니다. (host인 경우 Host OS의 port를 직접 사용하기 때문)
  • 서비스 이름:Alias 형태로 선언하거나 서비스 이름만 지정합니다.

1
2
3
4
5
6
7
8
web:
link:
- db:mycontainerdb-alias
- redis
db:
image: mysql
redis:
image: redis

network_mode

Docker network policy 설정 (다음 장에 상세 설명하겠습니다.)

1
2
3
4
5
network_mode: "bridge"
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"
network_mode: "container:[container name/id]"

Docker Swarm을 사용하는 경우 network_mode 옵션은 무시됩니다.

volumes

  • Host OS의 디렉터리 경로를 Container 내부의 디렉터리에 Mount 합니다. (쉽게 말해서 디렉토리가 연동됩니다.)
  • docker run -v 또는 --volume과 같습니다.
  • Dockerfile의 VOLUME[] 과 같습니다.
  • docker-compose.yml의 volumes에는 상대경로를 지정할 수 있습니다.
  • 호스트:컨테이너:권한 순으로 작성하여 읽기/쓰기 권한 설정을 할 수 있습니다. (Default는 rw)
    • ro : Container 디렉토리에서 Host OS 디렉토리의 내용을 읽을 수만 있음. Container에서 파일에 대한 수정이 불가능합니다.
    • rw : Container 디렉토리에서 Host OS 디렉토리의 내용을 읽을 수 있고, Container에서 파일 수정이 가능하고, Host OS 디렉토리에 반영이 됩니다.

1
2
3
4
5
6
7
redis: 
volumes:
- /usr/local/redis/data:/data # <Host OS 디렉터리 경로> : <Container 내부 data 경로>

volumes:
- /usr/local/redis/data:/data:ro #ReadOnly
- /usr/local/redis/data:/data:rw #ReadWrite

restart

Container 재 시작에 대한 policy를 설정합니다.

  • no : 문제가 발생하여 Container가 중지된 경우 재시작 하지 않음 (default)
  • always : 어떠한 문제로 Container가 중지되는 경우 무조건 재시작
  • on-failure : Container의 exit code 0 이 아닌 경우 재시작
  • unless-stopped : 명시적으로 중지되거나, Docker 자체가 중지되는 경우 재시작

1
2
3
4
restart: no            
restart: always
restart: on-failure
restart: unless-stopped

참고

  • https://docs.docker.com/compose/compose-file/
  • http://raccoonyy.github.io/docker-usages-for-dev-environment-setup/
  • https://www.joinc.co.kr/w/man/12/docker/Guide/DataWithContainer