JavaScript
Docker - Express(TS) - Config(Prod,dev,test)
foxlee
2022. 1. 30. 19:36
- 참고 링크
- Docker https://nodejs.org/en/docs/guides/nodejs-docker-webapp/
- Express https://expressjs.com/
- Directory structure for JavaScript, Node projects https://gist.github.com/daehan0226/52aaaecd44735ecf8f8c4f37cb98b6c2
- 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로 복사