본문 바로가기
Study/Cloud,Docker,Kubernetes

Docker(4)-DockerCompose

by 왕방개 2024. 4. 6.

Docker Compose

1.개요

=>시스템 구축과 관련된 명령어를 하나의 텍스트 파일(yaml)에 기재해서 한번에 시스템 전체를 실행하고 종료와 폐기까지 하도록 도와주는 도구

=>공통의 목적을 갖는 애플리케이션을 docker-compose.yml 파일에 코드로 정의해서 한번에 서비스를 올리고 관리할 수 있는 도구

=>하나의 서비스는 하나의 도구만 사용하는 경우는 드뭄

React <-> Node, Python의 Web Frameword, Spring <->데이터베이스

 

=>이런 경우 3개의 컨테이너를 정의해서 사용해야 하는데 이를 별개의 파일로 관리하는 것은 비효율적

여러 개로 관리하다보면 수정을 해야 하는 경우 3곳 모두 수정을 해야하는데 이런 경우 에러가 발생할 가능성이 높음

하나의 정의 파일을 이용해서 관리하는 것이 효율적

 

=> yaml 포맷으로 기술된 설정 파일을 이용해서 여러 container 간의 실행이나 관계를 설정

 

=>작성을 할 때 도커 명령어 와 비슷하지만 도커 명령어는 아님

 

=>명령어

-up:이미지를 내려받고 컨테이너를 생성하고 네트워크 나 볼륨도 생성해주는 명령

-down:컨테이너를 정지하고 네트워크도 정지 및 삭제하는 명령

-stop:중지

 

=>Docker-Compose 와 Dockerfile

-Dokcer-Compose 는 docker run 명령을 여러 개 만든 것과 유사해서 컨테이너와 주변 환경을 생성하고 네트워크와 볼륨도 만들 수 있음

-Dockerfile 은 이미지를 만들기 위한 스크립트 명령으로 네트워크나 볼륨이나 컨테이너를 생성하는 것은 안됨

-Docker Compose 는 도커 엔진과 별개의 프로그램

 

=>설치

-Mac 이나 Windows 에서 Docker Desktop 을 설치하면 자동 설치가 됨

-Linux의 경우는 별도로 설치해야 사용할 수 있습니다.

Linux에서 Docker는 중앙 저장소에서 다운로드 받을 수 없기 때문에 저장소를 직접 설정해서 다운로드 받아야합니다.

 

 

2.Docker Compose 작성 및 명령

1)httpd(apache) 컨테이너를 Docker-Compose 를 이용해서 생성

=>docker run 명령으로 생성

docker run --name apa000ex1 -dit -p 8080:80 httpd

 

=>docker-compose 명령으로 생성

-현재 디렉토리에 docker-compose.yml 파일을 생성하고 작성

version: "3"
service:
  app000ex1:
    image: httpd
    ports:
      -8081:80
    restart: always

 

-터미널 명령 수행

docker-compose up -d

 

-docker-desktop에서 확인

현재 디렉토리 이름으로 컨테이너가 만들어지고 그안에 apa000ex2 라는 컨테이너가 존재

 

-docker ps 명령으로 확인

컨테이너 이름이 현재 디렉토리 이름과 컨테이너 이름의 조합으로 만들어집니다.

 

2)mariadb 컨테이너를 배포

=>docker run 명령

docker run --name mariadb -dit -p 3306:3306 --restart=always -e MYSQL_ROOT_PASSWORD=wnddkd mariadb

 

-현재 디렉토리에 docker-compose.yml 파일을 생성

version: "3"
services:
  mariadb:
    image: mariadb
    ports:
      - 3306:3306
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: wnddkd

 

=>명령 수행

docker-compose up -d

3.작성 방법

1)주 항목

=>services

=>networks

=>volumes

 

2)정의 내용

=>image

=>networks: --net

=>volumes: -v

=>ports: -p

=>environment: -e

=>depoends_on:다른 서비스와의 의존 관계 ( 컨테이너 생성 순서와도 연관)

=>restart:컨테이너 종료시 재시작 여부를 설정하는 것으로 no,always,on-failure,unless-stopped

 

3)버전 정의

=>도커 엔진과의 호환성을 고려해서 작성

=>version 3 은 도커 엔진 1.13 이상에서 사용 가능

=>학습할 떄는 최신 버전을 이용하므로 별 문제가 되지 않는데 public cloud 서비스를 이용할 때 문제가 될 수 있습니다.

 

4)에러 발생

=>작성한 버전과 도커 컴포즈 또는 도커 엔진 릴리스가 적합하지 않은 경우 

=>도커 컴포즈 도구가 오래된 경우 - 리눅스에서만 발생. Windows 나 Mac 은 도커 엔진가 도커 컴포즈를 같이 설치하기 떄문에 이런 에러가 발생하지 않음

=>들여쓰기의 공백 수가 하위레벨과 맞지 않은 경우

 

5)서비스 정의

=>도커 컴포즈를 통해 실행할 서비스를 정의

=>도커 컴포즈에서는 컨테이너라는 용어 대신에 서비스라는 용어를 사용

=>다중 컨테이너 서비스 실행을 목적으로 하므로 복수형으로 작성

=>하위에는 컨테이너 이름처럼 이름을 기재하고 컨테이너 실행에 필요한 옵션을 작성

version "3.8"

services:

  myweb:

    image:nginx:latest

  mydb:

    image:mariadb:10.4.6

 

-nginx 이미지를 이용해서 myweb 이라는 컨테이너를 생성하고 mariadb 이미지를 이용해서 mydb라는 컨테이너를 생성하는데 어떤 컨테이너가 먼저 생성될지 알 수 없습니다.

 

=>프로젝트에 애플리케이션 개발을 위한 Dockerfile 을 작성해서 컨테이너를 실행하는 경우에는 미리 빌드해서 이미지명과 태그를 명시해도 되지만 build 옵션을 이용해서 이미지를 빌드해서 사용하는 것이 가능

 

=>build 옵션에는 이미지 빌드에 필요한 Dockerfile의 위치를 설정해주면 됩니다.

services:

  web:

    build: .

 

=>Dockerfile 의 위치나 파일 이름이 다른 경우에는 context 와 dockerfile 옵션을 사용

 

services:

  web:

    context:.

    dockerfile: Dockerfile의 경로

 

- dockerfile 의 경로를 찾아가서 이미지를 빌드하는데 이미지는 context 에 설정한 곳에 생성

- 프로그래밍에서 일반적으로 context 라는 용어는 대부분의 경우 저장의 의미를 가짐

그래픽에서는 context 라는 것이 현재 설정을 저장한다라는 의미로 사용

 

=>하위 옵션

-container_name: docker run 의 --name 옵션과 동일한데 생략시 자동으로 부여하는데 디렉토리명_서비스명_인덱스로 설정

-ports: -p 옵션과 동일한데 내부 포트와 외부 포트를 연결하는 것으로 바인딩 하기도 포트를 바인딩하는 경우에는 포트포워딩이라고도 합니다

 

-expose: 호스트 운영체제와 직접 연결하는 포트를 구성하지 않고 포트를 노출하는데 필요하면 링크로 연결된 서비스와 서비스 간의 통신만 허용

 

-networks: --net 옵션과 동일한데 최상위 레벨의 networks 에 정의된 네트워크 이름을 작성

-environments: -e 옵션과 동일한데 환경 변수 설정에 사용

환경변수가 많으면 *.env 파일에 작성하고 env_file 옵션에 경로를 설정

 

-command: docker run 명령의 마지막에 작성되는 명령어로 서비스가 구동 이후 실행할 명령어를 지정

 

-restart: --restart 옵션과 동일한데 서비스 재시작 옵션

 

-depends_on: 서비스 간의 종속성을 의미하는데 먼저 실행해야 하는 서비스를 지정해서 컨테이너 생성 순서를 설정

 

django 나 wordpress 같은 애플리케이션은 데이터베이스 연동이 필수이고 서비스가 시작될 때 데이터베이스 연결이 되어야 하므로 데이터베이스 컨테이너가 미리 실행되어 있어야 합니다.

 

6)네트워크 정의

=>네트워크: 여러 컨테이너들이 통신을 하고자 하는 경우 사용하는 객체

=>networks 옵션으로 생성하는데 이 옵션을 사용하지 않으면 자체 기본 네트워크를 자동으로 생성해서 사용

=>도커에서 생성한 네트워크를 이용할 때는 external 옵션에 네트워크 이름을 설정하면 됩니다

 

7)데이터베이스는 mysql 8.0을 사용하고 wordpress 5.7 이미지를 이용한 웹 애플리케이션 서비스를 구성

=>도커 명령어 사용

-볼륨(도커 컨테이너의 데이터를 반 영구적으로 저장하거나 호스트 컴퓨터의 데이터를 컨테이너 안에서 사용하거나 다른 컨테이너와 데이터를 공유하기위해서 사용)을 생성하고 확인

docker volume create mydb_data

 

docker volume create myweb_data

 

docker volume ls

 

-네트워크(여러 개의 컨테이너 들 간의 통신을 외부포트를 사용하지 않고  수행하기 위해서) 설정을 생성하고 확인

 

docker network create myapp-net

 

docker network ls

 

-컨테이너 생성

docker run -dit --name=mysql_app -v mydb_data:/var/lib/mysql --restart=always -p 3306:3306 --net=myapp-net -e MYSQL_ROOT_PASSWORD=wnddkd -e MYSQL_DATABASE=adam -e MYSQL_USER=adam -e MYSQL_PASSWORD=wnddkd mysql:8.0

 

docker run -dit --name=wordpress_app -v myweb_data:/var/www/html -v $[PWD]/myweb-log:/car/log --restart=always -p 8888:80 --net=myapp-net -e WORDPRESS_DB_HOST=mysql_app:3306 -e WORDPRESS_DB_NAME=adam -e WORDPRESS_DB_USER=adam -e WORDPRESS_DB_PASSWORD=wnddkd --link mysql_app:mysql wordpress:5.7

 

-여러 컨테이너를 만들 때 반드시 순서를 정확하게 지켜야 명령어를 직접 입력하기 떄문에 다음에 재사용하기가 쉽지 않습니다.

-재사용하고자 하면 파일을 저장해서 나중에 다시 복사해야 합니다

-이러한 내용을 파일에 기록해두고 파일을 호출해서 실행하면 훨씬 더 편리

-이러한 작성 내용이 인프라를 만드는 것이라면 이를 IaC (Infrastructure as Code): 동일한 환경을 만드는 작업이 훨씬 더 편리해지고 유지보수도 쉬워지고 에러를 발생시킬 가능성도 줄어듭니다

 

-확인

docker ps

브라우저에서 localhost:8888 로 확인

 

docker system prune =>캐시까지 지우는 명령

웹 프로젝트를 할 때 브라우저에서 변경이 되질 않음 

DOCKER 를 공부하는 이유: 컨테이너를 사용하기때문

맨 처음에 하나의 운영체제에 여러 애플리케이션을 설치해서 개발

애플리케이션끼리 별도로 설치를 해서 간섭을 최소화 해보자 => VM: 운영체제를 설치하고 운영체제 위에 애플리케이션을 설치

=>여러 개의 애플리케이션을 독립된 형태로 사용하려면 운영체제를 여러 개 설치

운영체제를 여러 개 설치하므로 속도가 느리거나 자원소모가 심함

 

-컨테이너 기반의 가상화

하나의 운영체제를 격리된 영역의 개념을 갖는 컨테이너라는 개념으로 분리해서 사용

이 개념에서 출발한 소프트웨어중 하나가 도커이고 , 이 중에서 도커가 현재는 가장 많이 사용됨

 

VOLUME:컨테이너는 메모리(사용 중 일때는 데이터를 보존하지만 종료가 되면 데이터가 소멸)에 존재하는 것

컨테이너가 만든 데이터를 반 영구적으로 저장하거나 다른 컨테이너(동일한 이미지로 부터 생성된 컨테이너)와 공유할 목적으로 사용

 

NETWORK:여러 컨테이너가 하나로 묶여서 통신을 하기 위한 개념

                    묶지 않아도 서로 포트를 개방해서 통신이 가능한데 이렇게 포트를 개방하면 다른 컨테이너도 접근이 가능

                    다른 컨테이너 와는 통신을 하고 싶지 않고 특정한 멤버와 만 통신을 하고자 하는 경우 사용

                    네트워크를 구성할 때 주의할 점은 단순하게 통신을 하는 것인지 종속해서 사용되는 경우인지 확인을 해봐야                      합니다.

 

 CI/CD 는 코드 수정해서 compile -> build ->test ->배포 과정을 push 한번에 실행될 수 있게 합니다.

 

-IaC(Infrastructure as Container)

 

=>docker-compose 를 이용한 생성

-docker-compose.yml 파일을 생성

version: "3"

networks:
  frontend-net: {}
  backend-net: {}

volumes:
  mydb_data: {}
  myweb_data: {}

services:
  mydb:
    image: mysql:8.0
    container_name: mysql_app
    volumes:
      - mydb_data:/var/lib/mysql
    restart: always
    ports:
      - "3306:3306"
    networks:
      - backend-net
    environment:
      MYSQL_ROOT_PASSWORD: wnddkd
      MYSQL_DATABASE: adam
      MYSQL_USER: adam
      MYSQL_PASSWORD: wnddkd
   
  myweb:
    depends_on:
      - mydb
    image: wordpress:5.7
    container_name: wordpress_app
    ports:
      - "8888:80"
    networks:
      - frontend-net
      - backend-net
    volumes:
      - myweb_data:/var/www/html
      - ./myweb_log:/var/log
    restart: always
    environment:
      WORDPRESS_DB_HOST: mydb:3306
      WORDPRESS_DB_USER: adam
      WORDPRESS_DB_PASSWORD: wnddkd
      WORDPRESS_DB_NAME: adam

 

-터미널에서 docker-compose 명령 수행

docker-compose up

 

-확인

docker desktop 에서 컨테이너 생성 여부 확인해도 되고 docker ps 명령으로 확인

 

브라우저에서 localhost:8888 확인

-볼륨 확인

스토리지 볼륨을 연결한 경우는 디렉토리로 가서 디렉토리를 확인해봐야 하는데 도커에서는 ${PWD} 로 현재 작업 디렉토리로 설정하는데 Windows 에서는 동작하지 않을 수 있습니다.

 

4.Flask Web Framework(python web framework) 와 Redis(In memory database) 를 이용해서 웹페이지 엑세스 카운트를 캐시해서 웹 페이지에 출력

 

로그인, 랭킹 이런거를 Redis 에 저장해놓음

=>개요

-python 기반 web framework

확장성 있는 설계를 지원

Django는 가장 많은 사용자를 보유한 python web application 인데 강력하고 풍부한기능을 제공하기 떄문에 사용법을 익히면 사용하기 편하지만 Framework 자체 설계한 개발 패턴 때문에 복잡한 경우가 있음

 

=Linked in이 Flask 을 이용해서 설계되어있음

 

=>project 생성 및 실행

 

-디렉토리 생성

 

-가상환경 생성

 

-flask 설치

pip install flask

 

-app.py 파일을 만들어서 작성

from flask import Flask

app = Flask(__name__)



@app.route("/")

def main():

  return "Hello Flask"



#app.run(host='0.0.0.0')

-실행

위 구문 대신에 실행할때 flask run --host=0.0.0.0

 

=>html 출력

-templates 디렉토리에 html 을 작성하고 요청 처리 메서드에서 flask의 render_template 함수에 매개변수로 html 파일을 전달하면 됩니다.

from flask import render_template

@app.route("/hello")
def hello():
  return render_template("google_login.html")

 

=>json 출력:데이터 넘겨주기

-Flask의 jsonify 에 데이터를 넣어서 return 하면 JSON으로 리턴됩니다

from flask import jsonify

@app.route("/json")
def json():
  #클라이언트에 전송할 데이터
  response = [{"name":"wang","age":25},{"name":"병권","age":25}]  
  return jsonify(response)

 

=>데이터베이스 연동이나 일반적인 로직의 처리는 python 처리 로직을 사용하면 됩니다.

 

2)Redis

=>최근의 데이터베이스 분류 방법 중 하나

-disk 기반의 데이터베이스

데이터를 파일로 저장하고 읽어오는 데이터베이스

 

-In Memory Database

데이터를 메모리에 저장했다가 요청이 있을 때 메모리에 저장될 데이터를 빠르게 돌려주는 방식으로 동작하는데 메모리는 디스크보다 훨씬 빠르기 때문에 고속으로 컨텐츠를 저장할 수 있고 사용자들에게 빠르게 데이터를 공급할 수 있음

 

=>개요

-Remote Dictionary Server(Redis)는 오픈 소스 기반의 메모리 key 값 데이터 구조 스토어

-데이터 읽고 쓰는 속도가 빠르기 때문에 캐싱이나 세션 관리, 구독 과 게시 시스템, 순위 표등에 응용

-디스크에 백업하는 기능도 제공해서 점점 사용빈도가 늘어남

-현재까지는 가장 빠른 데이터베이스

 

=>사용을 위한 설치

-https://redis.io/download 에서 다운로드 받아서 설치

Windows 용이 없어서 Docker Hub 에서 다운로드 받아서 사용해야함

 

- Docker 를 이용한 설치

docker pull redis

 

docker run --name 이름 -dit -p 6379:6379 redis

 

=>사용하기 위한 접속

docker run --it --link 이름:redis --rm redis redis-cli -h redis -p 6379

 

=>사용

- 데이터를 만들 때 유효기간 설정 가능

 

 

3)flask을 이용해서 redis 를 사용하는 application 생성

=>redis container  생성

docker run --name myredis -d -p 6379:6379 redis

 

=>flask app 생성

(배포할 때는  가상환경 무조건 우선))

-가상환경 생성

python -m venv ./myvenv

-가상환경 활성화

myvenv/Scripts/activate

-필요한 패키지 설치

pip install flask

pip install redis

 

-설치된 패키지 목록을 텍스트 파일로 내보내기

pip freeze > requirements.txt

 

-디렉토리에 app.py 파일을 만들고 작성:flask 의 실행 파일은 기본이름이 app.py 이고 이름을 변경하면 python 파일이름으로 실행을 함

import time
import redis
from flask import Flask

#Flask 앱 실행 파일을 만들기
app = Flask(__name__)

#레디스에서 데이터를 1개씩 증가시켜서 리턴하는 함수
def web_hit_cnt():
  with redis.StrictRedis(host='192.168.0.26',port=6379) as conn:
    #레디스는 키의 데이터를 1개 증강하는 함수 사용
    #hits 라는 키의 값을 1증가시켜서 리턴
    return conn.incr('hits')
  
  
@app.route('/')
def hello():
  cnt =web_hit_cnt()
  return '''
    <h1 style="text-align:center;color:black;"> Docker Compose App <h1>
    <p style="text-align:center;color:blue;"> Web Access Count :{} times </p>
    '''.format(cnt)
    
#이 파일을 python 명령으로 실행할때 수행할 명령
#이 내용이 없으면 flask run 명령으로 실행을 하고
#이 내용이 있으면 python app.py 명령으로 실행하면 됩니다.abs

if __name__ == '__main__':
  app.run(host='0.0.0.0',port=9000,debug=True)

 

=>flask app 실행

python app.py

 

=>확인

브라우저에서 127.0.0.1:9000 에 접속: 새로고침을 하면 새로 요청을 보이는 숫자가 1씩 증가

이렇게 빠르게 처리되어야하고 저장되어야 하는 경우 redis 을 이용하면 편리합니다

주로 세션관리,순위표 등을 만들 때 이용합니다.


RDBMS:오랜기간동안 저장하고 트랜잭션이 중요한 데이터

NoSQL 중 Mongo DB:읽기 전용 서비스나 agile 개발( 빠르게 동작하는 제품을 개발)에 이용
-읽기는 NoSQL 이 RDBMS 보다 빠름
-NoSQL은 스키마가 없기 때문에 모든 형태의 데이터를 하나의 컬렉션에 저장 가능

NoSQL 중 Redis(In Memory Database)
-읽기 속도나 기록하는 속도는 가장 빠름
-비용도 가장비쌈: 실제 비용 및 컴퓨팅 자원을 의미하기도 합니다.
-싱글 스레드를 사용 (싱글 스레드를 쓰면 중복 예약등을 피할 수 있음)
-실시간 빠르게 처리되어야 하는 시스템에 이용해야함
세션관리(로그인 정보),순위표,장바구니나 배달 정보 같은거에서 사용

 

 

4)만들어진 flask app을 배포하기 위해서 도커 이미지로 만들 Dockerfile 을 생성

=>프로젝트 디렉토리에 Dockerfile 을만들고 Dockerfile 작성

from python:3.8 -alpine

#일반 python은 python 모든 툴을 가지고 있지만 alpine 버전은
#최소로 설치된 상태라서 pip 가 없습니다
RUN apk update && apk add --no-cache bash
RUN apk --update add python3 py3-pip python3-dev

ENV LIBRARY_PATH=/lib:/usr/lib
ENV FLASK_APP=py_app
ENV FLASK_ENV=development

EXPOSE 9000
WORKDIR /py_app
COPY . .
RUN pip install -r requirements.txt

ENTRYPOINT ['python']
CMD['app.py']

 

=>Dockerfile 을 이용해서 이미지 생성

docker build -t flaskapp .

 

=>컨테이너로 실행: 이전에 실행된 컨테이너는 삭제하거나 중지

docker run -dit -p 9000:9000 --name=flaskapp flaskapp

 

5)레디스를 컨테이너로 실행한 후 flask app을 Dockerfile을 만들어서 이미지로 만든 후 컨테이너로 실행했는데 이것을 하나의 작업으로 만들기

 

=>하나의 서비스는 하나의 명령으로 구동되도록 해주어야 합니다.

Microservice 는 만들 떄 가장 중요한 것은 한번에 구동을 시킬 수 있는지 여부

Database 정규화에서 가장 중요한게 한번에 할 수 있느냐 없느냐가 중요

 

=>디렉토리에 docker-compose.yml 파일을 생성하고 작성
version: "3"
services:
  redis:
    image: redis:latest
    ports:
      - 6379:6379
    restart: always

  flask:
    #현재 디렉토리에 있는 Dockerfile을 빌드해서 이미지를 생성
    build: .
    ports:
      - 9000:9000
    depends_on:
      - redis
    restart: always

=>docker-compose 실행
docker-compose up -d

=>컨테이너를 확인해보고 브라우저에서 서비스가 구동되는지 확인(localhost:9000)

5.docker-compose를 이용한 scale up & down

1)scale up & down
=>scale up: 기존의 서버보다 용량이 높은 서버로 교체하는 것
=>scale down: 기존의 서버보다 용량이 작은 서버로 교체하는 것
=>scale out: 현재 서버를 여러 개 복제하는 것

=>docker-compose 에서의 scale up & down 은 동일한 이미지로 부터 만들어지는 컨테이너의 개수를 늘리거나 줄이는 것
이 개념이 하나의 컴퓨터에서 이루어지면 scale up 으로 봐야 하기 때문에 여기서는 scale up 이라는 용어를 사용합니다.

2)명령어
docker-compose up --scale 서비스이름=개수

3)scale up & down 실습
=>docker-compose.yml 파일 수정
version: "3"
services:
  server_db:
    image: redis:latest
    ports:
      - 6379:6379
    restart: always
  server_web:
    image: httpd:2
    ports:
      - 80:80

=>하나의 서비스를 실행
docker-compose up -d

=>서비스 확인
docker-compose ps

=>서비스의 개수를 3개로 설정
docker-compose up --scale server_db=3 server_web=3 -d

=>서비스 확인: 포트 충돌로 인해서 컨테이너 3개씩 만들어지지만 하나씩 만 동작
docker-compose ps

docker-compose ps -a

6.종료 와 중지 명령

1)중지 명령
=>docker-compose -f [현재디렉토리가 아닌 경우 파일 경로] stop 옵션
=>옵션
--rmi: 삭제할 때 이미지도 삭제

-v, --volumes: 볼륨을 삭제

-remove-orphans: 컴포즈 파일에 정의되지 않은 서비스도 삭제

2)삭제 명령
=>docker-compose -f [현재디렉토리가 아닌 경우 파일 경로] down 옵션
=>옵션
--rmi: 삭제할 때 이미지도 삭제

-v, --volumes: 볼륨을 삭제

-remove-orphans: 컴포즈 파일에 정의되지 않은 서비스도 삭제

 

7.Load Balancer

1)개요
=>로드 밸런서는 동일한 역할을 수행하는 애플리케이션을 여러 개 만들고 요청이 왔을 때 하나의 애플리케이션이 아닌 여러 애플리케이션에 부하를 분산해주는 객체
=>도커는 외부 서비스 와 컨테이너를 결합한 로드 밸런서 구현이 가능
=>부하 분산을 위한 필수 네트워크 기술
=>클라이언트 접속량이 많은 경우 이를 여러 대의 동일한 서버에 분산시켜서 요청을 처리
=>리소스 활용도를 최적화하고 처리량을 최대화하며 지연 시간을 줄이고 내결함성 구성을 보장하기 때문에 안정적인 시스템 운영에 도움을 줍니다.
=>실제 구현을 할 때는 각각의 애플리케이션이 서로 다른 region 이나 data center에 구현되서 하나의 애플리케이션이 중지되더라도 다른 애플리케이션이 그 동작을 대신합니다.
이런 경우는 이중화 또는 삼중화라고 합니다.

2)nginx 를 이용한 컨테이너 로드 밸런서 구축
=>동일한 역할을 수행하는 플라스크 웹 애플리케이션을 3개의 컨테이너로 배포하고 앞에 nginx 를 부착해서 로드 밸런싱을 구현
=>웹 애플리케이션을 직접 배포하는 경우는 이러한 로드밸런서를 직접 구현해야 합니다.
pulic cloud 에서는 load balancer 서비스가 제공
도메인은 load balancer 와 연결되어야 합니다.

3)실습
=>루트 디렉토리 생성 - docker-compose.yml 파일 존재

=>루트 디렉토리 안에 4개의 디렉토리 생성: mkdir nginx_alb pyfla_app1 pyfla_app2 pyfla_app3
nginx_alb: nginx

pyfla_app1: web application
pyfla_app2: web application
pyfla_app3: web application

=>nginx 작업
 - nginx_alb 디렉토리로 이동

 - Dockerfile 생성
 FROM nginx:alpine
 RUN rm /etc/nginx/conf.d/default.conf
 COPY nginx.conf /etc/nginx/conf.d/default.conf

 - nginx.conf 파일을 생성하고 작성
 upstream web-alb {
server 172.17.0.1:5001;
server 172.17.0.1:5002;
server 172.17.0.1:5003;
 }
 server {
location / {
proxy_pass http://web-alb;
}
}

=>pyfla_app1 작업
 - pyfla_app1 디렉토리로 이동
 
 - requirements.txt 파일을 생성하고 작성
 blinker==1.6.3
 click==8.1.7
 Flask==3.0.0

 - Dockerfile 생성
 FROM python:3
 COPY ./requirements.txt /requirements.txt
 WORKDIR /
 RUN pip install -r requirements.txt
 COPY . /
 ENTRYPOINT ["python"]
 CMD ["pyfla_app1.py"]

 - pyfla_app1.py 생성
 from flask import request, Flask
 import json
 app1 = Flask(__name__)

 @app1.route("/")
 def hello():
    return "Web Application [1]" + "\n"

 if __name__ == '__main__':
    app1.run(debug=True, host='0.0.0.0')


=>pyfla_app2 작업
 - 실제 구현을 할 때는 3개의 파일을 그대로 복사하면 되는데 서로 다른 앱에 접속되는 걸 확인하기 위해서 파이썬 파일에서 출력되는 부분만 수정

=>pyfla_app3 작업
 - 실제 구현을 할 때는 3개의 파일을 그대로 복사하면 되는데 서로 다른 앱에 접속되는 걸 확인하기 위해서 파이썬 파일에서 출력되는 부분만 수정

=>루트 디렉토리에 docker-compose.yml 파일을 생성하고 작성
version: "3"

services:
  pyfla_app1:
    build: ./pyfla_app1
    ports:
      - "5001:5000"

  pyfla_app2:
    build: ./pyfla_app2
    ports:
      - "5002:5000"

  pyfla_app3:
    build: ./pyfla_app3
    ports:
      - "5003:5000"

  nginx:
    build: ./nginx_alb
    ports:
      - "8080:80"
    depends_on:
      - pyfla_app1
      - pyfla_app2
      - pyfla_app3
      
=>docker-compose 명령 수행
docker-compose up --build

=>컨테이너가 모두 동작하는지 확인하고 브라우저에서 localhost:8080 을 접속한 후 새로 고침이나 다시 접속을 하면 다른 웹 애플리케이션에서 처리를 합니다.

'Study > Cloud,Docker,Kubernetes' 카테고리의 다른 글

Container 기초  (0) 2024.10.15
Kubernetes  (0) 2024.04.08
Docker(3)-Dockerfile  (0) 2024.04.04
Docker(2)  (0) 2024.04.03
Docker(1)  (0) 2024.04.02