Как сделать Https с помощью Traefik для моего проекта PERN, теперь он возвращает плохой шлюз 502

#node.js #docker #nginx #docker-compose

Вопрос:

Я создал проект стека PERN. Он отлично работает в Http, я хочу, чтобы он работал в Https. Структура docker выглядит следующим образом:

        |--- api (Express)
       |     |--- Dockerfile
       |     
       |     
       |--- app (React)
       |     |--- Dockerfile
       |     |--- compose/nginx/nginx.conf  
       |     
       |--- docker-compose.yml
 

—Это файл docker-compose.yml, который поддерживает только Http.

 version: "3"

services:
  api:
    container_name: api
    build:
      context: ./api
      dockerfile: Dockerfile
    volumes:
      - /api/node_modules
      - ./api:/api
    ports:
      - "3000:3000"
    networks:
      - app
    restart: unless-stopped
  app:
    container_name: app
    build:
      context: ./app
      dockerfile: Dockerfile 
    ports:
      - "80:80"
    networks:
      - app
    restart: unless-stopped
  
networks:
  app:
 

—api/Dockerfile :: Я думаю, что в этом файле нет проблем.

—Файл приложения/докера :: Здесь я определил и использовал Nginx для связи между 2 контейнерами.

 # build environment
FROM node:latest as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package*.json /app/
RUN npm ci --silent
RUN npm install react-scripts@3.4.3 -g --silent
COPY . ./
RUN npm run build

# production environment
FROM nginx:stable-alpine
COPY --from=build /app/build /usr/share/nginx/html
# new
COPY compose/nginx/nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
 

— приложение/создать/nginx/nginx.conf

 server {

  listen 80;

  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }

  error_page   500 502 503 504  /50x.html;

  location = /50x.html {
    root   /usr/share/nginx/html;
  }

  location /api {
    proxy_pass http://localhost:3000; #http://localhost:5054;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
}
 

Until here, It is working fine with HTTP.

Next I want to make it support in HTTPS, so I did change in Docker-compose.yml, like this:

 version: "3"

volumes:
  production_traefik: {}

services:
  traefik:
    build:
      context: .
      dockerfile: ./compose/traefik/Dockerfile
    image: stats2win_traefik
    networks:
      - traefik-global-proxy
    volumes:
      - production_traefik:/etc/traefik/acme:z
    ports:
      - "80:80"
      - "443:443"
      - "3000:3000"
  api:
    container_name: api
    build:
      context: ./api
      dockerfile: Dockerfile
    volumes:
      - /api/node_modules
      - ./api:/api
    # ports:
    #   - "3000:3000"
    networks:
      - traefik-global-proxy
      - app
    restart: unless-stopped
    # Traefik stuff
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web-secure-router.rule=Host(`api.*mydomain*`)" # domain to expose on
      - "traefik.http.routers.web-secure-router.entrypoints=web-secure" # if you named your 443 entrypoint differently than webscure, substitute it here!
      - "traefik.http.routers.web-secure-router.tls.certresolver=letsencrypt" # if you named your cert resolver differently than letsencrypt, substitute it here!
      - "traefik.port=3000"
  app:
    container_name: app
    build:
      context: ./app
      dockerfile: Dockerfile 
    # volumes:
    #   - /app/node_modules
    #   - ./app:/app
    # environment:
    #   - CHOKIDAR_USEPOLLING=true
    # ports:
    #   - "80:80"
    networks:
      - traefik-global-proxy
    restart: unless-stopped
    # Traefik stuff
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web-secure-router.rule=Host(`test.*mydomain*`)" # domain to expose on
      - "traefik.http.routers.web-secure-router.entrypoints=web-secure" # if you named your 443 entrypoint differently than webscure, substitute it here!
      - "traefik.http.routers.web-secure-router.tls.certresolver=letsencrypt" # if you named your cert resolver differently than letsencrypt, substitute it here!
      - "traefik.port=80"
networks:
  app:
  traefik-global-proxy:
    external: true

 

—создать/traefik/Докерфайл

 FROM traefik:v2.2.11
RUN mkdir -p /etc/traefik/acme 
  amp;amp; touch /etc/traefik/acme/acme.json 
  amp;amp; chmod 600 /etc/traefik/acme/acme.json
COPY ./compose/traefik/traefik.yml /etc/traefik
 

—написать/traefik/traefik.yml

 log:
  level: INFO

entryPoints:
  web:
    # http
    address: ":80"
    http:
      # https://docs.traefik.io/routing/entrypoints/#entrypoint
      redirections:
        entryPoint:
          to: web-secure

  web-secure:
    # https
    address: ":443"

certificatesResolvers:
  letsencrypt:
    # https://docs.traefik.io/master/https/acme/#lets-encrypt
    acme:
      email: "*myEmail*"
      storage: /etc/traefik/acme/acme.json
      # https://docs.traefik.io/master/https/acme/#httpchallenge
      httpChallenge:
        entryPoint: web

http:
  routers:
    web-secure-router:
      rule: "Host(`test.*mydomain*`)"

      entryPoints:
        - web-secure
      service: nginx
      tls:
        # https://docs.traefik.io/master/routing/routers/#certresolver
        certResolver: letsencrypt

  services:
    nginx:
      loadBalancer:
        servers:
          - url: http://nginx

providers:
  # https://docs.traefik.io/master/providers/file/
  file:
    filename: /etc/traefik/traefik.yml
    watch: true
 

Затем я попробовал это на тестовом сервере, который находится в EC2,
Остро, когда я пытаюсь с http://mydomain, он превращается в https://mydomain. Но я получаю плохой ответ Шлюза.

Комментарии:

1. Есть ли у вас HTTPS-сервер, работающий в вашем приложении узла? Почему бы вам не завершить SSL/TLS на Traefik/nginx и не работать внутри только с http?

2. Спасибо за ответ. @Марк, не могли бы вы сказать мне более точно, пожалуйста?