일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- minikube mac 설치
- minikube 설치 방법
- iterm2 shortcuts
- AWS
- customize
- Shell
- 빅오노테이션
- terraform 문법
- zshrc
- linux
- docker-compose
- sftp란
- zsh
- 테라폼 문법
- 테라폼 기본 문법
- 도커컴포즈
- Bash
- Django
- iterm2 단축키
- test
- 도커
- 컨테이너
- server
- docker
- python
- 파이썬
- nosql
- terraform
- DynamoDB
- BIG-O NOTATION
- Today
- Total
sklass의 s-class 프로그래밍 blog
[Docker] docker-compose 본문
Docker Compose 란?
여러 개의 컨테이너를 정의하고 실행하기 위한 도구로, 쿠버네티스처럼 yaml 파일을 이용해서 여러 응용 프로그램의 컨테이너를 정의하고 서비스를 구성할 수 있습니다.
Docker Compose에 대해 알아보기 전, Docker Compose를 쓰지 않을때의 불편한 점이 뭐였길래 Docker Compose가 개발되었는지 살펴보겠습니다.
Django를 도커로 실행하고 싶을 경우, 데이터베이스 서버와 django 서버 둘다를 도커 컨테이너화 해야하는데요. 기본적으로 도커 컨테이너들은 각각 격리된 환경에서 실행됩니다. 다시 말해, 별도의 옵션을 지정하지 않으면 다른 컨테이너의 존재를 알 수 없습니다. 따라서, 데이터베이스 서버를 먼저 실행한 후 django 서버를 실행해야하지만, django 컨테이너는 데이터베이스 컨테이너가 실행되었는지 여부를 알지 못합니다.
따라서, django 컨테이너에게 데이터베이스 컨테이너의 존재를 알려주기 위해서는 다음 과정을 거쳐야합니다.
- 데이터베이스 컨테이너를 실행하면서 컨테이너 이름을 붙이고(db라고 하겠습니다.)
- django 컨테이너를 실행할 때 db 컨테이너를 연결해줍니다.
먼저 데이터베이스 컨테이너를 실행해보겠습니다.
$ docker run --it --rm \
--name db \
-e POSTGRES_DB=djangosample \
-e POSTGRES_USER=sampleuser \
-e POSTGRES_PASSWORD=samplesecret \
--volume=$(pwd)/docker/data:/var/lib/postgresql/data \
postgres
- --it: 추가하면 컨테이너를 현재 프롬프트에서 실행시킵니다. 삭제하면, 데몬으로 background에서 실행시킵니다.
- --name: 데이터베이스 컨테이너에 이름을 설정합니다. 위의 경우, 데이터베이스 컨테이너 이름을 db로 설정했습니다.
- -e: 환경변수를 설정하여 컨테이너를 실행시킵니다. 여기서는 컨테이너 시작과 함께 djangosample 데이터베이스를 만들고(POSTGRES_DB) sampleuser라는 사용자에게 접속 권한을 부여(POSTGRES_USER, POSTGRES_PASSWORD)합니다.
- --volume: --rm 옵션을 지정하면, 데이터베이스 컨테이너가 종료와 함께 삭제되면서 컨테이너 내부에 쌓였던 데이터베이스 데이터들도 모두 사라집니다. 깔끔하지만, 매번 개발용 데이터를 쌓기가 귀찮을 수 있습니다. 따라서 --volume 옵션을 통해서 데이터베이스 컨테이너 내부의 디렉토리(/var/lib/postgresql/data)를 로컬 컴퓨터의 디렉토리($(pwd)/docker/data)로 연결해줍니다. 이제 데이터베이스가 데이터를 저장할 파일 시스템으로 로컬 컴퓨터의 $(pwd)/docker/data 디렉터리도 추가되면서, 데이터베이스가 컨테이너 종류와 함께 삭제되는걸 방지할 수 있습니다.
아래 링크는 도커 허브의 공식 포스트그레SQL 저장소로, 설정할 수 있는 환경 변수 종류를 확인할 수 있습니다.
https://hub.docker.com/_/postgres/
Postgres - Official Image | Docker Hub
We and third parties use cookies or similar technologies ("Cookies") as described below to collect and process personal data, such as your IP address or browser information. You can learn more about how this site uses Cookies by reading our privacy policy
hub.docker.com
이제 django 컨테이너를 실행하면서 db 컨테이너를 연결(link)해주는 코드를 살펴보겠습니다. 아래의 명령어로 django-sample 이라는 이미지를 컨테이너로 실행하고 db 컨테이너까지 연결해보겠습니다.
$ docker run -it --rm \
-p 8000:8000 \
--link db \
-e DJANGO_DB_HOST=db \
-e DJANGO_DEBUG=True \
--volume=$(pwd):/app/ \
django-sample \
./manage.py runserver 0.0.0.0:8000
- -p: 포트넘버로, :을 기준으로 왼쪽 8000은 로컬의 포트, 오른쪽 8000은 컨테이너의 포트를 의미합니다.
- --link: 참조할 다른 컨테이너를 지정합니다.
- --volume: 이 옵션을 사용하면, 로컬 디렉토리의 특정 경로를 컨테이너 내부로 마운트할 수 있습니다. 따라서 로컬의 코드를 바꿀때마다 컨테이너 속 코드도 똑같이 바뀌게 됩니다. $(pwd)는 위의 명령어를 실행하는 현재 디렉토리의 절대 경로입니다.
Docker Compse의 탄생 배경
이처럼 도커로 독립된 개발 환경을 빠르게 구성할 수 있었지만, 아래와 같은 몇몇 불편한 부분이 남았습니다.
- 장황한 옵션
- 개발 서버를 실행할 때마다 장황한 도커 명령어의 옵션들을 적기가 귀찮고, 헷갈리기도 해서 빼먹는 경우가 종종 존재합니다.
- 앱 컨테이너와 데이터베이스 컨테이너의 실행 순서
- 반드시 데이터베이스 컨테이너를 실행한 다음에 django 컨테이너를 실행해야 합니다. 그렇지 않으면 django 컨테이너에서 데이터베이스 컨테이너를 찾을 수 없기 때문인데요. 이 순서를 지키지 않으면 컨테이너를 다시 다 종료하고 재실행시켜야한다는 불편함이 존재합니다.
이러한 불편한 점들을 해결하기 위해서 docker compose라는 도구가 나옵니다. docker compose를 사용하면, 컨테이너 실행에 필요한 옵션을 docker-compose.yml이라는 파일에 적어둘 수 있고, 컨테이너 간 실행 순서나 의존성도 관리할 수 있게됩니다.
Docker Compose 예제
1.1 선행 조건
이후의 과정을 따라하려면, 도커 엔진의 버전이 1.13.1 이상이어야 하고, 도커 컴포즈의 버전은 1.6.0 이상이어야 합니다.
1.2 docker-compose.yml 생성
docker-compose.yml은 장황한 도커 실행 옵션을 미리 적어둔 문서라고 볼 수 있습니다. 아래와 같이 docker-compose.yml을 생성합니다.
version: '3'
services:
db:
image: postgres
volumes:
- ./docker/data:/var/lib/postgresql/data
environment:
- POSTGRES_DB=sampledb
- POSTGRES_USER=sampleuser
- POSTGRES_PASSWORD=samplesecret
- POSTGRES_INITDB_ARGS=--encoding=UTF-8
django:
build:
context: .
dockerfile: ./compose/django/Dockerfile-dev
environment:
- DJANGO_DEBUG=True
- DJANGO_DB_HOST=db
- DJANGO_DB_PORT=5432
- DJANGO_DB_NAME=sampledb
- DJANGO_DB_USERNAME=sampleuser
- DJANGO_DB_PASSWORD=samplesecret
- DJANGO_SECRET_KEY=dev_secret_key
ports:
- "8000:8000"
command:
- python manage.py runserver 0:8000
volumes:
- ./:/app/
위의 파일을 하나하나 보겠습니다.
1.2.1 version
version: '3'
docker-compose.yml 파일의 첫 줄에는 파일 규격 버전을 적습니다. 파일의 규격에 따라 지원하는 옵션이 달라지는데, '3'이라고만 적으면 3으로 시작하는 최신 버전을 사용한다는 의미입니다.
1.2.2 services
services:
이 항목 밑에 실행하려는 컨테이너들을 정의합니다. 컴포즈에서는 컨테이너 대신 서비스라는 개념을 사용합니다.
1.2.3 db
services:
db:
postgres 서비스의 이름을 db로 정합니다.
1.2.4 image
services:
db:
image: postgres
db 서비스에서 사용할 도커 이미지를 적습니다. 여기서는 https://hub.docker.com/_/postgres/ 에서 dockerhub의 공식 postgres 이미지를 사용합니다.
1.2.5 volumes
services:
db:
volumes:
- ./docker/data:/var/lib/postgresql/data
docker run으로 db 컨테이너를 실행할 때 --volume 옵션을 사용하여 데이터베이스의 데이터를 로컬 컴퓨터에 저장했던 부분과 같습니다. 다만 docker-compose.yml의 volumes에는 상대 경로를 지정할 수 있어서 편리합니다.
docker run으로 db 컨테이너를 실행할 때와 마찬가지로, 프로젝트 루트 아래의 docker/data 디렉토리와 데이터베이스 컨테이너의 /var/lib/postgresql/data 디렉토리를 마운트시켜서, 각각의 폴더에 생기는 변화를 다른 한쪽에 자동으로 반영시킵니다.
1.2.6 enviornment
services:
db:
environment:
- POSTGRES_DB=sampledb
- POSTGRES_USER=sampleuser
- POSTGRES_PASSWORD=samplesecret
- POSTGRES_INITDB_ARGS=--encoding=UTF-8
docker run 명령어의 -e 옵션에 적었던 내용들입니다. 마지막의 POSTGRES_INITDB_ARGS 부분이 추가되었는데, 데이터베이스 서버의 인코딩을 UTF-8로 설정하기 위함입니다.
1.2.7 django
services:
django:
앱 서비스의 이름을 django로 지정하였습니다.
1.2.8 build
services:
django:
build:
context: .
dockerfile: ./compose/django/Dockerfile-dev
db 서비스와 달리 앱 서비스는 특정 이미지 대신 build 옵션을 추가합니다.
context는 docker build 명령을 실행할 디렉토리 경로라고 보시면 됩니다.
dockerfile에는 개발용 도커 이미지를 빌드하는데 사용할 Dockerfile을 지정하면 됩니다.
1.2.9 environment
services:
django:
environment:
- DJANGO_DEBUG=True
- DJANGO_DB_HOST=db
- DJANGO_DB_PORT=5432
- DJANGO_DB_NAME=sampledb
- DJANGO_DB_USERNAME=sampleuser
- DJANGO_DB_PASSWORD=samplesecret
환경 변수는 docker run 을 할 때보다 좀 더 자세하게 적었습니다. 각 값은 앱 서비스의 환경 변수로 설정되며, Django 설정 파일(djangosample/settings.py)에서 불러와 사용하게 됩니다. (데이터베이스 관련 정보들은 db 서비스에서 설정한 값들과 일치해야 합니다.)
1.2.10 ports
services:
django:
ports:
- "8000:8000"
docker run 명령어의 -p 옵션에 해당하는 부분입니다.
1.2.11 command
services:
django:
command:
- python manage.py runserver 0:8000
docker run으로 앱 컨테이너를 실행할 때 가장 마지막에 적었던 명령어 부분입니다.
1.2.12 volumes
services:
django:
volumes:
- ./:/app/
docker run으로 앱 컨테이너를 실행할 때 -v 옵션을 사용하여 프로젝트 루트 디렉터리를 컨테이너 안의 /app 디렉터리와 연결했던 부분과 같습니다.
1.3 실행
docker-compose.yml을 모두 작성했고, 이제 서비스를 아래의 명령어로 실행합니다.
$ docker-compose up -d
이제 http://127.0.0.1:8000에 접속해보면 개발 서버가 잘 작동함을 확인할 수 있습니다.
docker-compose를 사용함으로써, 각 컨테이너를 실행하던 길고 복잡했던 명령어들을 docker-compose.yml 파일에 요약해서 실행하니 훨씬 편리하단걸 알 수 있습니다.
1.3.1 네트워크 관련
현재 docker-compose.yml에는 db와 django라는 2개의 서비스가 들어있습니다. 그런데 어떻게 --link 옵션을 주지 않고도 django 서비스에서 db 서비스를 찾을 수 있었을까요?
도커 컴포즈 파일 버전 2일 때는 다음과 같이 links 라는 항목으로 연결할 서비스를 명시하곤 했습니다.
services:
django:
links:
- db
하지만 도커 컴포즈 파일 버전 3으로 와서는 links 항목을 사용하지 않더라도 한 네트워크 안에 있는 서비스끼리 서로 통신할 수 있습니다. (한 docker-compose.yml 안에 있는 서비스들은 별도로 지정하지 않으면 하나의 네트워크에 속합니다.)
1.4 개발용 Dockerfile을 별도로 관리하기
앞에서 개발 서버용 Dockerfile-dev 파일을 짧게 언급했었는데, 이는 개발용과 배포용 Dockerfile을 따로 관리함으로써 개발을 좀더 쉽게 하기 위함입니다.
Dockerfile-dev 의 내용은 아래와 같습니다.
FROM python:3
RUN apt-get update && apt-get -y install \
libpq-dev
WORKDIR /app
ADD requirements.txt /app/
RUN pip install -r requirements.txt
# ADD ./djangosample /app/djangosample/
# ADD ./manage.py /app/
# CMD ["python", "manage.py", "runserver", "0:8000"]
위에서 주석으로 처리한 부분들은 원래 Dockerfile에는 있었지만 개발 서버용 도커 이미지에서 삭제한 내용입니다.
참고로 CMD는 도커 컴포즈의 command로 관리하는 편이 더 쉽습니다.
1.5 파이썬 로그가 한 발 느리게 출력되는 문제 해결
도커 컴포즈에서 파이썬 로그가 한 발 늦게 출력된다는 느낌을 받을 때가 있습니다. 파이썬에서 출력 버퍼가 기본으로 작동하면서 출력 로그를 붙잡고 있기 때문인데요. 이 버퍼링을 없애려면 PYTHONUNBUFFERED 환경변수를 추가하면 됩니다.
Dockerfile-dev에 다음 내용을 추가합니다. (설정할 값은 0이든 1이든 상관 없고, 환경변수가 존재하기만 하면 됩니다.)
ENV PYTHONUNBUFFERED=0
References
https://www.44bits.io/ko/post/almost-perfect-development-environment-with-docker-and-docker-compose
도커(Docker) 컴포즈를 활용하여 완벽한 개발 환경 구성하기
개발 환경을 구축하기란 그리 쉬운 일이 아닙니다. 문서화를 해두어도 누군가 계속 신경쓰지 않으면 내용이 낡기 마련이고, 계속 신경 쓰자니 이 또한 쉽지 않죠. 어떻게 하면 손쉽게 개발 환경
www.44bits.io
'docker' 카테고리의 다른 글
[docker] 로컬 컴퓨터에서 컨테이너간 api 호출을 하기 위한docker.for.mac (0) | 2021.12.17 |
---|---|
Ubuntu에 Docker & docker-compose 설치 및 이미지 생성과 실행 (0) | 2021.12.07 |
[Docker] docker-compose의 주요 명령어 (0) | 2021.10.09 |
도커(Docker) 기초 (0) | 2021.08.25 |