Как развернуть приложение Angular 18 SSR с помощью Docker, docker-compose и NGINX?

Я обновил свое приложение до Angular 18 и хочу использовать технологию SSR, чтобы повысить производительность и SEO. Без SSR у меня не было проблем с развертыванием и запуском моего приложения в производство, но теперь я не знаю, как это сделать.

Это мой файл docker-compose.yml

version: "3.9"
services:
    myapod-be:
        image: myapod-be
        container_name: myapod-be
        build:
            context: ./my-apod-be
        ports:
            - "9000:80"
    myapod-fe:
        image: myapod-fe
        container_name: myapod-fe
        build:
            context: ./myapod-fe
        ports:
            - "80:80"
            - "443:443"
        depends_on:
            - myapod-be
    myapod-text-translator:
        image: myapod-text-translator
        container_name: myapod-text-translator
        build:
            context: ./myapod-text-translator
        ports:
            - "8081:8081"

Это мой Dockerfile для внешнего интерфейса

FROM nginx:alpine

COPY /dist/* /usr/share/nginx/html/
COPY /nginx/security-headers.conf /etc/nginx/conf.d/security-headers.conf
COPY /nginx/certificates/myapod.com/myapod.key /etc/nginx/conf.d/certificates/myapod.key
COPY /nginx/certificates/myapod.com/ssl-bundle.crt /etc/nginx/conf.d/certificates/ssl-bundle.crt
COPY /nginx/nginx.conf /etc/nginx/conf.d/default.conf

И это мой файл nginx.conf

upstream docker-be {
    server myapod-be:80 max_conns=200;
}

server {
    listen 80;
    server_name myapod.com;
    return 301 https://$server_name$request_uri;
}

server {
   include /etc/nginx/extra-conf.d/*.conf;
   
   listen       443 ssl;
   server_name myapod-fe;
   
   ssl_certificate           /etc/nginx/conf.d/certificates/ssl-bundle.crt;
   ssl_certificate_key       /etc/nginx/conf.d/certificates/myapod.key;

   #ssl on;
   ssl_session_cache  builtin:1000  shared:SSL:10m;
   ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
   ssl_prefer_server_ciphers on;
   
   server_tokens off;
   
   charset UTF-8;
   
   #GZIP
   gzip on;
   gzip_disable "MSIE [1-6]\\.(?!.*SV1)";
   gzip_proxied any;
   gzip_comp_level 5;
   gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/x-icon image/bmp image/svg+xml;
   gzip_vary on;
   gzip_min_length 256;
   
   # Logging Settings
   access_log /var/log/nginx/access.log;
   error_log /var/log/nginx/error.log;
   
   reset_timedout_connection on;
   client_body_timeout 5s;
   client_header_timeout 5s;
   
   client_body_buffer_size 20K;
   client_header_buffer_size 2k;
   client_max_body_size 20k;
   large_client_header_buffers 3 1k;
   
   keepalive_timeout 15;
   send_timeout 10;
  
   #Request mapping
   location / {
       root /usr/share/nginx/html;
       index index.html index.htm;
       try_files $uri $uri/ /index.html =404;
       add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
       include /etc/nginx/conf.d/security-headers.conf;
   }
   
   location /myapod-be/ {
       proxy_pass http://docker-be;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
   }
}

Я не публиковал другие файлы проекта, потому что у меня проблемы только с пакетом FE. Подскажите, пожалуйста, что мне делать?

Я пытался изменить файл Docker и содержимое nginx.conf, но не помогло.

Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Angular и React для вашего проекта веб-разработки?
Angular и React для вашего проекта веб-разработки?
Когда дело доходит до веб-разработки, выбор правильного front-end фреймворка имеет решающее значение. Angular и React - два самых популярных...
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Эпизод 23/17: Twitter Space о будущем Angular, Tiny Conf
Мы провели Twitter Space, обсудив несколько проблем, связанных с последними дополнениями в Angular. Также прошла Angular Tiny Conf с 25 докладами.
Угловой продивер
Угловой продивер
Оригинал этой статьи на турецком языке. ChatGPT используется только для перевода на английский язык.
Мое недавнее углубление в Angular
Мое недавнее углубление в Angular
Недавно я провел некоторое время, изучая фреймворк Angular, и я хотел поделиться своим опытом со всеми вами. Как человек, который любит глубоко...
Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
0
0
51
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Docker-файл внешнего интерфейса:

# Use Node.js for building the Angular SSR app
FROM node:18 as builder

# Set the working directory
WORKDIR /app

# Copy package.json and install dependencies
COPY package*.json ./
RUN npm install

# Copy all files and build the Angular SSR app
COPY . .
RUN npm run build:ssr

# Use a minimal Node.js image to run the SSR server
FROM node:18-alpine as server

# Set the working directory
WORKDIR /app

# Copy the built app from the builder stage
COPY --from=builder /app/dist /app/dist

# Install serve to serve the SSR app
RUN npm install -g serve

# Expose the SSR server port
EXPOSE 4000

# Command to run the SSR server
CMD ["npm", "run", "serve:ssr"]

docker-compose.yml

services:
    myapod-be:
        image: myapod-be
        container_name: myapod-be
        build:
            context: ./my-apod-be
        ports:
            - "9000:80"
    myapod-fe:
        image: myapod-fe
        container_name: myapod-fe
        build:
            context: ./myapod-fe
        ports:
            - "4000:4000"
        depends_on:
            - myapod-be
    myapod-text-translator:
        image: myapod-text-translator
        container_name: myapod-text-translator
        build:
            context: ./myapod-text-translator
        ports:
            - "8081:8081"

nginx.conf

upstream ssr {
    server myapod-fe:4000;
}

upstream docker-be {
    server myapod-be:80 max_conns=200;
}

server {
    listen 80;
    server_name myapod.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name myapod.com;
    
    ssl_certificate           /etc/nginx/conf.d/certificates/ssl-bundle.crt;
    ssl_certificate_key       /etc/nginx/conf.d/certificates/myapod.key;
    
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
    ssl_prefer_server_ciphers on;
    
    charset UTF-8;
    
    gzip on;
    gzip_disable "MSIE [1-6]\\.(?!.*SV1)";
    gzip_proxied any;
    gzip_comp_level 5;
    gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/x-icon image/bmp image/svg+xml;
    gzip_vary on;
    gzip_min_length 256;
    
    access_log /var/log/nginx/access.log;
    error_log /var/log/nginx/error.log;

    reset_timedout_connection on;
    client_body_timeout 5s;
    client_header_timeout 5s;

    client_body_buffer_size 20K;
    client_header_buffer_size 2k;
    client_max_body_size 20k;
    large_client_header_buffers 3 1k;

    keepalive_timeout 15;
    send_timeout 10;
    
    # Proxy requests to the SSR server
    location / {
        proxy_pass http://ssr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
    }

    location /myapod-be/ {
       proxy_pass http://myapod-be; #edited
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
   }
}

Привет, спасибо за ваш ответ, но для маршрутизации запроса к моим службам BE?

Mario Proietti 25.08.2024 17:25
proxy_pass http://ssr; это ваш серверный сервис?? я так не думаю. разве ваша серверная служба не в location /myapod-be/ ?? проложен по пути? Я не включил это, позвольте мне отредактировать для вас.
nabin sademba 25.08.2024 17:54

@MarioProietti, я отредактировал для вас блок местоположения в nginx, я думал, вы об этом знаете. но теперь он отредактирован, вы можете попробовать.

nabin sademba 25.08.2024 18:00

эй @MarioProietti, где ты nginx бежишь, это в контейнере в той же сети докеров или на твоем хост-компьютере??

nabin sademba 25.08.2024 18:16

Он находится в контейнере в той же сети докеров.

Mario Proietti 25.08.2024 19:46

я модифицировал nginx, можешь попробовать @MarioProietti

nabin sademba 25.08.2024 20:01

Привет @nabin sademba, благодаря тебе я смог реализовать технологию Angular SSR на своем сайте!!

Mario Proietti 27.08.2024 00:08

В локации /myapod-be/ мне пришлось изменить «proxy_pass» на myapod-be;

Mario Proietti 27.08.2024 00:18

да, верно @MarioProietti, я допустил опечатку, извини, рад, что ты смог ее решить, я отредактировал опечатку

nabin sademba 27.08.2024 03:19

Я отвечаю на свой собственный ответ, чтобы показать, как я решил. Я получил решение благодаря @nabin sademba, мне нужно было просто изменить файл docker-compose.yml, вот его содержимое.

version: "3.9"
services:
    myapod-be:
        image: myapod-be
        container_name: myapod-be
        build:
            context: ./my-apod-be
        ports:
            - "9000:80"
    myapod-fe:
        image: myapod-fe
        container_name: myapod-fe
        build:
            context: ./myapod-fe
        ports:
            - "4000:4000"
    myapod-text-translator:
        image: myapod-text-translator
        container_name: myapod-text-translator
        build:
            context: ./myapod-text-translator
        ports:
            - "8081:8081"
    nginx:
        restart: always
        image: nginx:alpine
        ports:
          - "80:80"
          - "443:443"
        volumes:
          - ./nginx/security-headers.conf/:/etc/nginx/conf.d/security-headers.conf
          - ./nginx/certificates/myapod.key/:/etc/nginx/conf.d/certificates/myapod.key
          - ./nginx/certificates/ssl-bundle.crt/:/etc/nginx/conf.d/certificates/ssl-bundle.crt
          - ./nginx/nginx.conf/:/etc/nginx/conf.d/default.conf

Кроме того, небольшое изменение в моем файле nginx.conf:

upstream ssr {
    server myapod-fe:4000;
}

server {
    listen 80;
    server_name myapod.com;
    return 301 https://$server_name$request_uri;
}

server {
   include /etc/nginx/extra-conf.d/*.conf;
   
   listen       443 ssl;
   server_name myapod-fe;
   
   ssl_certificate           /etc/nginx/conf.d/certificates/ssl-bundle.crt;
   ssl_certificate_key       /etc/nginx/conf.d/certificates/myapod.key;

   #ssl on;
   ssl_session_cache  builtin:1000  shared:SSL:10m;
   ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
   ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
   ssl_prefer_server_ciphers on;
   
   server_tokens off;
   
   charset UTF-8;
   
   #GZIP
   gzip on;
   gzip_disable "MSIE [1-6]\\.(?!.*SV1)";
   gzip_proxied any;
   gzip_comp_level 5;
   gzip_types text/plain text/css application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/x-icon image/bmp image/svg+xml;
   gzip_vary on;
   gzip_min_length 256;
   
   # Logging Settings
   access_log /var/log/nginx/access.log;
   error_log /var/log/nginx/error.log;
   
   reset_timedout_connection on;
   client_body_timeout 5s;
   client_header_timeout 5s;
   
   client_body_buffer_size 20K;
   client_header_buffer_size 2k;
   client_max_body_size 20k;
   large_client_header_buffers 3 1k;
   
   keepalive_timeout 15;
   send_timeout 10;
  
   #Request mapping
   location / {
        proxy_pass http://ssr/;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_cache_bypass $http_upgrade;
   }

   location /myapod-be/ {
       proxy_pass http://myapod-be;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
   }
}

Почему вы не видите мои работы на myapod.com :)?

Другие вопросы по теме