본문 바로가기

Docker

Docker Compose로 Nginx + NodeJS + SSL 환경 만들기

만약 NodeJS를 사용하여 만든 웹 서버를 어딘가에 deploy 하고 싶다면 pm2를 사용하거나 nginx로 port를 연 후 proxy를 통하여 실행 중인 NodeJS 웹 서버와 연결하여 사용하게 됩니다. 그 중 Nginx로 환경 제작에 대해 알아보겠습니다.

구성

우선 ssl 까지 하는 것이 목표이기 때문에 저는 certbot을 통하여 ssl 인증서를 발급받기로 하였습니다. 그중 순서의 문제가 하나 발생하였는데요. 바로 ssl 인증서를 발급받기 전까진 key 파일이 없으므로 nginx container가 죽는 상황이 발생하였습니다. 그러므로 총 2개의 docker-compose 파일을 생성하였습니다.

 

  • docker-compose.yml: 실제 서버 구동용
  • docker-compose.ssl.yml: ssl 인증서 발급용

우선 인증서 발급용 yml 파일부터 확인 후 실제 서버 구동용 yml 파일을 확인 해봅시다.

1. docker-compose.ssl.yml 설정

version: "2"
services:
  nginx:
    container_name: nginx
    image: nginx
    volumes:
      - ./templates/ssl:/etc/nginx/templates
    ports:
      - "80:80"
    env_file:
      - ./.env
  certbot:
    depends_on:
      - nginx
    image: certbot/certbot
    container_name: certbot
    volumes:
      - ./certbot/etc:/etc/letsencrypt
      - ./certbot/var:/var/lib/letsencrypt
      - ./certbot/www:/var/www/html
    command: "certonly --webroot --webroot-path=/var/www/html --email ${SSL_EMAIL} --agree-tos --no-eff-email --force-renewal -d ${SERVER_NAME} -d www.${SERVER_NAME}"
    env_file:
      - ./.env

ssl 발급용은 yml 파일을 위와 같이 작성되었는데요. 우선 천천히 nginx service부터 확인해봅시다.

1-1. Nginx

Volumes

  • nginx conf 파일을 /etc/nginx/templates와 volume으로 연결하여 설정하였습니다. templates 폴더로 연결한 이유는 conf 파일에서 환경변수를 사용하기 위함입니다. (1.19 버전부터 가능합니다)

ports

  • http 통신을 하므로 80 포트를 80과 연결해줍니다.

*. conf.template

server {
     listen 80;
     listen [::]:80;

     server_name ${SERVER_NAME} www.${SERVER_NAME};

     location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }
}

 

  • ${SERVER_NAME}:. env 파일에서 설정된 환경변수입니다.
  • 인증서 발급을 위한 경로를 설정해줍니다.

1-2. Certbot

Volumes

  • ssl 인증서 관련 파일을 volume으로 데이터를 공유하였습니다.

1-3. 실행

$ docker-compose -f docker-compose.ssl.yml up

위 명령어를 입력하여 up 해줍니다. 정상적으로 실행하면 위 그림과 같이 자신의 도메인명으로 폴더가 하나 생성된 것을 확인할 수 있습니다. 만약 발급이 안된다면 nginx가 실행 중인지 확인해주세요.

2. docker-compose.yml 설정

version: "2"
services:
  nginx:
    container_name: "nginx"
    build:
      context: "./"
      dockerfile: "./docker/nginx/Dockerfile"
    volumes:
      - ./templates/production:/etc/nginx/templates
      - ./certbot/etc:/etc/letsencrypt
      - ./certbot/www:/var/www/certbot
    ports:
      - "80:80"
      - "443:443"
    env_file:
      - ./.env
  nodejs:
    container_name: "nextjs"
    build:
      context: "./"
      dockerfile: "./docker/nodejs/Dockerfile"

2-1. Nginx

ports

  • ssl 연결을 위해 443 port 또한 오픈시켰습니다.

volumes

  • conf 파일을 443을 listen 하고 key파일을 사용하는 conf 파일로 사용하였습니다.
  • 생성된 인증서 연결을 위해 certbot을 volume으로 연결하였습니다.

*. conf.template

upstream nodeserver {
    server nodejs:3000;
}

server {
    listen 80;
    listen [::]:80;

    server_name ${SERVER_NAME} www.${SERVER_NAME};
    server_tokens off;

    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl;
    server_name ${SERVER_NAME} www.${SERVER_NAME};
    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/${SERVER_NAME}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${SERVER_NAME}/privkey.pem;

    location / {
        proxy_pass      http://nodeserver/;
        rewrite /(.*) /$1 break;
        proxy_redirect    default;
        proxy_set_header  Host $host;
        proxy_set_header  X-Real-IP $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Host $server_name;
    }
}

80 포트로 접속 시 443으로 리다이렉션 시킨 후 proxy를 통하여 node 서버와 통신합니다.

2-2. NodeJS

# Dockerfile
FROM node:16
ARG USER_ID=node

USER $USER_ID

RUN mkdir /home/$USER_ID/.npm-global
ENV PATH=/home/$USER_ID/.npm-global/bin:$PATH
ENV NPM_CONFIG_PREFIX=/home/$USER_ID/.npm-global

RUN npm install yarn --global
RUN mkdir -p /home/$USER_ID/app
WORKDIR /home/$USER_ID/app
COPY --chown=$USER_ID . .

RUN yarn
EXPOSE 3000
ENV PORT 3000
CMD ["yarn", "build:start"]

NodeJS Dockerfile입니다. 권한 문제를 해결하기 위해 npm global시 설치되는 경로를 home/node/. npm-global로 변경하였습니다. image를 모두 생성 후 yarn build:start 명령을 실행해 NextJS 서버를 실행합니다. build:start 명령어를 build 후 구동시키는 명령어입니다.

2-3. 테스트

$ docker-compose up

ssl 인증된 NextJS

정상적으로 ssl 인증된 NextJS 서버를 구동되는 것을 확인할 수 있습니다. 전체 코드 및 디렉토리 구조는 아래 github 에서 확인 가능합니다.

https://github.com/dawan0111/docker-nginx-nodejs-certbot

 

GitHub - dawan0111/docker-nginx-nodejs-certbot: docker로 ssl 인증된 nodejs 웹 서버 생성 테스트

docker로 ssl 인증된 nodejs 웹 서버 생성 테스트. Contribute to dawan0111/docker-nginx-nodejs-certbot development by creating an account on GitHub.

github.com

 

'Docker' 카테고리의 다른 글

Docker로 ROS2 Foxy 설치하기 + GUI 설정 (NOVNC)  (0) 2022.07.09