Computer Science/BackEnd

Docker compose로 Django, Nginx, Mysql 띄우기

토마토. 2023. 6. 22. 21:19

docker compose로 django, nginx, mysql를 띄우면, 다음 두 개의 명령어만으로 서버를 띄울 수 있다. 

docker compose build
docker compose up

 

  • step 1. 디렉토리 구조 설정

나 같은 경우는 다음과 같이 구조를 설정했다. django, mysql, nginx를 따로 폴더를 만들어주고, 각 폴더에 Dockerfile을 생성했다. 

- django/
- mysql/
- nginx/
docker-compose.yaml
  • step 2. django Dockerfile 작성
FROM python:3.8

# 컨테이너 내부 기준 디렉토리 생성
WORKDIR /app 
# django/requirements.txt를 컨테이너 app/requirements.txt로 복사
COPY ./django/requirements.txt requirements.txt
# 기반 세팅
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
# django 내부 모든 파일을 app/ 이하로 복사
COPY . .
  • step 3. nginx Dockerfile, conf 작성
- nginx/
ㄴ Dockerfile
ㄴ nginx.conf
ㄴ project.conf

nginx/Dockerfile 은 다음과 같다. 

FROM nginx:1.15.8

RUN rm /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/
RUN rm /etc/nginx/conf.d/default.conf
COPY project.conf /etc/nginx/conf.d/

nginx/nginx.conf

#ngnix.conf

#Define the user that will own and run the Nginx server
user  nginx;

# Define the number of worker processes; recommended value is the number of
# cores that are being used by your server
worker_processes  1;

# Define the location on the file system of the error log, plus the minimum
# severity to log messages for
error_log  /var/log/nginx/error.log warn;

# Define the file that will store the process ID of the main NGINX process
pid        /var/run/nginx.pid;


# events block defines the parameters that affect connection processing.
events {
    # Define the maximum number of simultaneous connections that can be opened by a worker process
    worker_connections  1024;
}


# http block defines the parameters for how NGINX should handle HTTP web traffic
http {
    # Include the file defining the list of file types that are supported by NGINX
    include       /etc/nginx/mime.types;

    # Define the default file type that is returned to the user
    default_type  text/html;

    # Define the format of log messages.
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    # Define the location of the log of access attempts to NGINX
    access_log  /var/log/nginx/access.log  main;

    # Define the parameters to optimize the delivery of static content
    sendfile        on;
    tcp_nopush     on;
    tcp_nodelay    on;

    # Define the timeout value for keep-alive connections with the client
    keepalive_timeout  65;

    # Define the usage of the gzip compression algorithm to reduce the amount of data to transmit
    #gzip  on;

    # Include additional parameters for virtual host(s)/server(s)
    include /etc/nginx/conf.d/*.conf;
}

nginx/project.conf

server {
    # nginx 서버가 80 포트 변화를 체크함
    listen 80;
    server_name localhost;

    location / {
        proxy_pass http://django_app:8000;

        # Do not change this
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /static/ {
        alias /app/venti/static/;
    }
}
  • step 4. mysql Dockerfile 작성
FROM mysql:latest

ENV MYSQL_ROOT_PASSWORD=pass

COPY ./data.sql /docker-entrypoint-initdb.d/data.sql

mysql/ 하위 폴더에 data.sql 파일도 생성한다. 

CREATE DATABASE IF NOT EXISTS my_database;

USE my_database;

 

  • step 5. docker-compose.yaml
version: "3.9" # docker version

services:
  nginx:
    container_name: nginx
    build: ./nginx
    ports:
      - "8084:80"
    volumes: # 필요한 파일 내파일:도커파일
      - ./nginx/nginx.conf:/etc/nginx.conf.d
      #- ./django/app:/app
      #- ./django/venti/static:/static
    depends_on:
      - django_app
    networks:
      - app-tier
  mysql:
    build: ./mysql
    ports:
      - "3306:3306"
    networks:
      - app-tier  
  django_app: # nginx proxy name
    container_name: django_app
    build:
      context: .
      dockerfile: ./django/Dockerfile
    command: 
      bash -c "
      chmod +x ./wait-for-it.sh &&
      ./wait-for-it.sh mysql:3306 -t 10 &&
      python3 manage.py makemigrations &&
      python3 manage.py migrate &&
      gunicorn admin.wsgi:application --bind 0.0.0.0:8000"
    ports:
      - "8000:8000"
    expose:
      - "8000"
    depends_on:
      - mysql
    links:
      - mysql:mysql
    restart: always # 변경사항 있을 때마다 리스타트
    volumes:
      - ./django:/app
    networks:
      - app-tier
networks:
  app-tier:
    driver: bridge

 

참고) wait-for-it.sh

mysql depends_on이라고 해도 실행 순서는 같지만 끝나는 순서는 같지 않음

따라서 mysql 끝나고 django가 시작되도록 해야한다. 

wait-for-it.sh 는 공식 깃허브에서 다운 받았는데, 

django/wait-for-it.sh 로 저장하면 되고, 파일 내용은 vishnubob/wait-for-it: Pure bash script to test and wait on the availability of a TCP host and port (github.com) 이 링크에서 다운 받을 수 있다. 

 

해커톤에서 처음으로 nginx, gunicorn으로 배포할 때 docker를 쓰지 않아 끔찍한 밤을 보냈는데, 도커를 쓰니 정말 편리하고 깔끔하게 배포할 수 있었다. 두 문장으로 배포를 끝내다니! 이번 달에 가장 기쁜 순간이었다. 

이제 github action으로 더 편리하게 배포를 해보아야겠다 ~_~