✔ Docker-Compose
작성 방법
기본 구성
버전 정의
- yaml 코드의 첫 줄에는 버전을 정의해야 한다.
서비스 정의
- 컨테이너를 실행하는 것과 동일한 개념
- 서비스 이름을 정의하고, 하위 레벨에 도커 명령과 유사하게 컨테이너 실행에 필요한 옵션을 작성
docker run --name=myweb nginx:latest
가 있을 때, yaml은?
version "3"
services:
myweb:
image: ningx:latest
version "3"
services:
myweb:
build: .
mariadb:
build:
context: .
dockerfile: 도커파일경로
하위 옵션
- container_name
- --name
과 같은 옵션으로, 컨테이너 이름설정
- ports
- -p
와 같은 옵션으로, 포트포워딩 설정
- expose
- 외부로 노출하지는 않고, 필요 시 링크로 연결된 서비스와 서비스 간의 통신을 허용할 때 사용하는 포트
- networks
- --net
옵션과 같은 옵션으로, 하나의 네트워크로 묶을 때 사용
- volumes
- -v
옵션과 같은 옵션으로, 볼륨을 사용하고자 할 때 사용
- environments
- -e
옵션과 같은 옵션으로, 환경 설정을 할 때 사용
- command
- 서비스가 구동된 뒤 실행할 명령어를 작성
- restart
- --restart
옵션과 동일하며, 재시작 옵션
- depends_on
- 서비스 간의 종속성을 의미하며, 먼저 실행해야 하는 서비스를 지정
네트워크 정의
- 네트워크
- 여러 컨테이너들이 서로 연결될 수 있도록 해주는 것
- docker-compose는 네트워크를 지정하지 않으면, 자체 기본 네트워크를 자동으로 생성
- 최상위 레벨에 networks 지정 시, 해당 이름의 네트워크가 생성되고, 대역은 172.x.x.x로 자동할당 됩니다.
- cmd에다가
docker network ls
해보면 bridge로 되어있는 것이 기본
볼륨 정의
- 도커 엔진 내부의 공간과 컨테이너 사이의 데이터를 공휴가 위한 것
- 컨테이너 내부의 데이터를 반 영구적으로 보관하기 위한 목적으로 사용
✔ 도커 명령어와 Docker-compose 비교
- DB-mysql:8.0을 사용하고, 웹-wordpress:5.7을 이용하는 웹 애플리케이션 서비스
- 각 컨테이너는 각각의 볼륨을 소유하고, 2개의 컨테이너는 하나의 네트워크로 묶어서 사용
- 이 작업을 할 때, wordpress나 redmine을 많이 사용하는데, 이유는 wordpress나 redmine은 mysql이나 mariadb가 연결되지 않으면 에러를 발생시키기 때문이다.
도커 명령어 사용
- 2개의 볼륨 생성
- docker volume create mydb_data
- docker volume create myweb_data
- 볼륨 확인
- docker volume ls
- 네트워크를 생성
- docker network create 이름
- 네트워크를 확인
- docker network ls
- MySQL 컨테이너부터 생성해보자(wordpress)
- docker run -dit --name=컨테이너이름 -v mydb_data:/var/lib/mysql --net=myapp-net --restart=always -p 3306:3306 -e MYSQL_ROOT_PASSWORD=관리자비밀번호 -e MYSQL_DATABASE=데이터베이스이름 -e MYSQL_USER=기본유저 -e MYSQL_PASSWORD=유저비밀번호 mysql:8.0
- docker run -dit --name=mysql_app -v mydb_data:/var/lib/mysql --net=myapp-net --restart=always -p 3306:3306 -e MYSQL_ROOT_PASSWORD=supersonic -e MYSQL_DATABASE=sonic -e MYSQL_USER=sonic -e MYSQL_PASSWORD=supersonic mysql:8.0
- 확인: docker ps
- docker ps
에서 안되고 docker ps -a
에서 확인된다면 실행 오류
- 포트 확인 : db 접속도구에서 확인해보자 (3306번 포트)
- WordPress 컨테이너 생성
- 로그 데이터는 사용자가 보아야 하는 데이터이므로, 볼륨에 연결하지 않고 하드디스크에 직접 연결하기도 합니다.
- docker run -dit --name=컨테이너 이름 -v myweb_data:/var/www/html wordpress:5.7 -v ${PWD}/myweb-log:/var/log --net=myapp-net --restart=always -p 외부에노출할포트:80 -e WORDPRESS_DB_HOST=데이터베이스컨테이너:포트번호 -e WORDPRESS_DB_NAME=사용할데이터베이스이름 -e WORDPRESS_DB_USER=데이터베이스계정 -e WORDPRESS_DB_PASSWORD=계정비밀번호 --link 사용할데이터베이스컨테이너:mysql wordpress:5.7
- docker run -dit --name=wordpress_app -v myweb_data:/var/www/html -v ${PWD}/myweb-log:/var/log --net=myapp-net --restart=always -p 8001:80 -e WORDPRESS_DB_HOST=mysql_app:3306 -e WORDPRESS_DB_NAME=sonic -e WORDPRESS_DB_USER=sonic -e WORDPRESS_DB_PASSWORD=supersonic --link mysql_app:mysql wordpress:5.7
- 최종
- docker run -dit --name=wordpress_app -v myweb_data:/var/www/html -v ./myweb-log:/var/log --net=myapp-net --restart=always -p 8008:80 -e WORDPRESS_DB_HOST=mysql_app:3306 -e WORDPRESS_DB_NAME=sonic -e WORDPRESS_DB_USER=sonic -e WORDPRESS_DB_PASSWORD=supersonic --link mysql_app:mysql wordpress:5.7
- ${PWD}
부분이 틀렸다 → 현위치로 -v ./myweb-log
로 수정
- 확인 : docker ps
- 브라우저에서 localhost:외부에 노출할 포트번호
docker-compose.yaml 이용
빈 디렉 생성
디렉에 docker-compose.yaml 생성
version: "3"
services:
mydb:
image: mysql:8.0
container_name: mysql_app
volumes:
- mydb_data:/var/lib/mysql
networks:
- myapp-net
restart: always
ports:
- "3306:3306" # 3306 쓰고있으면 mysql 컨테이너 끄기(stop)
environment:
MYSQL_ROOT_PASSWORD: supersonic
MYSQL_DATABASE: sonic
MYSQL_USER: sonic
MYSQL_PASSWORD: supersonic
myweb:
image: wordpress:5.7
container_name: wordpress_app
volumes:
- myweb_data:/var/www/html
- ./myweb-log:/var/log
networks:
- myapp-net
restart: always
ports:
- "8008:80"
environment:
WORDPRESS_DB_HOST: mydb:3306
WORDPRESS_DB_NAME: sonic
WORDPRESS_DB_USER: sonic
WORDPRESS_DB_PASSWORD: supersonic
depends_on:
- mydb
networks:
myapp-net: {}
volumes:
mydb_data: {}
myweb_data: {}
- networks는 backend-net과 frontend-net 사용이 가능하다고 하네
✔ Load Balancer
Load Balancing (부하 균등)
- 동일한 기능을 수행하는 여러 개의 애플리케이션을 만들어두고 요청이 오면 적절한 애플리케이션(하드웨어)을 선택해서 수행하도록 해주는 기능
- 부하 분산을 위한 필수 네트워크 기술
- 리소스 활용도를 최적화하고 처리량을 최대화하며 지연 시간을 줄이고, 내결함성(Fault Tolerance) 구성을 보장해서 안정적인 시스템 운영이 가능하도록 합니다.
- Docker는 HaProxy, Nginx/Apache 등 외부 서비스를 이용해서 로드 밸런싱을 구현하는 것이 가능합니다.
로드 밸런싱 알고리즘
- 라운드 로빈 알고리즘 (RR)
- 클라이언트 요청을 서버의 가중치를 고려해서 구성된 서버에 균등 배분하는 방식으로 경로 보장이 안됨
- 최소 연결(Least Connection)
- 현재 연결된 클라이언트 수가 가장 적은 서버로 요청을 전달, 경로 보장이 안됨
- IP Hash
- 해시 키를 이용해서 IP별 INDEX를 생성해서 동일 IP주소는 동일 서버로의 경로를 보장하는 방식으로, 해당 서버의 장애가 발생하면 주소는 변경되고, 균등 배분 보장이 안됨
- 트랜잭션이 긴 작업에 이용함
- General Hash
- 사용자가 정의하는 키를 이용한 서버 지정 방식
- 최소 시간(Least Time)
- 요청에 대한 낮은 평균 지연 시간을 기준으로 계산해서 서버를 지정
- random
로드 밸런서 구현
- 동일한 python flask 앱을 3개 만들고, 앞에 nginx를 추가해서 클라이언트의 요청을 nginx가 받아서 RR 방식을 이용해서 각 flask 앱에 전송
- 원래는 모든 flask 앱이 동일한 모양이어야 하지만, 편의상 보여지는 내용을 다르게 구성
실습
=>디렉토리 생성
mkdir loadbalancer
cd loadbalancer
mkdir nginx_alb pyfla_app1 pyfla_app2 pyfla_app3
____
=>nginx 작업
- cd nginx_alb
____
- Dockerfile 생성
FROM nginx
#기본 환경 설정을 제거
RUN rm /etc/nginx/conf.d/default.conf
#환경 설정 파일을 복사
COPY nginx.conf /etc/nginx/conf.d/default.conf
____
- niginx.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 작업
- Dockerfile 생성
FROM python:3
COPY . .
WORKDIR /
RUN pip install flask
COPY . /
ENTRYPOINT ["python"]
CMD ["app.py"]
____
- app.py 파일 생성
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Web Application [1]" + "\n"
#flask를 5000번 포트로 실행
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0")
=>pyfla_app2 작업
pyfla_app1 의 파일을 pyfla_app2 디렉토리로 복사
=>pyfla_app3 작업
pyfla_app1 의 파일을 pyfla_app3 디렉토리로 복사
=>확인
python app.py
docker build -t flaskapp .
docker run -dit -p 5000:5000 --name=flaskapp flaskapp
____
=>loadbalance 디렉토리에 docker-compose.yaml 파일을 만들고 작성
___
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
- 브라우저에서 localhost:8080 를 입력해서 수행한 후 새로고침을 수행