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

7 minute read

Docker 여러 컨테이너 관리의 개요

웹 3계층 시스템 아키텍처

  • 프론트 서버: 클라이언트의 웹 브라우저가 보낸 HTTP 요청을 받아, HTTP 응답을 반환하는 서버 기능을 가진다.
    웹서버의 기능은 미들웨어로 구축하는 경우도 있으며, 오픈소스인 Nginx, Microsoft의 IIS등이 있다.

  • 애플리케이션 서버: 업무처리를 실행하는 서버
  • 데이트베이스(DB)서버: 영구 데이터를 관리하기 위한 서버이다.
    영구 데이터는 높은 가용성이 요구되기 떄문에 클러스터링과 같은 기술로 다중화 하는 경우가많다. 만일의 장애에 대비하여 데이터의 백업이나 원격지 보관 등과 같은 대책이 필요하다.


영구 데이터의 관리
서버의 장애에 대비하여 데이터를 백업한다.
백업은 디바이스와 같은 물리 매체인 경우도 있는가 하면 클라우드상의 스토리지 서비스를 이용하는 경우도 있다.
시스템이나 애플리케이션은 각 서버상에 저장한는 경우도 있지만 여러 개의 서버로 된 분산 환경에서 통합 감시흫 하는 경우는 로그 수집 전용 서버를 마련하는 것이 일반적이다.
Docker는 컨테이너를 사용하여 서버 기능을 제공한다.
컨테이너는 필요에 따라 생성하거나 파기하는 운용에 적합하며, 하나의 컨테이너에는 하나의 프로세스를 구성해 두는 것이 대원칙 이다.
따라서 애플리케이션의 실행 모듈이나 각종 라이브러리의 모듈, 미들웨어의 설정 팡리 등은 서버 프로세스가 작동하는 컨테이너 안에 저장하고, 시스템 가동 후에 생성되는 영구 데이터에 대해서는 별도의 인프라 아키텍처를 검토하는 것이 바람직하다.

Docker Compose

그림참조:SQL Server Story 블로그
웹 시스템에서는 여러개의 Docker 컨테이너가 협력하면서 작동한다.
Docker Compose는 여러 컨테이너를 모아서 관리하기 위한 툴 이다.
Compose 정의 파일은 앱 애플리케이션의 의존관계(데이터 베이스, 큐, 캐시, 애플리케이션 등)를 모아서 설정할 수 있다.
이러한 Compose파일은 ‘docker-compose.yml’라는 파일에 컨테이너의 구성 정보를 정의함으로써 동일 호스트상의 여러 컨테이너를 일괄적으로 관리할 수 있다.


웹 애플리케이션을 로컬에서 움직여 보자

Compose 구성 파일의 작성
다음 코드를 통하여 Docker Compose를 확인하기 위한 환경을 구성하자.

git clone https://github.com/asahiho/kocertext2
cd dockertext2/chap07/


위의 디렉토리에서 Docker Compose file인 docker-compose.yml은 다음과 같다.

version: '3.3'
services:
  # WebServer config
  webserver:
    build: .
    ports:
     - "4444:80"
    depends_on:
     - redis

  # Redis config
  redis:
    image: redis:4.0


Compose 맨 앞에는 버전을 지정한다.
Service로서는 Webserver인 webserver와 redis라는 2개의 서비스를 정의한다.
webserver는 80번 port를 80번 port로서 연결한다.
중요한 것은 webserver 는 redis에 의존적 이라는 것 이다.
redis는 NoSQL의 일종으로 DB의 하나의 종류이다.
이러한 의존적인 관계로 인하여 redis Service가 먼전 실행 된 뒤 webserver Service가 실행되는 것을 알 수 있다.

여러 Docker 컨테이너 시작
본격적인 여러 Container를 실행하는 구분이다.
여기서 중요한 점은 위의 docker-compose.yml이다.
docker-compose.yml에서 build: .은 현 위치의 DockerFile을 사용해 이미지를 빌드한다는 의미이다.
즉 Docker Compose는 DockerFile을 참조하여 여러 Container를 실행할 수 있도록 정의하는 하나의 기능이라고 생각할 수 있다.
Docker file은 다음과 같다.
Docker file

# Maintainer
LABEL maintainer "Shiho ASA"

# Upgrade pip
RUN pip install --upgrade pip

# Install Path
ENV APP_PATH /opt/imageview

# Install Python modules needed by the Python app
COPY requirements.txt $APP_PATH/
RUN pip install --no-cache-dir -r $APP_PATH/requirements.txt

# Copy files required for the app to run
COPY app.py $APP_PATH/
COPY templates/ $APP_PATH/templates/
COPY static/ $APP_PATH/static/

# Port number the container should expose
EXPOSE 80

# Run the application
CMD ["python", "/opt/imageview/app.py"]


app.py

from flask import Flask, render_template
from redis import Redis
import os,random

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

...


위의 Code를 종합하여 생각하면 Docker Compose로 인하여 redis -> webserver 순으로 Service하고 webserver는 Dockerfile을 참조하여 Build한다.
최종적으로는 Flask(파이썬 웹 프레임 워크)를 실행하여 Webservice를 실행한다.

docker-compose up

Creating network "chap07_default" with the default driver
Pulling redis (redis:4.0)...

...



작동 확인


컨테이너 확인

docker-compose ps


       Name                    Command              State          Ports
--------------------------------------------------------------------------------
chap07_redis_1       docker-entrypoint.sh redis     Up      6379/tcp
                     ...
chap07_webserver_1   python /opt/imageview/app.py   Up      0.0.0.0:4444->80/tcp


컨테이너 정지

docker-compose stop

Stopping chap07_webserver_1 ... done
Stopping chap07_redis_1     ... done


리소스 삭제

docker-compose down

Removing chap07_webserver_1 ... done
Removing chap07_redis_1     ... done
Removing network chap07_default


  • stop: Container를 정지함
  • down: Container와 networks를 정지 및 삭제한다.



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

YAML
YAML은 구조화된 데이터를 표현하기 위한 데이터 포멧이다.
YAML은 Python과 같이 들여쓰기로 데이터의 계층 구조를 나타낸다.
들여쓰기는 탭이 아니라 반각 스페이스(스페이스 두번)를 사용한다.
누가 써도 읽기 쉽기 떄문에 설정 파일 등에 많이 사용된다.
YAML에서는 데이터의 맨 앞에 ‘-‘를 붙이면 배열은 나타낼 수 있다. ‘-‘다음에는 반드시 반각 스페이스를 넣어야 한다.

Version

version: "[version 이름]"


Docker compose 제일 앞에는 version을 정의해야 한다.
version은 Docker Engine에 따라서 바뀌게 된다.

Compose 정의 파일의 버전 Docker Engine의 버전
3.3 17.06.0
3.2 17.04.0
3.1 1.13.1
3.0 1.13.0
2.3 17.06.0
2.2 1.13.0
2.1 1.12.0
2.0 1.10.0
1.0 1.9.1


이미지 지정
Docker 컨테이너의 바탕이 되는 베이스 이미지를 지정하려면 iamge를 사용한다.
image에는 이미지의 이름 또는 이미지 ID 중 하나를 지정한다.

image:  [image 명 or image ID]
​```<br>

추가적으로 공식 이미지뿐만 아니라 Docker Hub에 공개되어 있는 이미지는 모두 지정할 수 있다.  
<br>
**이미지 빌드**  
이미지의 작성을 Dockerfile에 기술하고 그것을 자동으로 빌드하여 베이스 이미지로 지정할 때는 build를 지정한다.  
​```code
build: [커렌트 디렉토리 기준의 Dockerfile의 위치]


임의의 이름으로 작성된 Dockerfile을 빌드하는 경우에는 context로서 위치를 나타내로 dockerfile로서 dockerfile의 이름을 지정한다.
또한 이미지를 빌드할 때에 인수를 args로 지정할 수 있다.

build:
  context:   [커렌트 디렉토리 기준의 Dockerfile의 위치]
  dockerfile:  [Docekr file 이름]
  args:
    projectno:  1
    user:  asa


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

command: [명령어]


또한 entrypoint를 덮어 쓸수 있다.

entrypoint:
  - [변수]
  - [변수]
    ...


컨테이너 간 연결(links)
Container의 IP는 언제든 변할 수 있는 유동적인 성격을 가지고 있다.
Container는 일종의 Process 이므로, 언제든 생성/소멸 될 수 있음을 전제로 해야한다.
만약 Container가 중지 되었다가 시작하면, Process가 kill 되었다가 다시 새롭게 생성되는 것과 같다.
이때, Container에게 부여되는 Private IP는 언제든 변할 수 있다.
따라서 Container를 서로 연결하기 위하여 IP기반의 설정이 아니라 link로서 연결하는 것이 권고 된다.

link:
  -  [서비스명]
  -  [서비스명:앨리어스명]\


이러한 연결은 depends_on을 사용하여 서비스를 시작하는 순서또한 지정할 수 있다.

서비스 의존관계 정의(depends_on)
여러 서비스의 의존관계를 정의할 때 depends_on을 지정한다.
주의할 점은 depends_on은 컨테이너의 시작 순서만 제어할 뿐 컨테이너상의 애플리케이션이 이용가능핼 질 때까지 기다리고 제어를 하지 않는다. 즉, 의존관계에 있는 데이터베이스 서비스의 준비가 끝날 때까지 기다리는 것은 아니기 때문에 애플리케이션 측에서 이에 대한 대책을 세울 필요가 있다.

[서비스명]:
    depends_on:
    <text>-</text>  [서비스명]
    <text>-</text>  [서비스명]
    ...


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

ports:
  - "[호스트 머신의 포트 번호:컨테이너의 포트 번호]"
  - "[호스트 머신의 포트 번호:컨테이너의 포트 번호]"
    ...


expose:
  - "[컨테이너의 포트 번호]"
  - "[컨테이너의 포트 번호]"
    ...


컨테이너 환경변수 지정(environment/env_file)
컨테이너 안의 환경변수를 지정할 때는 environment를 지정한다.
배열 형식 또는 해시 형식 중 하나로 변수 지정 가능하다.

environment:
  - [변수명] = [변수 값]
  - [변수명] : [변수 값]
    ...


변수명이 많아서 다른 파일에 환경변수를 정의하고 그 파일을 읽어들일 수 있다.

env_file:
  - [커렌트 디렉토리 기준 환경변수 파일]
  - [커렌트 디렉토리 기준 환경변수 파일]
    ...


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

container_name: [컨테이너 이름]


또한 컨테이너에 라벨을 붙일 때는 labels를 지정한다. 여러개의 라벨을 붙일 때는 YAML의 배열 또는 해시 형식 중 하나로 변수를 지정한다.

labels:
  - "[라벨 이름] = [라벨 값]"
  - [라벨 이름] : "[라벨 값]"


설정한 라벨을 확인할 때는 docker-compose config 명령을 사용한다.

컨테이너 데이터 관리(volumes/volumes_form)
컨테이너에 볼륨을 마운트 할 때는 volumes를 지정한다.

volumes:
  - [컨테이너의 디렉토리 경로]
  - [호스트의 디렉토리 경로]:[컨테이너의 디렉토리 경로]
    ...


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

volumes_forms:
  - [컨테이너 명]




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

Docker Compose의 버전확인

docker-compose --version

docker-compose version 1.17.1, build unknown


Docker Compose의 서브 명령

서브 명령 설명
up 컨테이너 생성/시작
ps 컨테이너 목록 표시
logs 컨테이너 로그 출력
run 컨테이너 실행
start 컨테이너 시작
stop 컨테이너 정지
restart 컨테이너 재시작
pause 컨테이너 일시 정지
unpause 컨테이너 재개
port 공개 포트 번호 표시
config 구성 확인
kill 실행 중인 컨테이너 강제 정지
rm 컨테이너 삭제
down 리소스 삭제


Ex) 특정 컨테이너 정지

docker-compose stop webserber


여러 컨테이너 생성(up)
작성한 docker-compose.yml을 바탕으로 여러 개의 컨테이너를 생성하여 시작할 때는 docker-compose up명령어 사용

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


옵션

-d 백그라운드에서 실행
--no-deps 링크 서비스를 시작하지 않는다
--build 이미지를 빌드한다.
--no-build 이미지를 빌드하지 않는다.
-t, --timeout 컨테이너의 타임아웃을 초로 지정(기본 10초)
--scale SERVICE = 서비스 수 서비스 수를 지정한다


여러 컨테이너 확인(ps/logs)
여러 컨테이너의 상태 확인

docker-compose ps


여러 컨테이너의 로그 확인

docker-compose logs


컨테이너에서 명령 실행(run)
Docker COmpose로 시작한 컨테이너에서 임의의 명령을 실행하기 위하여 사용

docker-compose run [시작한 서비스] [명령어]


여러 컨테이너 시작/정지/재시작
컨테이너 일괄 시작/정지/재시작

#컨테이너 일괄 시작
docker-compose start
#컨테이너 일괄 정지
docker-compose stop
#컨테이너 일괄 재시작
docker-compose restart


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

#특정 컨테이너 재시작
docker-compose restart [컨테이너 명]


여러 컨테이너 일시 정지/재개

#여러 컨테이너 일시 정지
docker-compose pause
#여러 컨테이너 일시 재개
docker-compose unpause


서비스의 구성 확인(port/config)
공개용 포트 확인

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


옵션

옵션 설명
--protocol=proto 프로토콜. tcp 또는 udp
--index=index 컨테이너의 인덱스 수


여러 컨테이너 강제 정지/삭제

#여러 컨테이너 강제 정지
docker-compose kill
#여러 컨테이너 일괄 삭제
docker-compose rm


참고 사항
docker-compose kill은 컨테이너에게 시그널을 전송하는 일종의 작업이다.
Linux는 프로그램을 실행할 때 파일에 쓰여있는 프로그림을 읽어들여 메모리상에 배치하게 되는데 이러한 메모리상에 배치된 프로그램이 프로세스 이다.
이러한 프로세스에게 명령을 송신할 수 있는데 이러한 명령을 시그널 이라고 한다.
Docker compose 시그널

시그널 설명
SIGUP 프로그램 재시작
SIGINT 키보드 인터럽트(Ctrl + c)
SIGQUIT 키보드에 의한 중지(Ctrl + /)
SIGTERM 프로세스 정상 종료
SIGKILL 프로세스 강제 종료
SIGSTOP 프로세스 일시 정지


EX) 컨테이너에 시그널 송신

docker-compose kill -s SIGINT


여러 리소스의 일괄 삭제
실행중인 컨테이너를 정지시키고, Docker 이미지, 네트워크, 데이터 볼륨을 일괄적으로 삭제

docker-compose down [옵션]


옵션

옵션 설명
--rmi all 모든 이미지를 삭제
--rmi local 커스텀 태그가 없는 이미지만 삭제
-v, --volumes Compose 정의 파일의 데이터 볼륨을 삭제




참조: 완벽한 IT 인프라 구축을 위한 Docker
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.

Categories:

Updated:

Leave a comment