JavaScript

Docker - Express(TS) - Config(Prod,dev,test)

foxlee 2022. 1. 30. 19:36
  • 참고 링크
  • Docker, proxy 설정
    # docker-compose.yml
    version: "3"
    services:
      proxy:
        build:
          context: ./proxy  # proxy 폴더 안의 도커파일 빌드함
        container_name: proxy
        ports:
          - "16610:80"      # 도커 ip:16610 를 proxy 컨테이너:80 으로 연결해줌
        volumes:
          - ./proxy/nginx.conf:/etc/nginx/nginx.conf
          - ./proxy/log:/var/log/nginx
        restart: "unless-stopped" # 컨테이너가 종료되지 않는다면, 항상 재시작하고, 종료되었다면, 직접 시작하기 전까지는 Docker가 재시작되도 컨테이너는 재시작되지 않음
      express:
        build:
          context: ./server
        container_name: express
        expose:
          - "16620"  # 다른 컨테이너에서 express:16620 으로 접근 가능(컨테이너이름)
        restart: "unless-stopped"
        
        
    # ./proxy/Dockerfile
    FROM nginx
    RUN rm /var/log/nginx/*  # 도커의 nginx 로그 파일들이 access.log -> stdout/ error -> stderr 으로 되어 있어서 도커 로그에서 볼 수 있고 실제 파일에 쓰기가 되지 않음. 파일에 저장하기 위해서 지우면. stdout/stderr 설정이 사라짐
    
    # ./proxy/nginx.conf
    user  nginx;
    worker_processes  1; # 작업자 프로세스 수를 정의 CPU가 2개 이상의 코어라면 증가 권장
    
    pid        /var/run/nginx.pid;
    
    events {                     
        worker_connections  1024; # 작업자 프로세스가 동시에 처리할 수 있는 접속 수를 정의
    
    }                            
    
    http {
        include       /etc/nginx/mime.types; #  파일 확장명과 MIME 타입 목록
        default_type  application/octet-stream;
    
        upstream docker-express {  # 여기서 정의해주면 아래 sever의 location/ 의 proxy_pass 에서 연결 # 서버 여러개를 넣어 로드 밸런싱(최소 연결된 서버, ip 해쉬로 연결)
            server express:16620;  # port 16620은 컨테이너 내의 express의 포트로 다른 컨테이너에서 접근(즉, client -> nginx -> express) /  (client -> express 안됨)
        } # upstream 여러대의 컴퓨터가 순차적으로 어떤 일을 처리할 때 어떤 서비스를 받는 서버를 의미
          #  express:16620의 api 서버는  업스트림 서버, Nginx는 DownStream 서버라고 할 수 있음
    
    
        server {
            listen 80;
            server_name localhost;
    
            location / {
    		proxy_http_version 1.1;
                	proxy_pass         http://docker-express;
            }
    
        }
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
        error_log /var/log/nginx/error.log notice;
                                                    
        sendfile        on;                                                                         
        keepalive_timeout  65;                                                                      
        include /etc/nginx/conf.d/*.conf;           
    }
    
    
    # ./server/Dockerfile
    FROM node:16
    
    WORKDIR /usr/src/app
    
    COPY package*.json ./
    
    RUN npm install
    # If you are building your code for production
    # RUN npm ci --only=production
    
    # Bundle app source
    COPY . .
    
    CMD [ "npm", "run", "start" ]
  • Env 설정하기
// 환경 변수 선언
// /.env 
// /.env.development
// /.env.test

// /environment.d.ts
declare global {
    namespace NodeJS {
      interface ProcessEnv {
        NODE_ENV: 'development' | 'production' | 'test';
        APP_PORT?: string;
      }
    }
}

// /.babelrc -
{
    "plugins": [
        ["transform-inline-environment-variables", {
            "include": [
                "NODE_ENV",
                "APP_PORT"
            ]}
        ]
    ]
}

//  /src/config.ts
import {config as configDotenv} from 'dotenv'
import {resolve} from 'path'

switch(process.env.NODE_ENV) {
    case "development":
        configDotenv({
        path: resolve(__dirname, "../.env.development")
        })
        break
    case "test":
        configDotenv({
            path: resolve(__dirname, "../.env.test")
        })
        break
    case "production":
        configDotenv({
            path: resolve(__dirname, "../.env")
        })
        break
    default:
        throw new Error(`'NODE_ENV' ${process.env.NODE_ENV} is not handled!`)
}

// /src/server.js
"use strict";
import './config'
import app from "./app"

const port = process.env.APP_PORT;

app.listen(port, () => {
   console.log(`Server is running on ${port} port`);
});

// /package.json
"scripts": {
    "dev": "set NODE_ENV=development&& nodemon --watch \"src/**/*.ts\" --exec \"ts-node\" src/server.ts",
    "start-dev": "set NODE_ENV=development&& node dist/src/server.js",
    "build-dev": "copy .env.development dist && tsc -p ./",
    "test": "set NODE_ENV=test&& jest --forceExit --detectOpenHandles",
    "start": "NODE_ENV=production node dist/src/server.js",
    "build": "tsc -p ./ && cp .env ./dist/.env"
  },  
// dev, -dev 는 윈도우용(set 설정, copy 파일 폴더)
// .env.production  dist로 복사