#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. Спасибо за ответ. @Марк, не могли бы вы сказать мне более точно, пожалуйста?