본문 바로가기
프로그래밍 놀이터/Settings

[Docker] 여러 컨테이너의 운용 관리

by 돼지왕왕돼지 2020. 3. 26.

[Docker] 여러 컨테이너의 운용 관리


-

Docker 에서 움직이는 웹 앱을 제품 환경에서 운용할 때는 앱 서버, 로그 서버, 프록시 서버 등과 같이 여러 개의 컨테이너들을 연계하여 작동시킨다.





7.1. 여러 컨테이너 관리의 개요


-

앱을 가동시키려면 여러 개의 서버에 기능과 역할을 분할하여 인프라의 전체 구성을 정한다.

이것을 인프라 아키텍처라고 한다.

대규모 웹 시스템의 경우 몇 개의 서브 시스템/기능으로 나누어 시스템을 개발하는 경우가 많다.

웹 3계층 아키텍처는 웹 앱의 대표적인 인프라 아키텍처 중 하나로 웹 시스템의 서버들을 역할별로 다음 3개로 나누는 것을 이야기한다.



-

프론트 서버

    클라이언트의 요청을 받아 응답을 반환하는 서버이다.

    웹 프론트 서버 또는 그냥 웹 서버라고 한다.

    웹 서버의 기능은  오픈소스인 nginx, IIS 등dml 미들웨어로 구축하는 경우도 있다.

    요청의 처리가 메인 업무이므로 부하가 높은 경우 스케일러블하게 처리 대수를 늘리고, 로드밸런서 등과 같은 기기를 사용하여 부하분산을 한다.



-

앱 서버

    업무 처리를 실행한다. (비지니스 로직)

    앱 서버 기능도 미들웨어로 구축하는 경우도 있다.



-

DB 서버

    주로 RDBMS 기능을 갖고 있는 미들웨어에서 관리한다.

    영구 데이터는 높은 가용성이 요구되기 때문에 클러스터링과 같은 기술로 다중화하는 경우가 많다.

    장애에 대비하여 데이터의 백업이나 원격지 보관 등과 같은 대책도 필요하다.

    DB 조작 처리는 부하가 걸리는 경우가 많으므로 병목이 되지 않도록 퍼포먼스 튜닝이 필요하다.




* 영구 데이터의 관리


-

데이터의 백업 및 복원

    서버 장애에 대비해 데이터를 백업한다.

    기밀 정보도 포함되어 있을 수 있으므로 보안 대책이나 적절한 운용 규칙을 정할 필요가 있다.

    


-

로그 수집

    앱 실행 모듈이나 각종 라이브러리 모듈, 미들웨어의 설정 파일 등은 서버 프로세스가 작동하는 컨테이너 안에 저장하고, 시스템 가동 후에 생성되는 영구 데이터에 대해서는 별도의 인프라 아키텍처를 검토하는 것이 바람직하다.



-

중요한 정보들을 다루는 시스템(크리티컬 시스템)은 대부분 다중 구성을 하거나 만일의 장애나 사고에 대비하고 있다.

인프라 구축이나 운용에서 가장 어려운 점은 바로 이러한 영구 데이터의 관리에 있다.


또한 Docker 컨테이너는 웹 프론트 서버와 같이 트래픽의 증감 등에 맞춰 필요할 때 실행하고 필요 없어지면 파기시킨다는 일회성 운용에 적합하다.

따라서 컨테이너 안은 중요한 영구 데이터를 저장하는 데 적합하지 않다.

Docker 의 기능으로 데이터 전용 컨테이너에서 데이터를 관리하는 방법이나 로컬 호스트를 마운트하여 영구 데이터를 저장하는 방법 등이 있다.




* Docker Compose


-

Docker Compose 는 여러 컨테이너를 모아서 관리하기 위한 툴이다.

docker-compose.yml 라는 파일에 컨테이너의 구성 정보를 정의함으로써 동일 호스트상의 여러 컨테이너를 일괄적으로 관리할 수 있다.



-

Compose 정의 파일은 웹 앱의 의존관계(DB, 큐, 캐시, 앱 등)을 모아서 설정할 수 있다.

이 정의 파일을 바탕으로 docker-compose 명령을 실행하면 여러 개의 컨테이너를 모아서 시작하거나 정지할 수 있다.

또한 컨테이너의 구성 정보를 yaml 형식의 파일로 관리할 수 있으므로 지속적 디플로이나 지속적 인티그레이션 프로세스에 있어  관리하기 좋다.





7.2. 웹 앱을 로컬에서 움직여보자.


* Compose 구성 파일의 작성


-

version: '3.3'

services:

    # WebServer config

    webserver:

        build: . # Dockerfile 로 image 를 구성한다.

        ports :

            - "80:80"

        depends_on:

            - redis


    # Redis config

    redis:

        image: redis # Docker Hub 에 공개된 이미지




* 여러 Docker 컨테이너 시작


-

syntax)

$ docker-compose up




* 여러 Docker 컨테이너 정지


-

syntax)

$ docker-compose stop



-

Docker Compose 에서 이용한 리소스를 삭제하려면 down 을 사용한다.

ex)

$ docker-compose down








7.3. Docker Compose를 사용한 여러 컨테이너의 구성 관리


* docker-compose.yml 의 개요


-

YAML 은 구조화된 데이터를 표현하기 위한 데이터 포맷이다.

Python 과 같이 들여 쓰기로 데이터의 계층 구조를 나타낸다.

데이터의 맨 앞에 - 를 붙이면 배열을 나타낸다. - 다음에는 반각 스페이스를 넣어야 한다.



-

Compose 정의 파일에는 여러 컨테이너의 설정 내용을 모아서 하나의 파일에 기술한다.

이 정의 파일에 관리하고 싶은 컨테이너의 서비스(services:), 네트워크(networks:), 볼륨(volumes:)을 정의한다.



-

Compose 정의 파일은 버전에 따라 기술할 수 있는 항목이 다르다.

버전 정의는 맨 앞에 version : '3'3' 과 같이 한다.

정의되지 않으면 기본으로 1.0 으로 작동한다.




* 이미지 지정(image)


-

바탕이 되는 베이스 이미지를 지정하려면 image 를 사용한다.

image 에는 이미지의 이름 또는 이미지 ID 중 하나를 지정한다.

services:

    webserver:

        image: ubuntu # 태그가 없어서 latest 를 사용한다.




* 이미지 빌드 (build)


-

이미지의 작성을 Dockerfile 에 기술하고 그것을 자동으로 빌드하여 베이스 이미지로 지정할 때는 build 를 지정한다.

build 에는 Dockerfile 의 파일 경로를 지정한다.

services:

    webserver:

        build: .



-

임의의 이름으로 된 Dockerfile 을 빌드할 떄는 dockerfile 을 지정한다.

services:

    webserver:

        build:

            context: /data # path

            dockerfile: Dockerfile-alternate # Dockerfile 이 아닌 이름을 가진 Dockerfile

            args:

                projectno: 1

                user: asa

                isServer: "true" # true, false, yes, no 는 따옴표로 둘러야 한다.




* 컨테이너 안에서 작동하는 명령 지정 (command/entrypoint)


-

컨테이너에서 작동하는 명령은 command 로 지정한다.

베이스 이미지에서 지정되어 있을 때는 그 명령을 덮어쓴다.

command: /bin/bash



-

entrypoint 를 덮어쓸 수도 있다.

entrypoint:

    - php

    - -d

    - memory_limit=-1




* 컨테이너 간 연결 (links)


-

다른 컨테이너에 대한 링크 기능을 사용할 때는 links 를 사용하여 연결할 컨테이너명을 설정한다.

links:

    - logserver

    - logserver:log01 # log01 은 alias



-

서비스 간의 의존관계는 depends_on 을 사용하여 지정한다.

depends_on 은 서비스를 시작하는 순서도 지정할 수 있다.




* 컨테이너 간 통신 (ports/expose)


-

컨테이너가 공개하는 포트를 ports 로 지정한다.

"호스트 머신의 포트번호:컨테이너의 포트번호" 를 지정하거나, 컨테이너의 포트 번호만 지정한다. 이 경우 호스트 머신의 포트는 랜덤한 값으로 설정된다.


YAML 은 xx:yy 형식을 시간으로 해석하므로 포트 번호를 설정할 때는 꼭 겹따옴표로 둘러싸서 문자열 정의해야 한다.



-

호스트 머신에 대한 포트를 공개하지 않고 링크 기능을 사용하여 연결하는 컨테이너에게만 포트를 공개할 때는 expose 를 지정한다.

로그 서버와 같이 호스트 머신에서 직접 액세스하지 않고 웹 앱 서버 기능을 갖고 있는 컨테이너를 경유해서만 액세스하고 싶은 경우 등에 사용한다.




* 서비스의 의존관계 정의 (depends_on)


-

예를 들어 webserver 컨테이너를 시작하기 전에 db 컨테이너와 redis 컨테이너를 시작하고 싶을 때 depends_on 을 사용한다.

depends_on 은 컨테이너의 시작 순서만 제어할 뿐, 컨테이너상의 앱이 이용 가능해 질때까지 기다리는 제어는 하지 않는다.

즉, 의존관계에 있는 서비스의 준비가 끝날 때까지 기다리는 것은 아니기 때문에 앱 측에서 이에 대한 대책을 세울 필요가 있다.




* 컨테이너 환경 변수 지정 (environment/env_file)


-

environment 를 지정한다.

배열 혹은 해시 형식 중 하나로 지정한다.

# 배열 형식

environment:

    - FOO=bar


# hash 형식

environment:

    FOO: bar



-

설정하고 싶은 환경변수가 많을 때는 다른 파일에서 환경변수를 정의하고 그 파일을 읽어들일 수 있다.

env_file 을 지정하면 된다. 여러개를 지정할 수 있다.

env_file:

    - ./envfile1

    - ./app/envfile2




* 컨테이너 정보 설정 (container_name/labels)


-

Docker Compose 로 생성되는 컨테이너에 이름을 붙일 때는 container_name 을 지정한다.

단, Docker 컨테이너명은 고유해야 하므로 커스텀명을 지정하면 여러 컨테이너로 스케일할 수 없어진다.

container_name: web-container



-

컨테이너에 라벨을 붙일 때는 labels 를 지정한다.

여러 개의 라벨을 붙일때는 배열 또는 해시 형식 중 하나로 지정한다.

labels:

    - "com.example.description=Accounting webapp" # 배열 형식

    com.example.department: "Finance" # 해시 형식




* 컨테이너 데이터 관리(volumes/volumes_from)


-

볼륨을 마운트할 때 volumes 를 지정한다.

volumes:

    - /var/lib/mysql

    - cache/:/tmp/cache



-

볼륨 뒤에 ro 를 지정하면 읽기 전용으로 마운트한다.

설정 파일이 저장된 볼륨 등과 같이 쓰기를 금지하고 싶은 경우에 지정하면 좋다.

volumes:

    - ~/configs:/etc/configs/:ro



-

다른 컨테이너로부터 모든 볼륨을 마운트할 때는 volumes_from 에 컨테이너명을 지정한다.

volumes_from:

    - log








7.4. Docker Compose 를 사용한 여러 컨테이너의 운용


* Docker Compose 의 버전 확인


-

Docker Compose 는 Docker for Mac / Windows 에 미리 설치되어 있다.

버전 확인은..

$ docker-compose --version



-

docker-compose.yml (또는 .yaml) 파일이 없는 상태에서 docker-compose up 명령을 실행하면 정의 파일을 찾을 수 없다는 오류가 표시된다.

이때는 -f 옵션을 사용하여 정의 파일명을 지정할 수 있다.




* Docker Compose 의 기본 명령


-

docker-compose 의 주요 서브 명령은..

up : 컨테이너 생성/시작

ps : 컨테이너 목록 표시

logs : 컨테이너 로그 출력

run : 컨테이너 실행

start : 컨테이너 시작

stop : 컨테이너 정지

restart : 컨테이너 재시작

pause : 컨테이너 일시 정지

unpause : 컨테이너 재개

port : 공개 포트 번호 표시

config : 구성 확인

kill : 실행 중인 컨테이너 강제 정지

rm : 컨테이너 삭제

down : 리소스 삭제



-

docker-compose 명령은 docker-compose.yml 을 저장한 디렉토리에서 실행된다.

만일 다른 곳에 있는 compose 파일을 참조하려면 -f 옵션으로 파일 경로를 지정해야 한다.

syntax)

$ docker-compose -f <compose file path> up



-

서브 명령 다음에 컨테이너명을 지정하면 해당 컨테이너만 조작할 수 있다.

ex)

$ docker-compose stop webserver # webserver container 만 정지시킨다




* 여러 컨테이너 생성 (up)


-

syntax)

$ docker-compose up [옵션] [서비스명...]


주요 옵션

-d : 백그라운드 실행

--no-deps : 링크 서비스를 시작하지 않는다.

--build : 이미지를 빌드한다.

--no-build : 이미지를 빌드하지 않는다.

-t, --timeout : 컨테이너의 타임아웃을 초로 지정(기본 10초)

--scale SERVICE=서비스 수 : 서비스 수를 지정한다.



-

ex)

$ docker-compose up --scale server_a=10 --scale server_b=20

server_a 컨테이너를 10개, server_b 컨테이너를 20개 시작시킨다.




* 여러 컨테이너 확인 (ps/logs)


-

syntax)

$ docker-compose ps # -q 는 container id 만 표시한다.


syntax)

$ docker-compose logs




* 컨테이너에서 명령 실행 (run)


-

$ docker-compose run server_a /bin/bash




* 여러 컨테이너 시작/정지/재시작 (start/stop/restart)


-

$ docker-compose  start

$ docker-compose stop

$ docker-compose restart

특정 컨테이너만을 조작하고 싶을 때는 명령의 인수로 컨테이너명을 지정한다.




* 여러 컨테이너 일시 정지/재개 (pause/unpause)


-

$ docker-compose pause

$ docker-compose unpause




* 서비스 구성 확인 (port/config)


-

syntax)

$ docker-compose port [옵션] <서비스명> <프라이빗 포트 번호>


주요 옵션

--protocol=proto : tcp 또는 udp

--index=index : 컨테이너의 인덱스 수



-

ex)

$ docker-compose port webserver 80



-

syntax)

$ docker-compose config




* 여러 컨테이너 강제 정지/삭제 (kill/rm)


-

ex)

$ docker-compose kill-s SIGINT # 컨테이너에 시그널 송신, SIGINT 는 interrupt 로 Ctrl + C 와 같다.

옵션을 지정하지 않으면 SIGKILL(프로세스 강제 종료) 이 송신된다. 


주요 시그날은..

SIGHUP : 프로그램 재시작

SIGINT : 키보드 인터럽트, Ctrl + C

SIGQUIT : 키보드에 의한 중지, Ctrl + \

SIGTERM : 프로세스 정상 종료

SIGKILL : 프로세스 강제 종료

SIGSTOP : 프로세스 일시 정지



-

syntax)

$ docker-compose rm




* 여러 리소스의 일괄 삭제 (down)


-

compose 파일 기반 docker-compose up 으로 생성한 컨테이너나 이미지들을 모아서 삭제할 때 사용한다.

실행 중인 컨테이너를 정지시키고, 컨테이너, 이미지, 네트워크 데이터 볼륨을 일괄 삭제한다.

syntax)

$ docker-compose down [옵션]


주요 옵션은..

--rmi all : 모든 이미지 삭제

--rmi local : 커스텀 태그가 없는 이미지만 삭제

-v, --volumes : compose 정의 파일의 데이터 볼륨 삭제




댓글0