Node.js + Nginx - Co teraz?

1003

Skonfigurowałem Node.js i Nginx na moim serwerze. Teraz chcę go użyć, ale zanim zacznę, są dwa pytania:

  1. Jak powinni współpracować? Jak mam obsługiwać wnioski?
  2. Istnieją dwa pojęcia dotyczące serwera Node.js, który jest lepszy:

    za. Utwórz osobny serwer HTTP dla każdej witryny, która tego potrzebuje. Następnie załaduj cały kod JavaScript na początku programu, aby kod był interpretowany raz.

    b. Utwórz jeden serwer Node.js, który obsługuje wszystkie żądania Node.js. Spowoduje to odczytanie wymaganych plików i sprawdzenie ich zawartości. Pliki są interpretowane przy każdym żądaniu, ale logika serwera jest znacznie prostsza.

Nie jest dla mnie jasne, jak prawidłowo używać Node.js.

Van Coding
źródło

Odpowiedzi:

1306

Nginx działa jako serwer front-end, który w tym przypadku zastępuje żądania do serwera node.js. Dlatego musisz skonfigurować plik konfiguracyjny nginx dla węzła.

Oto, co zrobiłem w moim polu Ubuntu:

Utwórz plik yourdomain.comw /etc/nginx/sites-available/:

vim /etc/nginx/sites-available/yourdomain.com

Powinieneś w nim mieć coś takiego:

# the IP(s) on which your node server is running. I chose port 3000.
upstream app_yourdomain {
    server 127.0.0.1:3000;
    keepalive 8;
}

# the nginx server instance
server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    access_log /var/log/nginx/yourdomain.com.log;

    # pass the request to the node.js server with the correct headers
    # and much more can be added, see nginx config options
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header Host $http_host;
      proxy_set_header X-NginX-Proxy true;

      proxy_pass http://app_yourdomain/;
      proxy_redirect off;
    }
 }

Jeśli chcesz, aby nginx (> = 1.3.13) obsługiwał również żądania websocket, dodaj następujące wiersze w location /sekcji:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Po skonfigurowaniu musisz włączyć witrynę zdefiniowaną w pliku konfiguracyjnym powyżej:

cd /etc/nginx/sites-enabled/ 
ln -s /etc/nginx/sites-available/yourdomain.com yourdomain.com

Utwórz aplikację serwera węzła pod /var/www/yourdomain/app.jsi uruchom jąlocalhost:3000

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

Test na błędy składniowe:

nginx -t

Uruchom ponownie nginx:

sudo /etc/init.d/nginx restart

Na koniec uruchom serwer węzła:

cd /var/www/yourdomain/ && node app.js

Teraz powinieneś zobaczyć „Hello World” na twojadomena.com

Ostatnia uwaga dotycząca uruchomienia serwera węzłów: powinieneś użyć jakiegoś systemu monitorowania demona węzła. Jest niesamowity samouczek na temat węzła z upstartem i monitorem .

Joao Da Silva
źródło
11
Dzięki za post, nginx zapisze w pamięci podręcznej odpowiedzi node.js dla powyższego serwera lub uruchom je ponownie za każdym razem.
Lime
79
Czy jest jakiś powód, dla którego po prostu nie możesz tego zrobić location / { proxy_pass http://127.0.0.1:3000; }? Dlaczego potrzebujesz całego upstreambitu konfiguracji?
Robin Winslow,
20
+1, bardzo prosta i prosta odpowiedź na często zadawane pytania; idealne dla osób, które chcą skonfigurować wirtualne hosty za pomocą węzła i nginx. Jedyne, co myślę, że przeoczyłeś, to jakościowa odpowiedź na pytanie, dlaczego nginx-in-front-of-node jest najlepszy do obsługi wielu vhostów (drugie pytanie pytającego).
Paul d'Aoust,
34
@Robin Winslow na wypadek, gdybyś chciał dodać więcej serwerów dla serwerów do równoważenia obciążenia.
Joao Da Silva,
76
Należy zauważyć, że ta (bardzo pomocna) odpowiedź odnosi się do jednego smaku nginx, który domyślnie zawiera sites-enabledi sites-availablekatalogi wewnątrz /etc/nginx. Jeśli twoja wersja przyszła bez tych dwóch katalogów, prawdopodobnie conf.dzamiast tego ma jeden katalog. W takim przypadku wykonanie tych instrukcji nie przyniesie żadnego efektu, chyba że zmodyfikujesz includeinstrukcję w pliku, nginx.confaby wskazywała sites-enabledzamiast domyślnej conf.d. Mam nadzieję, że to ma sens. Powinno to stać się oczywiste, gdy zobaczysz wspomniane includeoświadczenie w środku nginx.conf.
meetamit
167

Możesz także skonfigurować wiele domen za pomocą nginx, przekazując je do wielu procesów node.js.

Na przykład, aby to osiągnąć:

Porty te (4000 i 5000) powinny być używane do nasłuchiwania żądań aplikacji w kodzie aplikacji.

/ etc / nginx / sites-enabled / domain1

server {
    listen 80;
    listen [::]:80;
    server_name domain1.com;
    access_log /var/log/nginx/domain1.access.log;
    location / {
        proxy_pass    http://127.0.0.1:4000/;
    }
}

W / etc / nginx / sites-enabled / domain2

server {
    listen 80;
    listen [::]:80;
    server_name domain2.com;
    access_log /var/log/nginx/domain2.access.log;
    location / {
        proxy_pass    http://127.0.0.1:5000/;
    }
}
250R
źródło
5
Używam twojej metody proxy_pass, ale z jakiegoś powodu http://example.comautomatycznie dostaje się 302do http://www.example.com. Dlaczego?
Kristian
Czy masz Cloudflare lub coś podobnego? Powyższa konfiguracja w ogóle nie powinna przekierowywać.
ozzieisaacs
1
@Kristian Musisz dodać, proxy_set_header Host $hostaby uniknąć przekierowania HTTP 302.
Ivan Shatsky
@IvanShatsky - Czy możesz udzielić pomocy, jak skonfigurować wiele portów z wieloma subdomenami i zapobiec uruchamianiu innych portów w innej domenie? Nginx v
1.14.1
59

Możesz również mieć różne adresy URL dla aplikacji w konfiguracji jednego serwera:

W / etc / nginx / sites-enabled / yourdomain :

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com;

    location ^~ /app1/{
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass    http://127.0.0.1:3000/;
    }

    location ^~ /app2/{
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_set_header X-NginX-Proxy true;
        proxy_pass    http://127.0.0.1:4000/;
    }
}

Uruchom ponownie nginx:

sudo service nginx restart

Uruchamianie aplikacji.

węzeł app1.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app1!\n');
}).listen(3000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:3000/');

węzeł app2.js

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello from app2!\n');
}).listen(4000, "127.0.0.1");
console.log('Server running at http://127.0.0.1:4000/');
0x8BADF00D
źródło
3
Wersja społeczności Open Source jest darmowa, ale mają wersję z innymi funkcjami, które nie są darmowe. nginx.com/products/feature-matrix
0x8BADF00D
Przepraszam za moją ignorancję. Jaki jest cel i korzyści z serwowania go w ten sposób? masz jakiś przykład lub przypadek użycia? Z góry dziękuję.
Mauro Aguilar,
2
@MauroAguilar Jeśli potrzebujesz aplikacji 2 node.js na jednym serwerze, możesz obsługiwać ją w sugerowany sposób (używając różnych portów). W moich przypadkach były to dwie różne aplikacje testowe.
0x8BADF00D
Ok, ale jaka jest różnica między uruchomieniem 2 aplikacji i jednej? Mam na myśli, jakie byłyby korzyści, gdyby były przeznaczone do tego samego celu?
Mauro Aguilar,
2
@ MauroAguilar, możesz uruchomić je w jednym i nie ma żadnej korzyści, jeśli mógłby być częścią jednego projektu i miałby ten sam cel. Ale jeśli potrzebujesz uruchomić 2 różne projekty z różnymi celami i różnymi konfiguracjami na jednym serwerze, możesz skorzystać z tej konfiguracji.
0x8BADF00D
35

Niezależne od proxy aplikacje Node Express za pośrednictwem Nginx.

Dzięki temu nowe aplikacje mogą być łatwo montowane, a także mogę uruchamiać inne rzeczy na tym samym serwerze w różnych lokalizacjach.

Oto więcej szczegółów na temat mojej konfiguracji z przykładem konfiguracji Nginx:

Wdróż wiele aplikacji Node na jednym serwerze WWW w podfolderach za pomocą Nginx

W przypadku węzła sprawy stają się trudne, gdy trzeba przenieść aplikację z hosta lokalnego do Internetu.

Nie ma wspólnego podejścia do wdrażania węzła.

Google może znaleźć mnóstwo artykułów na ten temat, ale starałem się znaleźć odpowiednie rozwiązanie dla potrzebnej konfiguracji.

Zasadniczo mam serwer sieciowy i chcę, aby aplikacje węzłów były montowane w podfolderach (tj. Http: // myhost / demo / pet-project / ) bez wprowadzania zależności konfiguracji od kodu aplikacji.

Jednocześnie chcę, aby inne rzeczy, takie jak blog, działały na tym samym serwerze internetowym.

Brzmi prosto, prawda? Najwyraźniej nie.

W wielu przykładach w Internecie aplikacje węzłów albo działają na porcie 80, albo są pośredniczone przez Nginx w katalogu głównym.

Mimo że oba podejścia są właściwe dla niektórych przypadków użycia, nie spełniają moich prostych, ale nieco egzotycznych kryteriów.

Dlatego stworzyłem własną konfigurację Nginx i oto fragment:

upstream pet_project {
  server localhost:3000;
}

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

  location /demo/pet-project {
    alias /opt/demo/pet-project/public/;
    try_files $uri $uri/ @pet-project;
  }

  location @pet-project {
    rewrite /demo/pet-project(.*) $1 break;

    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $proxy_host;
    proxy_set_header X-NginX-Proxy true;

    proxy_pass http://pet_project;
    proxy_redirect http://pet_project/ /demo/pet-project/;
  }
}

Z tego przykładu można zauważyć, że podłączam moją aplikację Pet Project Node działającą na porcie 3000 do http: // myhost / demo / pet-project .

Najpierw Nginx sprawdza, czy żądany zasób jest plikiem statycznym dostępnym w / opt / demo / pet-project / public /, a jeśli tak, to obsługuje go, ponieważ jest bardzo wydajny, więc nie musimy mieć zbędnej warstwy, takiej jak Connect statyczne oprogramowanie pośrednie.

Następnie wszystkie pozostałe żądania są nadpisywane i zastępowane aplikacją Pet Project Node , więc aplikacja Node nie musi wiedzieć, gdzie jest faktycznie zamontowana, a zatem może zostać przeniesiona w dowolne miejsce poprzez konfigurację.

proxy_redirect jest konieczny do prawidłowego obsługi nagłówka Location. Jest to niezwykle ważne, jeśli używasz res.redirect () w aplikacji Node.

Możesz łatwo powielić tę konfigurację dla wielu aplikacji Węzłów działających na różnych portach i dodać więcej programów do obsługi lokalizacji do innych celów.

Od: http://skovalyov.blogspot.dk/2012/07/deploy-multiple-node-applications-on.html

skovalyov
źródło
1
Dlaczego i jak powinieneś to zrobić w subdomenach: skovalyov.blogspot.dk/2012/10/…
skovalyov
Link tylko odpowiedź… czy możesz streścić odpowiednie części w odpowiedzi na wypadek, gdyby Twój blog zniknął?
kaiser
11

Node.js z konfiguracją Nginx.

$ sudo nano /etc/nginx/sites-available/subdomain.your_domain.com

dodaj następującą konfigurację, aby Nginx działał jako proxy przekierowujący na ruch portu 3000 z serwera, gdy pochodzimy z „subdomena.twoja_domena.com”

upstream subdomain.your_domain.com {
  server 127.0.0.1:3000;
}
server {
  listen 80;
  listen [::]:80;
  server_name subdomain.your_domain.com;
  access_log /var/log/nginx/subdomain.your_domain.access.log;
  error_log /var/log/nginx/subdomain.your_domain.error.log debug;
  location / {
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarder-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_set_header X-NginX-Proxy true;
    proxy_pass http://subdomain.your_domain.com;
    proxy_redirect off;
  }
}
aquadir
źródło
9

odpowiadając na twoje pytanie 2:

Użyłbym opcji bpo prostu dlatego, że zużywa ona znacznie mniej zasobów. z opcją „a”, każdy klient powoduje, że serwer zużywa dużo pamięci, ładując wszystkie potrzebne pliki (nawet jeśli lubię php, jest to jeden z problemów). Dzięki opcji „b” możesz załadować swoje biblioteki (kod wielokrotnego użytku) i udostępnić je wszystkim żądaniom klientów.

Ale pamiętaj, że jeśli masz wiele rdzeni, powinieneś dostosować plik node.js, aby korzystać z nich wszystkich.

Hugo Mota
źródło
2
Postępuj zgodnie z tą radą, jeśli zasoby są Twoim najważniejszym problemem (mało prawdopodobne). Istnieją różne kompromisy między (a) i (b). Opcja (a) jest prawdopodobnie lepsza, jeśli chcesz, aby strony były bardziej niezależne, np. Restart lub konserwacja strony, połączenia db, baza kodu, zależności bibliotek, przenoszenie stron między serwerami itp.
robocat
8

Zrobiłem repozytorium w Github, które można sklonować, vagrant-node-nginx -ilerplate

w zasadzie aplikacja node.js /var/www/nodeappto

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(4570, '127.0.0.1');

console.log('Node Server running at 127.0.0.1:4570/');

a konfiguracja nginx /etc/nginx/sites-available/to

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

        root /var/www/nodeapp;
        index index.html index.htm;

        server_name localhost;

        location / {
          proxy_pass http://127.0.0.1:4570;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection 'upgrade';
          proxy_set_header Host $host;
          proxy_cache_bypass $http_upgrade;
        }
}
svnm
źródło
5

Możesz także użyć node.js do wygenerowania plików statycznych do katalogu obsługiwanego przez nginx. Oczywiście niektóre dynamiczne części witryny mogą być obsługiwane przez węzeł, a niektóre przez nginx (statyczny).

Posiadanie niektórych z nich przez Nginx zwiększa wydajność.

Matej
źródło
5

Możemy łatwo skonfigurować aplikację Nodejs firmy Nginx działającą jako odwrotne proxy.
Poniższa konfiguracja zakłada, że ​​aplikacja NodeJS działa na 127.0.0.1:8080,

  server{
     server_name domain.com sub.domain.com; # multiple domains

     location /{ 
      proxy_pass http://127.0.0.1:8080;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }

     location /static/{
       alias /absolute/path/to/static/files; # nginx will handle js/css
     }
   } 

w powyższej konfiguracji Twoja aplikacja Nodejs,

  • pobierz HTTP_HOSTnagłówek, w którym możesz zastosować logikę specyficzną dla domeny, aby obsłużyć odpowiedź. „
  • Twoja aplikacja musi być zarządzana przez kierownika procesu, takiego jak pm2 lub przełożonego, w celu obsługi sytuacji / ponownego wykorzystywania gniazd lub zasobów itp.

  • Skonfiguruj usługę raportowania błędów w celu uzyskania błędów produkcyjnych, takich jak wartownik lub pasek przewijania

UWAGA: możesz skonfigurować logikę do obsługi tras żądań specyficznych dla domeny, utworzyć oprogramowanie pośrednie dla aplikacji expressjs

Renjith Thankachan
źródło
1
Innym powodem używania pm2 jest to, że możesz uruchomić aplikację „na zawsze” po wyjściu z powłoki i automatycznie uruchomić ją, jeśli kiedykolwiek będziesz musiał zrestartować serwer, patrz: pm2.keymetrics.io/docs/usage/startup
SeanQuinn781
3

Nginx może działać jako odwrotny serwer proxy, który działa podobnie jak kierownik projektu. Gdy otrzyma żądanie, analizuje je i przekazuje żądanie do wyższego szczebla (członkowie projektu) lub sam się obsługuje. Nginx ma dwa sposoby obsługi żądania w zależności od jego konfiguracji.

  • obsłużyć prośbę
  • przekaż żądanie do innego serwera

    server{
     server_name mydomain.com sub.mydomain.com;
    
     location /{ 
      proxy_pass http://127.0.0.1:8000;  
      proxy_set_header Host $host;
      proxy_pass_request_headers on;  
     }
    
     location /static/{
       alias /my/static/files/path;
     }

    }

Serwer żądania

W tej konfiguracji, gdy adres URL żądania mydomain.com/static/myjs.jszwraca myjs.jsplik w /my/static/files/pathfolderze. Gdy skonfigurujesz nginx do obsługi plików statycznych, sam obsługuje żądanie.

przekaż żądanie do innego serwera

Gdy adres URL żądania to mydomain.com/dothisnginx, przekaże żądanie na adres http://127.0.0.1:8000 . Usługa działająca na porcie localhost 8000 otrzyma żądanie i zwróci odpowiedź do nginx, a nginx zwróci odpowiedź do klienta.

Po uruchomieniu serwera node.js na porcie 8000 nginx przekaże żądanie do node.js. Napisz logikę node.js i obsłuż żądanie. To tyle, że serwer Nodejs działa za serwerem Nginx.

Jeśli chcesz uruchomić inne usługi niż nodejs, po prostu uruchom inną usługę, taką jak Django, flask, php na różnych portach i skonfiguruj ją w nginx.

Vkreddy Komatireddy
źródło
1

Możesz uruchomić nodejs za pomocą pm2, jeśli chcesz zarządzać każdym środkiem mikrousług i go uruchomić. Węzeł będzie działał w porcie po prostu skonfiguruj ten port w nginx (/etc/nginx/sites-enabled/domain.com)

server{
    listen 80;
    server_name domain.com www.domain.com;

  location / {
     return 403;
  }
    location /url {
        proxy_pass http://localhost:51967/info;
    }
}

Sprawdź, czy host lokalny działa, czy nie, używając polecenia ping.

I

Create one single Node.js server which handles all Node.js requests. This reads the requested files and evals their contents. So the files are interpreted on each request, but the server logic is much simpler.

To jest najlepsze i tak jak powiedziałeś łatwiej

gokul kandasamy
źródło
1

Najlepszą i prostszą konfiguracją w Nginx i Nodejs jest użycie Nginx jako modułu równoważenia obciążenia HTTP i TCP z włączonym protokołem proxy_protocol. W tym kontekście Nginx będzie mógł proxy przychodzących żądań do nodejs, a także zakończyć połączenia SSL z serwerami serwerowymi Nginx, a nie z samym serwerem proxy. (SSL-PassThrough)

Moim zdaniem nie ma sensu podawać przykładów innych niż SSL, ponieważ wszystkie aplikacje internetowe (lub powinny) korzystać z bezpiecznych środowisk.

Przykładowa konfiguracja serwera proxy w /etc/nginx/nginx.conf

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
events {
    worker_connections  1024;
}
http {
  upstream webserver-http {
    server 192.168.1.4; #use a host port instead if using docker
    server 192.168.1.5; #use a host port instead if using docker
  }
  upstream nodejs-http {
    server 192.168.1.4:8080; #nodejs listening port
    server 192.168.1.5:8080; #nodejs listening port
  }
  server {
    server_name example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Connection "";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://webserver-http$request_uri;
    }
  }
  server {
    server_name node.example.com;
    location / {
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header Host $http_host;
      proxy_set_header X-Forwarded-Host $server_name;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      add_header       X-Upstream $upstream_addr;
      proxy_redirect     off;
      proxy_connect_timeout  300;
      proxy_http_version 1.1;
      proxy_buffers 16 16k;
      proxy_buffer_size 16k;
      proxy_cache_background_update on;
      proxy_pass http://nodejs-http$request_uri;
    }
  }
}
stream {
  upstream webserver-https {
    server 192.168.1.4:443; #use a host port instead if using docker
    server 192.168.1.5:443; #use a host port instead if using docker
  }

  server {
    proxy_protocol on;
    tcp_nodelay on;
    listen 443;
    proxy_pass webserver-https;
  }
  log_format proxy 'Protocol: $protocol - $status $bytes_sent $bytes_received $session_time';
  access_log  /var/log/nginx/access.log proxy;
  error_log /var/log/nginx/error.log debug;
}

Teraz zajmiemy się serwerem zaplecza. /etc/nginx/nginx.conf :

user  nginx;
worker_processes  1;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;
load_module /etc/nginx/modules/ngx_http_geoip2_module.so; # GeoIP2
events {
    worker_connections  1024;
}
http {
    variables_hash_bucket_size 64;
    variables_hash_max_size 2048;
    server_tokens off;
    sendfile    on;
    tcp_nopush  on;
    tcp_nodelay on;
    autoindex off;
    keepalive_timeout  30;
    types_hash_bucket_size 256;
    client_max_body_size 100m;
    server_names_hash_bucket_size 256;
    include         mime.types;
    default_type    application/octet-stream;
    index  index.php index.html index.htm;
    # GeoIP2
    log_format  main    'Proxy Protocol Address: [$proxy_protocol_addr] '
                        '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';

    # GeoIP2
    log_format  main_geo    'Original Client Address: [$realip_remote_addr]- Proxy Protocol Address: [$proxy_protocol_addr] '
                            'Proxy Protocol Server Address:$proxy_protocol_server_addr - '
                            '"$request" $remote_addr - $remote_user [$time_local] "$request" '
                            '$status $body_bytes_sent "$http_referer" '
                            '$geoip2_data_country_iso $geoip2_data_country_name';

    access_log  /var/log/nginx/access.log  main_geo; # GeoIP2
#===================== GEOIP2 =====================#
    geoip2 /usr/share/geoip/GeoLite2-Country.mmdb {
        $geoip2_metadata_country_build  metadata build_epoch;
        $geoip2_data_country_geonameid  country geoname_id;
        $geoip2_data_country_iso        country iso_code;
        $geoip2_data_country_name       country names en;
        $geoip2_data_country_is_eu      country is_in_european_union;
    }
    #geoip2 /usr/share/geoip/GeoLite2-City.mmdb {
    #   $geoip2_data_city_name city names en;
    #   $geoip2_data_city_geonameid city geoname_id;
    #   $geoip2_data_continent_code continent code;
    #   $geoip2_data_continent_geonameid continent geoname_id;
    #   $geoip2_data_continent_name continent names en;
    #   $geoip2_data_location_accuracyradius location accuracy_radius;
    #   $geoip2_data_location_latitude location latitude;
    #   $geoip2_data_location_longitude location longitude;
    #   $geoip2_data_location_metrocode location metro_code;
    #   $geoip2_data_location_timezone location time_zone;
    #   $geoip2_data_postal_code postal code;
    #   $geoip2_data_rcountry_geonameid registered_country geoname_id;
    #   $geoip2_data_rcountry_iso registered_country iso_code;
    #   $geoip2_data_rcountry_name registered_country names en;
    #   $geoip2_data_rcountry_is_eu registered_country is_in_european_union;
    #   $geoip2_data_region_geonameid subdivisions 0 geoname_id;
    #   $geoip2_data_region_iso subdivisions 0 iso_code;
    #   $geoip2_data_region_name subdivisions 0 names en;
   #}

#=================Basic Compression=================#
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_buffers 16 8k;
    gzip_http_version 1.1;
    gzip_types text/css text/xml text/plain application/javascript image/jpeg image/png image/gif image/x-icon image/svg+xml image/webp application/font-woff application/json application/vnd.ms-fontobject application/vnd.ms-powerpoint;
    gzip_static on;

    include /etc/nginx/sites-enabled/example.com-https.conf;
}

Teraz skonfigurujmy wirtualnego hosta za pomocą tej konfiguracji SSL i proxy_protocol na /etc/nginx/sites-available/example.com-https.conf :

server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name 192.168.1.4; #Your current server ip address. It will redirect to the domain name.
    listen 80;
    listen 443 ssl http2;
    listen [::]:80;
    listen [::]:443 ssl http2;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name  example.com;
    listen       *:80;
    return 301   https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name www.example.com;
    listen 80;
    listen 443 http2;
    listen [::]:80;
    listen [::]:443 ssl http2 ;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    return 301 https://example.com$request_uri;
}
server {
    real_ip_header proxy_protocol;
    set_real_ip_from 192.168.1.1; #proxy server ip address
    #set_real_ip_from proxy; #proxy container hostname if you are using docker
    server_name example.com;
    listen 443 proxy_protocol ssl http2;
    listen [::]:443 proxy_protocol ssl http2;
    root /var/www/html;
    charset UTF-8;
    add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains; preload';
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy no-referrer;
    ssl_prefer_server_ciphers on;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
    ssl_session_cache   shared:SSL:10m;
    ssl_session_timeout 10m;
    keepalive_timeout   70;
    ssl_buffer_size 1400;
    ssl_dhparam /etc/nginx/ssl/dhparam.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=86400;
    resolver_timeout 10;
    ssl_certificate     /etc/nginx/certs/example.com.crt;
    ssl_certificate_key /etc/nginx/certs/example.com.key;
    ssl_trusted_certificate /etc/nginx/certs/example.com.crt;
location ~* \.(jpg|jpe?g|gif|png|ico|cur|gz|svgz|mp4|ogg|ogv|webm|htc|css|js|otf|eot|svg|ttf|woff|woff2)(\?ver=[0-9.]+)?$ {
    expires modified 1M;
    add_header Access-Control-Allow-Origin '*';
    add_header Pragma public;
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";
    access_log off;
    }
    location ~ /.well-known { #For issuing LetsEncrypt Certificates
        allow all;
    }
location / {
    index index.php;
    try_files $uri $uri/ /index.php?$args;
    }
error_page  404    /404.php;

location ~ \.php$ {
    try_files       $uri =404;
    fastcgi_index   index.php;
    fastcgi_pass    unix:/tmp/php7-fpm.sock;
    #fastcgi_pass    php-container-hostname:9000; (if using docker)
    fastcgi_pass_request_headers on;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_param   SCRIPT_FILENAME  $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_ignore_client_abort off;
    fastcgi_connect_timeout 60;
    fastcgi_send_timeout 180;
    fastcgi_read_timeout 180;
    fastcgi_request_buffering on;
    fastcgi_buffer_size 128k;
    fastcgi_buffers 4 256k;
    fastcgi_busy_buffers_size 256k;
    fastcgi_temp_file_write_size 256k;
    include fastcgi_params;
}
location = /robots.txt {
    access_log off;
    log_not_found off;
    }
location ~ /\. {
    deny  all;
    access_log off;
    log_not_found off;
    }
}

I na koniec przykład 2 serwerów nodejs : Pierwszy serwer:

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello From Nodejs\n');
}).listen(8080, "192.168.1.4");
console.log('Server running at http://192.168.1.4:8080/');

Drugi serwer:

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello From Nodejs\n');
}).listen(8080, "192.168.1.5");
console.log('Server running at http://192.168.1.5:8080/');

Teraz wszystko powinno działać idealnie i być zrównoważone.

Jakiś czas temu napisałem o tym, jak skonfigurować Nginx jako moduł równoważenia obciążenia TCP w Docker . Sprawdź, czy korzystasz z Dockera.

Sceptyk
źródło