Nginx - tệp tĩnh phục vụ nhầm lẫn với root & bí danh


473

Tôi cần phục vụ ứng dụng của mình thông qua máy chủ ứng dụng của mình tại 8080và các tệp tĩnh của tôi từ một thư mục mà không cần chạm vào máy chủ ứng dụng. Cấu hình nginx tôi có là một cái gì đó như thế này ...

    # app server on port 8080
    # nginx listens on port 8123
    server {
            listen          8123;
            access_log      off;

            location /static/ {
                    # root /var/www/app/static/;
                    alias /var/www/app/static/;
                    autoindex off;
            }


            location / {
                    proxy_pass              http://127.0.0.1:8080;
                    proxy_set_header        Host             $host;
                    proxy_set_header        X-Real-IP        $remote_addr;
                    proxy_set_header        X-Forwarded-For  $proxy_add_x_forwarded_for;
            }
    }

Bây giờ, với cấu hình này, mọi thứ đều hoạt động tốt. Lưu ý rằng rootchỉ thị được nhận xét.

Nếu tôi kích hoạt rootvà hủy kích hoạt alias- nó sẽ ngừng hoạt động. Tuy nhiên, khi tôi xóa dấu vết /static/khỏi rootnó thì nó bắt đầu hoạt động trở lại.

Ai đó có thể giải thích những gì đang xảy ra. Ngoài ra, vui lòng giải thích rõ ràng và rõ ràng sự khác biệt giữa rootalias, và mục đích của chúng.

Câu trả lời:


1074

Tôi đã tìm thấy câu trả lời cho sự nhầm lẫn của tôi.

Có một sự khác biệt rất quan trọng giữa rootcác aliaschỉ thị. Sự khác biệt này tồn tại trong cách đường dẫn được chỉ định trong roothoặc aliasđược xử lý.

Trong trường hợp rootchỉ thị, đường dẫn đầy đủ được gắn vào gốc bao gồm cả phần vị trí , trong khi đó trong aliaschỉ thị, chỉ phần của đường dẫn KHÔNG bao gồm phần vị trí được gắn vào bí danh .

Để minh họa:

Hãy nói rằng chúng ta có cấu hình

location /static/ {
    root /var/www/app/static/;
    autoindex off;
}

Trong trường hợp này, con đường cuối cùng mà Nginx sẽ xuất phát sẽ là

/var/www/app/static/static

Điều này sẽ trở lại 404vì không có static/trongstatic/

Điều này là do phần vị trí được gắn vào đường dẫn được chỉ định trong root. Do đó, với root, cách chính xác là

location /static/ {
    root /var/www/app/;
    autoindex off;
}

Mặt khác, với alias, phần vị trí bị rơi . Vì vậy, cho cấu hình

location /static/ {
    alias /var/www/app/static/;
    autoindex off;           ↑
}                            |
                             pay attention to this trailing slash

đường dẫn cuối cùng sẽ được hình thành chính xác như

/var/www/app/static

Các trường hợp dấu gạch chéo cho aliaschỉ thị

Không có hướng dẫn dứt khoát về việc liệu một dấu gạch chéo có bắt buộc theo tài liệu Nginx hay không , nhưng một quan sát chung của mọi người ở đây và những nơi khác dường như cho thấy rằng đó là.

Một vài nơi đã thảo luận về điều này, mặc dù không kết luận.

/server/376162/how-can-i-create-a-location-in-nginx-that-works-with-and-without-a-trailing-slas

/server/375602/why-is-my-nginx-alias-not- làm việc


97
Dấu gạch chéo trên đường dẫn bí danh là điều cần thiết!
mafrosis

2
Điều này thật tuyệt vời (nó đã giúp tôi khắc phục các sự cố cấu hình của mình), nhưng tôi tự hỏi những cài đặt ghi nhật ký nào mọi người có thể sử dụng để giúp chẩn đoán các loại sự cố này? Giống như, mọi thứ sẽ in ra để ghi nhật ký nội dung như "yêu cầu đã nhận cho [...], khớp với khối cấu hình" location [...] ", thư mục tìm kiếm [...]"
Pistos

2
@Pistos: đưa log_format scripts '$document_root | $uri | > $request';vào httpphần và access_log /var/log/nginx/scripts.log scripts;vào serverphần cấu hình nginx ..
helvete

Cảm ơn! Thật vậy, dấu gạch chéo là điều cần thiết trên bí danh, nếu không tôi đã nhận được nginx: [emerg] invalid number of arguments in "alias" directive, và máy chủ đã bị hỏng trong quá trình khởi động lại.
FotisK

@mafrosis Tại sao nó cần thiết?
Bruce Sun

104

như nói như @treecoder

Trong trường hợp rootchỉ thị, đường dẫn đầy đủ được gắn vào gốc bao gồm cả phần vị trí, trong khi đó trong aliaschỉ thị, chỉ phần của đường dẫn KHÔNG bao gồm phần vị trí được gắn vào bí danh.

một bưc tranh đang gia ngan lơi noi

cho root:

nhập mô tả hình ảnh ở đây

cho alias:

nhập mô tả hình ảnh ở đây


11
Mũi tên đầu tiên trong hình ảnh thứ hai có phải là "+" không?
aioobe

35

Trong trường hợp của bạn, bạn có thể sử dụng rootchỉ thị, bởi vì $urimột phần của lệnh locationnày giống với rootphần chỉ thị cuối cùng .

Tài liệu Nginx cũng khuyên nó:
Khi vị trí khớp với phần cuối của giá trị của lệnh:

location /images/ {
    alias /data/w3/images/;
}

thay vào đó, tốt hơn là sử dụng lệnh gốc:

location /images/ {
    root /data/w3;
}

rootchỉ thị sẽ nối $urivào đường dẫn.


2
Tại sao nó tốt hơn? Tài liệu cũng không nói.
HostedMetrics.com

Lợi ích mà tôi thấy là tránh trùng lặp $ uri, / hình ảnh trong ví dụ đã cho, khi sử dụng bí danh
antonbormotov

21

Chỉ là một phụ lục nhanh cho câu trả lời rất hữu ích của @ good_computer, tôi muốn thay thế root của URL bằng một thư mục, nhưng chỉ khi nó khớp với thư mục con chứa các tệp tĩnh (mà tôi muốn giữ lại như một phần của đường dẫn).

Ví dụ: nếu tệp được yêu cầu ở trong /app/jshoặc /app/css, hãy xem /app/location/public/[that folder].

Tôi đã làm điều này để làm việc bằng cách sử dụng một regex.

 location ~ ^/app/((images/|stylesheets/|javascripts/).*)$ {
     alias /home/user/sites/app/public/$1;
     access_log off;
     expires max;
 }

2
Cảm ơn câu trả lời này. Tôi biết điều này là 3 năm sau, nhưng bất cứ ai cũng có thể giải thích nếu có sự đánh đổi hiệu năng và / hoặc bảo mật giữa việc sử dụng bí danh so với root?
Mina

1
@Mina Tốt hơn là sử dụng root nếu bạn có thể. (Có một nhận xét trong tài liệu wiki.nginx.org/HttpCoreModule#alias )
Matthew Wilcoxson

Đây chính xác là những gì tôi đến đây cho 👍👏
Alienfromouterspace

6

aliasđược sử dụng để thay thế đường dẫn phần vị trí (LPP) trong đường dẫn yêu cầu, trong khi đường dẫn rootđược sử dụng để được thêm vào đường dẫn yêu cầu.

Chúng là hai cách để ánh xạ đường dẫn yêu cầu đến đường dẫn tệp cuối cùng.

aliaschỉ có thể được sử dụng trong khối vị trí và nó sẽ ghi đè lên bên ngoài root.

aliasrootkhông thể được sử dụng trong khối vị trí với nhau.


3
server {
    server_name xyz.com;
    root /home/ubuntu/project_folder/;

    client_max_body_size 10M;
    access_log  /var/log/nginx/project.access.log;
    error_log  /var/log/nginx/project.error.log;

    location /static {
        index index.html;
    }

    location /media {
        alias /home/ubuntu/project/media/;
    }
}

Khối máy chủ để sống trang tĩnh trên nginx.


2

Nói cách khác về việc giữ bản tóm tắt này: trong trường hợp root, đối số vị trí được chỉ định là một phần của đường dẫn và URI của hệ thống tệp . Mặt khác - đối với aliaschỉ thị của câu lệnh vị trí chỉ là một phần của URI

Vì vậy, aliaslà một tên khác ánh xạ URI nhất định đến một đường dẫn nhất định trong hệ thống tệp, trong khi rootnối thêm đối số vị trí vào đường dẫn gốc được cung cấp dưới dạng đối số cho rootchỉ thị.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.