nginx는 생성할 express 서버의 리버스 프록시가 될 예정이고, docker-compose는 nginx, express 컨테이너 2개를 생성, 관리할 서비스 관리자입니다. 먼저 express에 사용할 Dockerfile
부터 만듧시다.
FROM node:latest
LABEL name="dev2820"
# /app directory create
RUN mkdir -p /app
# set current work directory as /app
WORKDIR /app
# add current files in /app
ADD ./ /app
# node package download
RUN npm install
CMD npm start
위 도커이미지는 다음과 같은 일을 합니다.
1. node 최신버전 이미지를 가져온다.
2. docker container 내부에 /app
폴더를 만들고
3. current work directory를 /app
으로 설정한다.
4. 현재 위치(raspi_api폴더)의 모든 파일을 컨테이너의 /app
폴더에 집어넣는다.
5. 필요한 node package를 설치한다.
6. npm start를 실행한다.
express-generator로 express앱을 생성하면 npm start
로 서버가 실행될 수 있게 package.json에 기본적으로 start
스크립트가 탑재되어있습니다. (node ./bin/www
를 실행합니다)
먼저 도커 컨테이너로 express 앱을 만들고 실행해봅시다.
docker build --tag express_test:0.0.1 .
현재 위치(raspi_api)의 Dockerfile로 express_test:0.0.1
이미지를 빌드했습니다. 이미지를 통해 컨테이너를 가동시켜보죠.
docker run -it -p 3000:3000 express_test:0.0.1
express_test:0.0.1 이미지를 3000번 포트를 포트포워딩해 가동시켰습니다. 그리고 제 경우 공유기에 연결된 라즈베리파이에서 컨테이너가 가동중이니, 공유기 포트포워딩으로 3000번 포트를 열어줘야겠죠. 공유기 포트포워딩과정은 생략하겠습니다.
라즈베리파이로 다음의 쿼리를 요청했습니다.
192.168.75.198:3000/summary?limit=3&fields=date,uptime
잘 작동하는군요.
서버쪽 로그도 잘 찍혔습니다.
도커가 잘 돌아가는걸 확인했으니 nginx 설정과 docker-compose파일만 잘 작성하면 되겠네요.
혹시 docker-compose가 안깔려있으면 sudo apt-get install docker-compose
로 설치하면 됩니다. aarch64 리눅스 문제인지 docker-compose 홈페이지에서 알려주는 설치가이드가 오히려 작동을 안하더라구요.
먼저 docker-compose.yaml
파일부터 작성해봅시다.
version: '3'
services:
proxy:
image: nginx:latest
container_name: proxy
ports:
- "3000:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
restart: "unless-stopped"
express1:
build:
context: ./
express2:
build:
context: ./
nginx의 가장 최근 이미지를 가져와 컨테이너를 생성합니다. 다음으로 3000번포트를 컨테이너 내부의 80번 포트로 포트포워딩해주고, ./nginx.conf 파일을 컨테이너의 /etc/nginx/nginx.conf에 덮어씌워줍니다. restart: unless-stopped
는 stop시그널을 보내기 전까지 nginx가 오류등으로 죽으면 부활시키는 설정입니다.
express 컨테이너는 express1과 express2로 2개를 만들어줍니다. 현재 위치의 Dockerfile로 컨테이너를 생성합니다.
다음으로 nginx.conf
를 만들어줍니다.
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
upstream express-container {
server express1:3000 weight=10 max_fails=3 fail_timeout=10s;
server express2:3000 weight=10 max_fails=3 fail_timeout=10s;
}
server {
listen 80;
server_name express;
location / {
proxy_pass http://express-container;
}
}
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;
sendfile on;
keepalive_timeout 65;
include /etc/nginx/conf.d/*.conf;
}
upstream이 제일 중요합니다. 근데 별건 없고요. express1과 express2로 부하를 나누어 전달하게 합니다.
최종적으로 위와 같은 폴더 구조를 가지게 됩니다.
docker-compose를 가동시켜봅시다.
docker-compose up
위쪽부분은 생략했습니다. express서버 2개(epxress1_1과 epxress2_1)가 잘 작동하는 것을 볼 수 있습니다. request를 연속으로 4개 보내봅시다.
192.168.75.198:3000/summary?limit=3&fields=date,uptime,cpu_thermal
위 쿼리를 4번 보냈습니다.
request가 express1과 express2로 번갈아 전달되는 것을 볼 수 있습니다.
다음글에서 최종적으로 서비스 구조를 정리하고 글을 마무리하겠습니다.