Docker (Compose) 활용 - 개발 환경 구성하기

Post on 14-Apr-2017

2.189 views 12 download

Transcript of Docker (Compose) 활용 - 개발 환경 구성하기

Docker 활용법 ‐ 개발 환경 구성하기

raccoonytwi�er.com/@raccoonyy

사전 학습

근데 도커가 뭐야?

(추천) subicura님의 초보를 위한 도커 안내서 시리즈1. 도커란 무엇인가?

2. 설치하고 컨테이너 실행하기

3. 이미지 만들고 배포하기

(사족)

도커(클래스와 인스턴스에 비유하자면)Dockerfile: 서버 구성을 문서화한 것(=클래스 정의가 들어 있는 파일)

docker build: 도커 이미지 만들기(=클래스 정의를 애플리케이션에 로드)

docker run의 옵션들: 이미지에 붙이는 장식들(=인스턴스의 변수들)

docker run: 장식 붙은 이미지를 실제로 실행(=인스턴스 생성)

다음 저장소를 클론하세요파이썬/Django용 예제 프로젝트

노드/Express용 예제 프로젝트

개발 환경 구성 시작

파이썬+장고 프로젝트를 예로 들면,$ pyenv install (파이썬 버전)$ pyenv virtualenv (파이썬 버전) (가상환경이름)(가상환경이름) $ pip install -r requirements.txt...

한 번에 되면 좋겠지만...패키지 설치가 막힐 때도 있음(SSL, LDAP 관련)서버 환경이랑 같지 않아서 발생하는 문제들

로컬의 다른 환경이랑 꼬임!oTL

배포 환경에서는 도커 활용 중

아 간단하다...

개발 환경 설치하기 귀찮으니까

개발 환경도 도커로 해볼까?

일단 이미지 빌드하고$ docker build -t django-sample .

앱 컨테이너 실행$ docker run -it --rm \ -p 8000:8000 \ django-sample \ ./manage.py runserver 0:8000

데이터베이스에 접속이 안 되네?

데이터베이스 컨테이너 실행$ docker run -it --rm \ postgres:9.6.1

그래도 개발 서버는 실행되지 않는다

문제점 1앱 컨테이너가 PostgreSQL 컨테이너를 못 찾음

앱 컨테이너에서 데이터베이스 컨테이너를 찾을 수 있게 하자 (1/2)$ docker run -it --rm \ --name db \ -e POSTGRES_DB=djangosample \ -e POSTGRES_USER=sampleuser \ -e POSTGRES_PASSWORD=samplesecret \ postgres:9.6.1

--name으로 데이터베이스 컨테이너의 이름을  db라고 설정

-e로 환경 변수 설정

(각 환경 변수에 �해서는 dockerhub의 공식 postgres:9.6.1 이미지 참고)

앱 컨테이너에서 데이터베이스 컨테이너를 찾을 수 있게 하자 (2/2)$ docker run -it --rm \ -p 8000:8000 \ --link db \ -e DJANGO_DB_HOST=db \ -e DJANGO_DEBUG=True \ django-sample \ ./manage.py runserver 0:8000

--link를 통해 db 컨테이너를 참조

(각 옵션에 �한 자세한 설명은 블로그 Ú을 참고하세요.)

문제점 2앱 코드를 수정해도, 

개발 서버가 알아채지 못함

앱 코드 디렉터리를 앱 컨테이너 내부로 연결하자$ 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:8000

--volume을 통해 현재 디렉터리를 컨테이너 안으로 연결

문제점 3db 컨테이너가 죽으면, 데이터도 사라짐

데이터를 로컬에 저장하자$ 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:9.6.1

정리 차원에서 다시 실행!

1. 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:9.6.1

2. 앱 이미지 빌드$ docker build -t django-sample .

3. 앱 컨테이너 실행$ 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:8000

떴다!

h�p://127.0.0.1:8000에 가보면?

지금까지의 구조를 그려보면

그러나

1. 장황한 옵션을 타이핑하기가 너무 복잡하다

미리 적어둘 수는 없을까?

2. 매번 데이터베이스 띄운 다음,

앱 서버 띄우기가 귀찮음

한 번에 묶어서 띄울 수는 없을까?

도커 컴포즈라는 애가 있다던데?

도커 컴포즈

Tool for defining and running multi-container Docker applications

컨테이너 여럿을 사용하는 도커 애플리케이션을 정의하고 실행하는 도구

도커 vs. 도커 컴포즈Dockerfile  vs.  Dockerfile-dev : 서버 구성을 문서화한 것(=클래스 선언이 들어있는 파일)

docker build  vs.  docker-compose build : 도커 이미지 만들기(=클래스 선언을 애플리케이션에 로드)

docker run의 옵션들 vs.  docker-compose.yml : 이미지에 붙이는 장식들(=인스턴스의 변수들)

docker run  vs.  docker-compose up : 장식 붙은 이미지를 실제로 실행(=인스턴스생성)

컨테이너 �신 서비스라고 부름(한 서비스에 컨테이너를 여러 개 띄울 수도 있음)

도커 컴포즈로 가자!

선행 조건docker engine 1.12.0 이상

docker‐compose 1.6.0 이상

$ docker versionClient: Version: 1.13.1 API version: 1.26 Go version: go1.7.5 Git commit: 092cba3 Built: OS/Arch: darwin/amd64

Server: Version: 1.13.1 API version: 1.26 (minimum version 1.12) Go version: go1.7.5 Git commit: 092cba3 Built: Wed Feb 8 08:47:51 2017 OS/Arch: linux/amd64 Experimental: true

$ docker-compose versiondocker-compose version 1.11.1, build 7c5d5e4docker-py version: 2.0.2CPython version: 2.7.12OpenSSL version: OpenSSL 1.0.2j 26 Sep 2016

docker‐compose.yml을 만들자

versionversion: '2.1'

도커 컴포즈 파일 규격의 버전

servicesservices:

도커 컴포즈에서는 컨테이너 단위를 묶어서 서비스라고 함(한 서비스에 여러 컨테이너를 띄울 수 있음).

dbdb:

postgres 서비스의 이름을  db라고 정의

imageimage: postgres:9.6.1

db  서비스에서 사용할 도커 이미지

volumesvolumes: - ./docker/data:/var/lib/postgresql/data

데이터를 로컬의  ./docker/data에 저장함

environmentenvironment: - POSTGRES_DB=sampledb - POSTGRES_USER=sampleuser - POSTGRES_PASSWORD=samplesecret - POSTGRES_INITDB_ARGS=--encoding=UTF-8

(각 환경 변수에 �해서는 dockerhub의 공식 postgres:9.6.1 이미지 참고)

healthcheckhealthcheck: test: "pg_isready -h localhost -p 5432 -q -U postgres" interval: 3s timeout: 1s retries: 10

검사에 사용할 명령( test )을

3초 간격( interval )으로

열 번 시도( retries )

각 시도에서 타임아웃은 1초( timeout )

djangodjango:

앱 서비스의 이름을  django로 지정

buildbuild: context: . dockerfile: ./compose/django/Dockerfile-dev

특정 이미지 �신 '개발용' 도커 이미지를 빌드하여 사용

environmentenvironment: - DJANGO_DEBUG=True - DJANGO_DB_HOST=db - DJANGO_DB_PORT=5432 - DJANGO_DB_NAME=sampledb - DJANGO_DB_USERNAME=sampleuser - DJANGO_DB_PASSWORD=samplesecret

필요한 환경 변수들

portsports: - "8000:8000"

접근할 포트

depends_ondepends_on: db: condition: service_healthy

db  서비스의 헬스체크가 성공( service_healty )한 후  django  서비스를 실행

linkslinks: - db

db  서비스를  db라는 이름으로 참조

commandcommand: /start-dev.sh

./manage.py runserver 0:8000을 �신할 셀 스크립트 파일

(start‐dev.sh의 내용)

#!/bin/shpython manage.py migratepython manage.py runserver 0:8000

volumesvolumes: - ./:/app/

프로젝트 루트 디렉터리를 컨테이너 안으로 연결

드디어 실행!$ docker-compose up -dCreating network "djangosample_default" with the default driverCreating djangosample_db_1Creating djangosample_django_1Attaching to djangosample_db_1, djangosample_django_1db_1 | Initializing database... (DB 초기화 진행) ...django_1 | Operations to perform:django_1 | Apply all migrations: admin, app, auth, contenttypes, myapp, sessions, sitesdjango_1 | Running migrations:... (DB 마이그레이션 진행) ...

h�p://127.0.0.1:8000에 접속 성공!

여기까지를 그림으로 나타내면,

마지막!

Dockerfile‐dev

Dockerfile vs. Dockerfile‐dev (1/2)# 개발 서버용 Dockerfile-dev에서 뺄 부분들

# 앱 코드 복사 ADD ./app/ /app/

# Django 정적 파일 수집RUN ./manage.py collectstatic --noinput

# 서버 실행 명령CMD ['supervisord', '-n']

Dockerfile vs. Dockerfile‐dev (2/2)# 개발용 Dockerfile-dev에 추가할 부분들

# 개발 환경 구성에 필요한 파일 복사COPY ./requirements-dev.txt /app/requirements-dev.txtRUN pip install -r requirements-dev.txt

# 개발 서버 실행에 필요한 파일 복사ADD compose/django/start-dev.sh /start-dev.shRUN chmod +x /*.sh

작은 개선 하나

수정된 docker‐compose.yml도커가 지원하는 가상 디스크를 사용하도록

프로젝트 루트 전체 �신 필요한 파일이나 폴더만 연결

docker‐compose의 주요 명령어

docker-compose를 짧은 alias로 등록해두면 편리

oh‐my‐zsh에서는 기본으로  dco

up ‐d서비스 생성 + 이미지 빌드 + 서비스 실행1. 서비스를 띄울 네트워크 설정

2. 필요한 볼륨 생성

3. 필요한 이미지 pull

4. 필요한 이미지 build

5. 서비스 의존성에 따라 서비스 실행

-d : 서비스 실행 후 콘솔로 빠져나옴

ps현재 개발 환경에서 실행 중인 서비스 확인$ docker-compose ps Name Command State Ports--------------------------------------------------------------------------------djangosample_db_1 /docker-entrypoint.sh postgres Up 5432/tcpdjangosample_django_1 /start-dev.sh Up 0.0.0.0:8000->8000/tcp

stop, start서비스 시작 / 멈춤$ docker-compose stopStopping djangosample_django_1 ...Stopping djangosample_db_1 ...

$ docker-compose startStarting db ... doneStarting django ... done

down서비스, 네트워크 삭제서비스를 초기화할 때 사용

$ docker-compose down --volumeRemoving myproject_django_1 ... doneRemoving myproject_db_1 ... doneRemoving network djangosample_defaultRemoving volume django_sample_db_dev

down --volume : 볼륨까지 삭제

exec실행 중인 컨테이너에서 명령어 실행$ docker-compose exec django ./manage.py makemigrations...

$ docker-compose exec node npm run test> expresssample@0.1.0 test /www/service> mocha $(find test -name '*.spec.js')...

비슷한 명령어  run : 새 컨테이너 실행(‐‐rm 옵션을 적어야 컨테이너 찌꺼기가 남지 않음)

logs ‐f서비스 로그 확인$ docker-compose logs djangoAttaching to djangosample_django_1django_1 | System check identified no issues (0 silenced).django_1 | February 13, 2017 - 16:32:28django_1 | Django version 1.10.4, using settings 'djangosample.settings'django_1 | Starting development server at http://0.0.0.0:8000/django_1 | Quit the server with CONTROL-C.

-f : 로그 팔로잉

사용하면서 느낀 점

docker‐compose.yml을 수정했다면

up ‐d [<서비스 이름>]바뀐 내용을 감지하면 

알아서 서비스를 재생성하고 재시작함

Dockerfile‐dev를 수정했다면

up ‐d ‐‐build [<서비스 이름>]이미지를 새로 만들고 서비스 재생성 후 재시작

Dockerfile‐dev와 Dockerfile 모두 신경 써야 함Dockerfile만 고치면서 개발 환경에서  외않돼?

(Dockerfile에도 외부 파일 참조 개념이 있으면 좋을 텐데...)

데이터베이스 내용도 지우고 싶다면down ‐‐volume

docker-compose.yml의 volumes 부분에 선언한 볼륨들을 지움

MySQL 초기화에 �략 15초

PostgreSQL 초기화에 �략 5초PostgreSQL 짱짱맨

ERROR: 'No space left on device'

/Users/LOGIN_ID/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64‐linux/Docker.qcow2

기본 max 값이 64GiB파일 삭제하거나 Docker for Mac에서  Reset

하지만 지금까지 만든

Docker 이미지와 컨테이너, 볼륨이

모두 사라진다는 점을 주의!

python3 호환성 작업할 때도 좋음다양한 파이썬 버전을 로컬에 설치할 필요가 없어서

블로그 운Ý에도 사용하는 중h�p://raccoonyy.github.io/docker‐for‐ghost‐blogging/

Docker를 배우고 나면모든 것이 컨테이너로 보인다‐‐ raccoony

““