:alert:
🐳 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
'Ops, Infra, etc > 🐋 Docker (+Swarm)' 카테고리의 다른 글
docker로 개발용 mysql 컨테이너 올린 후 원격접속하기 (0) | 2021.05.06 |
---|---|
docker 기반 nginx~react 개발 및 배포 (0) | 2021.03.26 |
node.js 기반 앱을 docker 환경에서 실행해보자 (0) | 2021.03.23 |
Dockerfile을 이용한 Docker 이미지 생성하기 (0) | 2020.09.03 |
docker 기본 명령어 (ps, stop, start, rm, logs, exec, images, network) (1) | 2020.09.03 |