-
-
Save designervoid/424f6e1c14a982d210d39422e966f23c to your computer and use it in GitHub Desktop.
# my_frontend/docker-compose.yml | |
version: '3.7' | |
services: | |
my_frontend: | |
container_name: my_frontend | |
networks: | |
- my_network | |
restart: unless-stopped | |
security_opt: | |
- no-new-privileges:true | |
build: . | |
env_file: | |
- .env | |
labels: | |
- "traefik.enable=true" | |
- "traefik.http.routers.frontend.entrypoints=https" | |
- "traefik.http.routers.frontend.rule=Host(`domain.com`) && (PathPrefix(`/frontend`) || PathPrefix(`/_nuxt`))" | |
- "traefik.http.routers.frontend.tls.certresolver=letsEncrypt" | |
- "traefik.http.services.frontend.loadbalancer.server.port=8090" | |
networks: | |
my_network: | |
external: true | |
name: "my_network" |
# reverse-proxy/docker-compose.yml | |
version: '3.7' | |
services: | |
traefik: | |
image: traefik:v2.2 | |
container_name: traefik | |
command: | |
- "--log.level=DEBUG" | |
networks: | |
- my_network | |
restart: unless-stopped | |
security_opt: | |
- no-new-privileges:true | |
ports: | |
- 80:80 | |
- 443:443 | |
- 8090:8090 | |
volumes: | |
- /etc/localtime:/etc/localtime:ro | |
- /var/run/docker.sock:/var/run/docker.sock:ro | |
- ./data/traefik.yml:/traefik.yml:ro | |
- ./data/custom/:/custom/:ro | |
- ./data/acme.json:/acme.json | |
labels: | |
- "traefik.enable=true" | |
- "traefik.http.routers.traefik.entrypoints=https" | |
- "traefik.http.routers.traefik.rule=Host(`domain.com`)" | |
- "traefik.http.routers.traefik.tls=true" | |
- "traefik.http.routers.traefik.tls.certresolver=letsEncrypt" | |
- "traefik.http.routers.traefik.service=api@internal" | |
- "traefik.http.services.traefik.loadbalancer.server.port=888" | |
# Auth Middleware | |
- "traefik.http.middlewares.traefik-auth.basicauth.users=your_username_here:your_password_here" | |
- "traefik.http.routers.traefik.middlewares=traefik-auth" | |
networks: | |
my_network: | |
external: true | |
name: "my_network" |
# my_frontend/Dockerfile | |
### STAGE 1: Build ### | |
FROM node:latest as build | |
RUN mkdir /usr/src/app | |
WORKDIR /usr/src/app | |
ENV PATH /usr/src/app/node_modules/.bin:$PATH | |
COPY package.json /usr/src/app/package.json | |
RUN npm install --silent | |
COPY . /usr/src/app | |
RUN npm run generate | |
### STAGE 2: NGINX ### | |
FROM nginx:stable-alpine | |
COPY --from=build /usr/src/app/docker /usr/share/nginx/html/ | |
RUN rm /etc/nginx/conf.d/* | |
COPY nginx/main.conf /etc/nginx/conf.d/ | |
EXPOSE 8090 | |
CMD ["nginx", "-g", "daemon off;"] |
# reverse-proxy/data/custom/host.yml | |
http: | |
routers: | |
host: | |
entryPoints: | |
- https | |
service: service-host | |
rule: Host(`domain.com`) | |
tls: | |
certResolver: letsEncrypt | |
services: | |
service-host: | |
loadBalancer: | |
servers: | |
- url: "http://127.0.0.1:8080" | |
passHostHeader: true |
# my_frontend/nginx/main.conf | |
map $sent_http_content_type $expires { | |
"text/html" epoch; | |
"text/html; charset=utf-8" epoch; | |
default off; | |
} | |
server { | |
listen 8090; | |
server_name localhost; | |
charset utf-8; | |
client_max_body_size 10M; | |
gzip on; | |
gzip_types text/plain application/xml text/css application/javascript; | |
gzip_min_length 1000; | |
#charset koi8-r; | |
# access_log logs/host.access.log main; | |
location / { | |
absolute_redirect off; | |
root /usr/share/nginx/html/dist; | |
try_files $uri $uri/ /index.html; | |
} | |
} |
# reverse-proxy/data/traefik.yml | |
api: | |
dashboard: true | |
entryPoints: | |
http: | |
address: ":80" | |
https: | |
address: ":443" | |
http: | |
routers: | |
http-catchall: | |
rule: hostregexp(`{any:.+}`) | |
entrypoints: | |
- http | |
middlewares: | |
- redirect-to-https | |
middlewares: | |
redirect-to-https: | |
redirectScheme: | |
scheme: https | |
permanent: true | |
port: "443" | |
providers: | |
docker: | |
endpoint: "unix:///var/run/docker.sock" | |
exposedByDefault: false | |
file: | |
directory: /custom | |
watch: true | |
certificatesResolvers: | |
letsEncrypt: | |
acme: | |
email: [email protected] | |
storage: acme.json | |
#caServer: "https://acme-staging-v02.api.letsencrypt.org/directory" | |
httpChallenge: | |
entryPoint: http |
Как работает один узел приложения
Для корректной работы требуется установить Docker
, Docker Compose
, а также выставить права файлу /data/acme.json
:
$ chmod 600 /data/acme.json
Затем надо создать Docker Network
:
$ docker network create main_network
На эту схему требуется смотреть справа налево. Входной точкой в приложение является HTTP:80 или HTTPS:443, в зависимости от того, какой протокол явно выбрал клиент
http://domain.com или https://domain.com при вводе домена в адресную строку. Если клиент подключается через незащищённое
http соединение (80 порт), мы проксируем его на защищённое
https соединение (443 порт). При неявном выборе протокола domain.com - клиента проксирует на защищённое соединение. Чтобы сервисы тоже общались между собой через https - необходимо добавить несколько полей метаданных в конфигурационный файл Docker. Метаданные записываются в поле labels, конфигурационного файла docker-compose-frontend.yml. Все сервисы Docker Compose связаны между собой единой Docker Network, external означает то, что сеть внешняя. Перед запуском приложения её необходимо создать вручную (один раз), дальше он всегда будет присоединяться к этой сети:
Архитектура построена на основе статьи - https://habr.com/ru/post/508636/
Все приложение базируется на Traefik Reverse Proxy. В данном приложении - это единственный прокси-сервис, который смотрит в глобальную сеть.

В приложении используются сервисы Traefik и Frontend.