Перейти к содержимому

Использование nginx вместе с Node.js

19/01/2010

У Node.js есть один серьёзный недостаток — ей неудобно отдавать файлы. А без этой функции делать полноценный веб-сервис не очень то удобно. И если отдавать текстовые файлы вроде HTML/JavaScript/CSS ещё можно как то приспособиться, то с двоичными всё сложнее. Поэтому будем ставить nginx в пару к node.

Nginx — очень быстрый веб-сервер, основанный как и node.js на event loop. У нас он будет выполнять почти ту же роль, что и Apache для PHP-сайтов: статические файлы отдавать самостоятельно, динамический контент передавать из node. Для этого нам сначала надо продумать структуру директорий.

Чтобы сильно не заморачиваться, в своей инсталляции я всё устроил довольно просто. Всё что находится в /files/, отдаётся из определённой папки напрямую nginx’ом, остальное обрабатывает Node. Таким образом, если мы вызываем /files/css/style.css, этот запрос в Ноду вообще не попадёт: nginx отдаст файл самостоятельно. Но запрос /page/hello-world уже будет передан Node.

Итак, сначала ставим nginx. Если Вы используете виртуальную машину с Debian из прошлой статьи, то установка предельно проста:

apt-get install nginx

В других дистрибутивах всё может быть сложнее. Всё, nginx установлен. Теперь идём в /etc/nginx, и редактируем файл nginx.conf. Можно использовать vim, можно передать файл на основной компьютер и с комфортом открыть в любимом текстовом редакторе. Находим в файле директиву http, прописываем внутрь следующее:

server {
    # IP, который мы будем слушать
    listen 192.168.175.128:80;

    location / {
        # IP и порт, на которых висит node.js
        proxy_pass http://192.168.175.128:8000;
        proxy_set_header Host $host;
    }

    location ^~ /files/ {
        # Путь к корневому каталогу со статическими файлами
        root /home/www;
    }
}

Итак, по порядку. IP адрес можно узнать, выполнив команду ifconfig eth0, он будет в начале второй строки. Также надо знать порт, на котором висит node.js (для nerve это по умолчанию 8000, у Вас может быть по другому). Nginx будет обрабатывать только HTTP-запросы, поэтому если Вам захочется например поднять TCP-сервер на node, он не будет мешать.

Правила в nginx — достаточно большая и сложная тема, поэтому сейчас мы её касаться не будем. Достаточно сказать что эти два правила берут контент для /files/ из папки /home/www, а остальные запросы отдают Node.

Имейте в виду, что к указанному во втором location пути будет прибавлена строка запроса вместе с /files/. То есть, если пользователь запросит файл http://192.168.175.128/files/style.css, nginx попытается отдать файл /home/www/files/style.css.

После сохранения надо создать указанный каталог и дать пользователю www-data (по умолчанию) к нему доступ:

mkdir /home/www
mkdir /home/www/files
chown www-data /home/www
chown www-data /home/www/files

Пользователь, под которым работает nginx, указывается в первой строке конфигурационного файла (user www-data;).

Запускаем nginx:

nginx

Пробуем получить файл из /files/ и запрашиваем обычный путь или какой нибудь Callback. Я использовал для тестов модифицированный nerve, о котором писал в статье про горячую замену кода.

Если что то не работает как задумано, логи nginx по умолчанию можно найти в /var/log/nginx.

Ссылки по теме

Вики nginx с описанием формата конфигурационного файла
Мой nginx.conf на gist.github.com

15 комментариев
  1. Да что ж такое. Только подумывал написать статью про использование nodejs под nginx и вот, нате 🙂
    Видимо, нужно поменьше мне лениться.

    Все, ушел читать)

    • В Интернете вполне найдётся место для двух таких статей (и даже трёх). Так что рано опускать руки 🙂

      • Не, не буду писать — про то же самое хотел написать 🙂 Незачем повторяться. Я уж лучше про что-нибудь другое.

  2. zit permalink

    спасибо за статью!

    > В других дистрибутивах всё может быть сложнее
    угу, для тех, кто, как и я, в первый раз видит убунту (и линукс вообще) пригодятся такие команды:
    sudo /etc/init.d/nginx start
    sudo /etc/init.d/nginx stop
    sudo /etc/init.d/nginx restart

    кроме того, чтобы через обозреватель файлов работать с каталогом:
    1. в nginx.conf сменил пользователя на своего
    2. chown делал тоже не для www-data

    для listen (уж не знаю, правильно ли это) указал не ip из «ifconfig eth0», а то же, что и в proxy_pass

    • zit permalink

      хм… зря для listen указал тоже, что и для ноды… потому что понял все с точностью до наоборот 🙂 это ж он ноду проксит

  3. Антон permalink

    Спасибо за статью! Можно только уточнить у Вас, как в данном случае запустить сам node? Желательно ответить как чайнику, который редко урывками полгода читал про ноду, вот только что таки собрал ее и поставил на убунту, и успешно протестил работу тестового скрипта (из статьи http://www.giantflyingsaucer.com/blog/?p=894)
    Просто как я понял, сам nodejs — просто среда для исполнения js, а тот тестовый скрипт, что я тестил — как бы веб-сервер. Хочется знать, подойдет ли этот скрипт для бэкенда к nginx. И, как я догадываюсь, есть что-то для этих целей получше, чем сей helloworld-style скрипт? ))

    • Сама нода запускается именно так как вы это делали с HelloWorld-скриптом: node script.js. Для production environment лучше чтобы что нибудь поддерживало node в запущенном состоянии — ведь любая ошибка в скрипте роняет весь сервер. Я рекомендую комбинацию Init + Monit или supervise.

      • а как насчет pm2?
        Хотел сначала использовать strongloop pm, но он с шестой нодой что-то вообще не захотел и поход на монстра

  4. Спасибо!
    Очень полезная статья!

  5. спасибо! Я улучшил конфиг. Теперь nodejs (express) работает в связке с nginx на одном порте, очень удобно для нормального проекта.

    server {
    listen 127.0.0.1:8000;

    location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $Host;

    #proxy_read_timeout 120s;
    proxy_set_header Host $Host;
    proxy_http_version 1.1;
    proxy_set_header обновления $http_upgrade;
    proxy_set_header связи «upgrade»;
    }

    location ^~ /javascript/ {
    root /home/protected/static;
    }
    location ^~ /stylesheet/ {
    root /home/protected/static;
    }
    location ^~ /upload/ {
    root /home/protected/static;
    }
    location ^~ /image/ {
    root /home/protected/static;
    }
    }

  6. Админ, немного исправил..

    server {
    listen 127.0.0.1:80;

    location / {
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;

    #proxy_read_timeout 120s;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection «upgrade»;
    }

    location ^~ /javascript/ {
    root /home/protected/static;
    }
    location ^~ /stylesheet/ {
    root /home/protected/static;
    }
    location ^~ /upload/ {
    root /home/protected/static;
    }
    location ^~ /image/ {
    root /home/protected/static;
    }
    }

Trackbacks & Pingbacks

  1. Использование nginx вместе с Node.js « nodeJS
  2. Alec C4 » Blog Archive » all ’bout node.js

Ответить на Сенсорный стол Отменить ответ