Backend - docker-compose

kukudas·2022년 2월 26일
0

industry-app-client

목록 보기
4/11

docker-compose.yml

아래 docker-compose.yml로 각각의 이미지들을 만들고 해당 이미지로 컨테이너들을 생성해주고 이미지를 생성한 컨테이너들을 묶어주는 하나의 공간인 네트워크도 만들어줌. 해당 네트워크로 컨테이너들이 소통 가능함(장고에서 mysql로 접근하는 것 같은것 등).

예시) job_finished:0.3.2라는 이름의 이미지를 context: ./project/industry_alarm/에 있는 Dockerfile로 생성함.

services:
	django:
    db:

에서 django랑 db 같은 이름은 compose build 했을때
컨테이너 이름이 해당 docker-compose.yml 파일이 있는 디렉토리이름_컨테이너이름 이런 식으로 컨테이너 이름이 지정되고 빌드 했을때 컨테이너끼리 구별해야하기 때문에 필요함.
아래는 sudo docker ps로 컨테이너 전체 출력한 것임.

위 이미지를 보면 NAMES에 docker-compose.yml 파일이 있는 pathfinder-docker 디렉토리랑 컨테이너 이름인 django가 합쳐진 pathfinder-docker_django_1이라는 이름으로 컨테이너가 만들어진 것을 볼 수 있음.

sudo docker-compose up --build -d django으로 django 컨테이너만 따로 새로 빌드해줄 수 있음. 변경점 있을때 전부 하면 시간오래걸리니 바꾼거만 따로 해줘야함.

  1. docker-compose up -d 로(-d는 daemon으로 백그라운드 실행옵션임.) 이미지랑 컨테이너들이랑 컨테이너들을 묶은 네트워크를 만들어줌.
ports:
	- "8001:80"

는 외부에서 8001 포트로 들어왔을때 컨테이너의 80번 포트로 넣어줌.

// docker-compose.yml
version: '3'

services:
    django:
        image: job_finished:0.3.2
        build:
            context: ./project/industry_alarm/
        restart: always
        env_file:
            - ./project/industry_alarm/industry_alert/mysite/.env
            - ./project/industry_alarm/industry_alert/account/.env
        depends_on:
            - db
            - redis
        ports:
            - "8001:80"
        networks:
            - pathfinder-network

    db:
        image: mysql:5.7
        volumes:
            - database:/var/lib/mysql
            - ./config/start.sql:/docker-entrypoint-initdb.d/start.sql
            - ./config/eve_universe.sql:/docker-entrypoint-initdb.d/eve_universe.sql
            - ./pathfinder.sql:/pathfinder.sql
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
        ports:
            - "3306:3306"
        networks:
            - pathfinder-network
    redis:
        image: redis:alpine
        restart: always
        ports:
            - "6379:6379"
        command: redis-server --port 6379
        networks:
            - pathfinder-network
    pathfinder:
        # build:
        #   context: .
        #   dockerfile: Dockerfile
        restart: always
        image: somniholic/pathfinder:latest
        env_file: .env
        volumes:
            - ./ssl/privkey.pem:/etc/letsencrypt/live/pathfinder.fish-vending-machine.com/privkey.pem
            - ./ssl/fullchain.pem://etc/letsencrypt/live/pathfinder.fish-vending-machine.com/fullchain.pem
        ports:
            - "80:80"
            - "8020:8020"
        networks:
            - pathfinder-network
    slave-of-bukandara:
        build:
            context: ./seat-bot
            dockerfile: Dockerfile
        env_file:
            - ./seat-bot/.env
        volumes:
            - ./seat-bot/notification-list.txt:/code/notification-list.txt
            - ./seat-bot/news-list.txt:/code/news-list.txt
    aura:
        build:
            context: ./Aura
            dockerfile: Dockerfile
        env_file:
            - ./Aura/.env
        volumes:
            - ./Aura/news-list.txt:/code/news-list.txt

volumes:
    database: {}
networks:
    pathfinder-network:

Dockerfile

위 docker-compose.yml 파일에서 ./project/industry_alarm/에 있는 Dockerfile로 job_finished:0.3.2라는 이미지를 생성함.

image: job_finished:0.3.2
build:
	context: ./project/industry_alarm/

./project/industry_alarm/으로 가면 아래의 도커 파일이 있음.

FROM oem0404/ubuntu_python:0.3

# ADD 복사할파일경로 이미지에서파일이위치할경로
ADD . /code/

RUN pip install -r /code/requirements.txt

RUN chown -R www-data:www-data /code

RUN ln -s /code/nginx-app.conf /etc/nginx/sites-enabled/
RUN ln -s /code/supervisor-app.conf /etc/supervisor/conf.d/

# WORKING DIRECTORY 변경
WORKDIR /code

# 외부 포트 포워딩을 도커 VM으로 연결하려면 도커 VM도 포트 노출해줘야함
EXPOSE 80 22

# 해당 이미지를 컨테이너롤 띄울 때 디폴트로 실행할 커맨드나, ENTRYPOINT 명령문으로 지정된 커맨드에 디폴트로 넘길 파라미터를 지정할 때 사용
# 여기서는 supervisor 실행
CMD ["supervisord", "-n"]

그러면 이제 docker build로 이미지를 생성할 때
1. FROM oem0404/ubuntu_python:0.3
oem0404/ubuntu_python:0.3에다가 python이랑 ubuntu 이미지를 만들어놨는데 이거를 가져오고
2. ADD . /code/
ADD 복사할파일경로의 문법으로 이미지에서 파일이 위치할 경로를 설정해줌. 따라서 ./code/에 파일이 위치하게됨.
3. RUN pip install -r /code/requirements.txt
requirements.txt에 있는 패키지들 설치해줌.
4. RUN chown -R www-data:www-data /code
www-data는 우분투에서 기본으로 제공하는 유저임. nginx가 기본적으로 그 유저 권한으로 웹 서버를 사용함. 웹서버는 www-data가 접근 가능한 파일들을 접근할 수 있음.
www-data:www-data에서 :뒤는 그룹인데 www-data 그룹은 www-data 유저의 그룹 소속이 www-data임. 따라서 /code를(-R로 안에도 재귀로 싹 다 바꿔줌)의 소유자와 그룹을 www-data유저와 www-data그룹으로 바꿔줌.
5.

RUN ln -s /code/nginx-app.conf /etc/nginx/sites-enabled/
RUN ln -s /code/supervisor-app.conf /etc/supervisor/conf.d/

심볼릭링크 만들어서 각각 /etc/nginx/sites-enabled/, /etc/supervisor/conf.d/에 넣어줌. 여기가 설정파일이 있어야하는 곳임. 여기서 nginx랑 supervisor가 가져다가 쓰게됨. 권한은 lrwxrwxrwx 1 root root 20 Feb 26 17:48 nginx-app.conf -> /code/nginx-app.conf여서 실행에는 문제 없음.
6. WORKDIR /code
working directory를 code 디렉토리 안으로 변경해줌. cd랑 똑같음. 이제 나오는 명령문은 해당 디렉토리를 기준으로 실행함.
7. EXPOSE 80 22

ports:
	- "8001:80"

에서 외부의 8001번 포트를 컨테이너의 80번 포트로 이어줬으니 컨테이너 내부의 80번 포트를 expose 해줘야함. 22번은 SSH에서 사용함. 맘대로 포트 번호 정해도 되는데 자주쓰는 포트들이 있음.

웹서버 80, mysql 3306 등

  1. CMD ["supervisord", "-n"]
    로 supervisor를 실행하고 supervisor-app.conf에 등록된 프로세스들을 실행함.

    supervisrod는 프로세스 매니저임. 꺼지면 자동으로 다시 켜주는거 같은거 해줌.

// supervisor-app.config
[program:app-uwsgi]
command = /usr/local/bin/uwsgi --ini /code/uwsgi.ini
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

[program:nginx-app]
command = /usr/sbin/nginx
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

[program:app-celery]
command = celery -A mysite worker --beat --scheduler django --loglevel=info
directory = /code/industry_alert
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

command를 순서대로 실행하는데 uswgi에서 socket = /tmp/industry-alert.sock로 소켓 만들고

// uswgi.ini
[uwsgi]
# this config will be loaded if nothing specific is specified
# load base config from below
ini = :base

# %d is the dir this configuration file is in
socket = /tmp/industry-alert.sock
master = true
processes = 4

[dev]
ini = :base
socket = :8001
logto = /dev/stdout

[local]
ini = :base
http = :8000
home = /path/to/my/env

[base]
# chdir to the folder of this config file, plus app/website
chdir = %dindustry_alert
# load the module from wsgi.py, it is a python path from
# the directory above.

#make sure you hook up your wsgi app correctly
module = mysite.wsgi:application
# allow anyone to connect to the socket. This is very permissive
chmod-socket = 666

nginx를 켜서 80번 포트(ports: - "8001:80")
에서 아까 uswgi에서 만든 소켓('/tmp/industry-alert.sock;')에서 듣고 있다가 들어오는 tcp 요청을 해당 소켓 파일로 넣어주고 uwsgi에 워커프로세스가 있는데 그 워커가 파이썬 request 객체로 바꿔서 uwsgi.ini에 써있는module = mysite.wsgi:application로 보내줌.
http니까 다시 응답도 보내줘야하는데 uwsgi 워커랑 nginx가 응답을 기다리고 있음. 장고가 requset객체를 uwsgi 워커로 다시 보내주면 이제 워커가 tcp로 바꿔서 nginx로 보내주고 nginx로 이 tcp가 다시 나감.

// nginx-app.config
upstream django {
	server unix:/tmp/industry-alert.sock;
}

server {
	listen 80;
	
	charset utf-8;

	client_max_body_size 20m;

	location / {
		uwsgi_pass django;
		include /code/uwsgi_params;
	}

	location /static {
		alias /code/industry_alert/static;
	}
	
	proxy_set_header Host $http_host;
	proxy_redirect off;
	proxy_set_header X-Real-IP $remote_addr;
	proxy_set_header X-Scehme $scheme;
	proxy_connect_timeout 90;
	proxy_read_timeout 90;

}

// celery 이거 설명 추가해야함.

0개의 댓글