본문으로 바로가기

:alert:

https://docs.docker.com/compose/

 


 

🐳 docker compose 설치

 

linux의 경우 docker compose를 별도로 설치해줘야 한다.

https://docs.docker.com/compose/install/

 

sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

docker for mac/windows로 설치한 경우 docker는 이미 docker-compose가 설치되어 있다.

 

설치가 제대로 되었는지 확인하기 위해 version 정보를 찍어보자.

docker-compose version

 

 

🐳 docker-compose 왜 씀? (= 그냥 도커 쓰면 뭐가 불편함?)

 

요약하자면, 도커 명령어를 파일로 관리해서 복잡한 도커 컨테이너 및 도커 네트워크를 구성하기에 용이하다는 것이다!

 

1. docker 보다 간결함

 

간단한 html을 만들고 nginx로 연결하려면 아래와 같이 docker 명령어를 입력해야 한다.

컨테이너 80 포트를 로컬 8080 포트와 매핑하고, 종료시 컨테이너를 삭제하기 위해 --rm 옵션을 주었고

로컬의 특정 경로의 폴더 혹은 파일을 참고하도록 volume 옵션을 통해 현재 경로 $(pwd)를 nginx 컨테이너 내에 /usr/share/nginx/html에 매핑해주자.

이 모든 과정은 이해할 수는 있지만 살짝 verbose하다. compose를 사용하면 이런 번거로운 cli를 작성하지 않고, 

docker-compose.yml을 활용할 수 있다.

docker run -it -p 8080:80 --rm -v $(pwd):/usr/share/nginx/html/ nginx

 

2. 컨테이너 간 연결이 쉬워진다.

 

아래는 postgres와 django-sample이란 컨테이너를 연결한 것이다.

--link 옵션을 주어서 django-sample 컨테이너에게 db라는 이름으로 postgres 컨테이너의 존재를 알린 것이다.

{연결할 컨테이너 이름}:{해당 컨테이너에서 참고할 이름}

역시나 verbose하다.

docker run --rm -d --name postgres \
  -e POSTGRES_DB=djangosample \
  -e POSTGRES_USER=sampleuser \
  -e POSTGRES_PASSWORD=samplesecret \
  postgres

docker run -d --rm \
  -p 8000:8000 \
  -e DJANGO_DB_HOST=db \
  --link postgres:db \
  django-sample

 

 

3. 특정 컨테이너끼리만 통신할 수 있는 가상 네트워크 환경을 관리하는데 너무 명령어가 길어진다.

 

--network 옵션을 통해서 특정 네트워트 내에만 존재하는 컨테이너끼리만 통신할 수 있도록 만들어주었다.

django2의 경우 해당 네트워크 내에 존재하지 않는 컨테이너이기 때문에 --link로 연결해도 통신할 수 없게 된다.

 

너무 verbose하다...

// network 생성
docker network create --driver bridge web-service

// 해당 network를 활용하여 컨테이너 실행
docker run --rm -d --name postgres \
  --network web-service \
  -e POSTGRES_DB=djangosample \
  -e POSTGRES_USER=sampleuser \
  -e POSTGRES_PASSWORD=samplesecret \
  postgres

docker run -d --rm --name django1 \
  --network web-service \
  -p 8000:8000 \
  -e DJANGO_DB_HOST=db \
  --link postgres:db \
  django-sample

docker run -d --rm --name django2 \
  -p 8001:8000 \
  -e DJANGO_DB_HOST=db \
  --link postgres:db \
  django-sample

 

 

🐳 docker-compose.yml

 

docker-compose를 구성하기 위한 yml 파일을 만들자. 

 

귀여운 도커 아이콘을 볼 수 있다.

앞서 구성한 도커 구성을 아래와 같이 파일 형태로 작성하여 사용할 수 있게 된다.

version: '3'

volumes:
  postgres_data: {}

services:
  db:
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgres/data
    environment:
      - POSTGRES_DB=djangosample
      - POSTGRES_USER=sampleuser
      - POSTGRES_PASSWORD=samplesecret
      
  django:
    build:
      context: .
      dockerfile: ./compose/django/Dockerfile-dev
    volumes:
      - ./:/app/
    command: ["./manage.py", "runserver", "0:8000"]
    environment:
     - DJANGO_DB_HOST=db
    depends_on:
      - db
    restart: always
    ports:
      - 8000:8000

 

실행하는 방법은 해당 docker-compose.yml이 있는 파일에 가서 docker-compose up 명령어를 입력해주면 된다.

백그라운드에서 실행하기 위해 -d 옵션도 줍시다.

docker-compose up -d

 

실행 중인 컨테이너를 내리고 싶다면 down합시다.

docker-compose down

 

 

🐳 docker-compose 명령어

 

 

docker-compose up -d // 도커 백그라운드 실행
docker-compose up --force-recreate // 도커 컨테이너 새로 만들기
docker-compose up --build // 도커 이미지 빌드 후 compose up

 

1. docker-compose up 에서 --build 플래그 여부의 차이는,

--build가 붙으면 캐싱된 이미지를 체크하지 않고 무조건 빌드를 하고 시작하라는 의미입니다.

붙이지 않고 써도 이미지에 없으면 빌드부터 시작합니다. 

소스 수정이 이루어졌을 때는 다시 이미지를 빌드해야 하므로 가급적 --build를 붙여서 compose-up을 하도록합시다.

 

2. -d (detached) 모드를 붙이면 백그라운드라서 당연히 앱 내의 출력이 터미널에 찍히지 않습니다.

 

docker-compose start // 정지한 컨테이너를 재개
docker-compose start mysql // mysql 컨테이너만 재개

docker-compose restart // 이미 실행 중인 컨테이너 다시 시작
docker-compose restart redis // 이미 실행중인 redis 재시작

docker-compose stop // gracefully stop함.
docker-compose stop wordpress

docker-compose down // stop 뿐만 아니라 컨테이너 삭제까지

docker-compose logs
docker-compose logs -f // 로그 watching

docker-compose ps // 컨테이너 목록

docker-compose exec [컨테이너] [명령어]
docker-compose exec wordpress bash // wordpress에서 bash 명령어 실행

docker-compose build // build 부분에 정의된 대로 빌드
docker-compose build wordpress // wordpess 컨테이너만 빌드

docker-compose run [service] [command] // 이미 docker-compose 가동 중인 것과 별개로 하나 더 올릴 때
docker-compose run nginx bash

 

 

🐳 docker-compose.yml 문법

 

- version

docker-compose.yml 파일의 명세 버전. 버전에 따라 도커 엔진 버전도 다르다.

뭐 쓸지는 docs.docker.com/compose/compose-file/ 참고.

version: '2'

 

- services 

 

컨테이너에 사용할 이미지 이름과 태그(버전) 태그를 생략하면 최신 버전을 설치합니다. 

이미지가 없으면 자동으로 pull하기 때문에 굳이 수작업으로 로컬에 설치할 필요 없습니다.

 

또, ports에 있어서 일반 dockerfile을 구성할 때와 마찬가지로 호스트 포트로 접근해야 내용을 볼 수 있다.

services:
  django:
    image: ...
    ports:
      - "8000:80" // 호스트 포트:컨테이너 포트
  postgres:
  	image: ....

 

restart

재시작 정책. pm2 대신 사용하기도 하기도하고, 도커 컨테이너가 실행되는 순간 접근하여 접근 시간에 따른 실패를 방지하고, 자동으로 재시작하게끔 해주기도 합니다.

여래저래 유용한 녀석입니다.

services:
  django:
    image: ...
    restart: always // "no", always, on-failure, unless-stopped
  postgres:
  	image: ....

 

build

이미지를 자체 빌드 후 사용할 경우 build를 이용할 경우에 사용합니다. 이미지 빌드를 위한 dockerfile이 필요하니까 지정해주면 됩니다.

자체 빌드니까 image 속성 대신 사용합니다.

 

docker-compose build를 통해서 빌드한 후 docker-compose up해주면 된다.

services:
  django:
    build:
      context: .
      dockerfile: ./compose/django/Dockerfile-dev 
  postgres:
  	image: ....

 

environment

 

사용하고자 하는 이미지의 환경 변수.

여기서, dockerfile의 환경변수와 docker-compose.yml의 환경변수가 중복되어서 올라가면 어떻게 되느냐?는 의문이 생깁니다.

우선순위는 다음과 같습니다. 즉, docker.compose.yml이 덮어쓰게 됩니다.

 

1. docker-compose [run / exec] -e key:value

2. docker-compose.yml의 environment

3. Dockerfile의 ENV

 

services:
  db:
    image: mysql:5.7 // 사용할 이미지
    volumes:
      - ./mysql:/var/lib/mysql // 볼륨(컨테이너가 죽어도 데이터를 유지)
    restart: always // 컨테이너가 죽지 않고 계속
    environment: // 환경변수
      MYSQL_ROOT_PASSWORD: wordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress

 

volumes

services:
  nginx:
    image: nginx
    ports:
      - 8080:80
    volumes:
      - ./:/usr/share/nginx/html
    link:
      - mysql:db

 

link (legacy)

docker cli 사용할 때 --link와 동일하다. {연결할 컨테이너 이름}:{해당 컨테이너에서 참고할 이름}

그러나 기본적으로 docker-compose 내부에선 모든 컨터네이너가 소통할 수 있기 때문에 사용되지 않음.

 

services:
  nginx:
    image: nginx
    ports:
      - 8080:80
    link:
      - mysql:db

 

 

depends_on

의존성 명시다. 예를 들어 아래와 같이 써 있다면, nginx는 mysql에 의존하고 있으므로 mysql 이미지가 먼저 실행된 후에 그 다음에 nginx 이미지가 실행된다.

services:
  mysql:
    image: mysql
    ...
  nginx:
    image: nginx
    ports:
      - 8080:80
    depends_on:
      - mysql

 

 

다양한 docker-compose.yml 작성 예시들

 

1. 간단히 Nginx 올리기

 

docker run -it -p 8080:80 -v $(pwd):/usr/share/nginx/html nginx로 실행하던 것을 docker-compose.yml로 만들면 다음과 같이 작성될 수 있다. cli 환경이 아니니까 $(pwd)꼴로 사용못하고, 직접 경로를 준 것만 다르다.

version: '3'

services:
  nginx:
    image: nginx
    ports:
      - 8080:80
    volumes:
      - ./:/usr/share/nginx/html

 

 

2. 워드프레스

 

mysql 실행하면서 읽어들이는 환경 변수들이 있으니 아래처럼 설정해주고,

db를 먼저 켜도록 depends_on을 wordpress에 세팅해주면 된다.

version: '3'

services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: rootpwd
      MYSQL_DATABASE: databasename
      MYSQL_USER: user
      MYSQL_PASSWORD: userpwd

  wordpress:
    image: wordpress
    ports:
      - 8080:80
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wp
      WORDPRESS_DB_PASSWORD: wp
      WORDPRESS_DB_NAME: wp
    depends_on:
      - db

volumes:
  db_data: {}

 

3. flask + redis 조합

 

dockerfile로 빌드한 후에 compose로 올렸습니다.

docker-compose up -d --build

 

FROM python:3.7-alpine

WORKDIR /code

ENV FLASK_APP app.py
ENV FLASK_RUN_HOST 0.0.0.0

RUN apk add --no-cache gcc musl-dev linux-headers
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

COPY . .

CMD ["flask", "run"]
version: '3'

services:
  redis:
    image: redis
    ports:
      - 6379:6379
    restart: always

  flask:
    image: whateveryouwant
    build:
      context: .
      dockerfile: .
    ports:
      - 5000:5000
    depends_on:
      - redis
    restart: always

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체