Triển khai Django với gunicorn và nginx


81

Đây là một câu hỏi rộng nhưng tôi muốn nhận được câu trả lời chính tắc. Tôi đã cố gắng triển khai một trang web bằng gunicornnginx trong Django . Sau khi đọc rất nhiều hướng dẫn, tôi đã thành công nhưng tôi không thể chắc chắn rằng các bước tôi làm theo đủ tốt để chạy một trang web mà không gặp sự cố hoặc có thể có những cách tốt hơn để làm điều đó. Sự không chắc chắn đó là khó chịu.

Đó là lý do tại sao tôi đang tìm kiếm một câu trả lời rất chi tiết và được giải thích rõ ràng cho người mới. Tôi không muốn giải thích quá nhiều những gì tôi biết và những gì tôi không biết vì điều này có thể làm sai lệch câu trả lời một chút và những người khác có thể hưởng lợi ở mức độ thấp hơn từ câu trả lời của bạn. Tuy nhiên, một số điều tôi muốn thấy được đề cập là:

  • Bạn thấy "thiết lập" nào hoạt động tốt nhất? Tôi đã sử dụng virtualenv và di chuyển dự án Django của mình bên trong môi trường này, tuy nhiên tôi đã thấy một thiết lập khác trong đó có một thư mục dành cho môi trường ảo và các thư mục khác dành cho dự án.

  • Làm cách nào để thiết lập mọi thứ theo cách cho phép một số trang web được lưu trữ trong một máy chủ?

  • Tại sao một số người đề xuất sử dụng gunicorn_django -b 0.0.0.0:8000và những người khác đề xuất gunicorn_django -b 127.0.0.1:8000? Tôi đã thử nghiệm cái sau trong một phiên bản Amazon EC2 nhưng nó không hoạt động trong khi cái trước đó hoạt động mà không có vấn đề gì.

  • Logic đằng sau tệp cấu hình của nginx là gì? Có rất nhiều hướng dẫn sử dụng các tệp cấu hình khác nhau đến mức tôi bối rối không biết cái nào tốt hơn. Ví dụ, một số người sử dụng alias /path/to/static/foldervà những người khác root /path/to/static/folder. Có thể bạn có thể chia sẻ tệp cấu hình ưa thích của mình.

  • Tại sao chúng ta tạo liên kết biểu tượng giữa site-availablesites-enabledtrong /etc/nginx?

  • Một số phương pháp hay nhất luôn được hoan nghênh :-)

Cảm ơn


Bạn có thể vui lòng đăng một ví dụ trên git về những nginx và gunicorn / uwsgi này không. Nó sẽ hữu ích hơn cho những người mới học như tôi.
Shiva

@Shiva Trên thực tế, câu trả lời của miki725 chứa một mẫu tệp cấu hình rất đầy đủ. Nếu bạn muốn được giới thiệu rất kỹ lưỡng về những gì đang diễn ra với nginx, tôi khuyên bạn nên <a href=" amazon.com/Nginx-HTTP-Server-Cl%C3%A9ment-Nedelcu/dp/… book </b>. việc tích hợp gunicorn là rất đơn giản Nó được nêu <a href=" docs.djangoproject.com/en/dev/howto/deployment/wsgi/gunicorn/...>.
Robert Smith

Câu trả lời:


106

Bạn thấy "thiết lập" nào hoạt động tốt nhất? Tôi đã sử dụng virtualenv và di chuyển dự án django của mình bên trong môi trường này, tuy nhiên tôi đã thấy một thiết lập khác trong đó có một thư mục dành cho môi trường ảo và các thư mục khác dành cho các dự án.

virtualenv là một cách để cô lập môi trường Python; do đó, nó không có một phần lớn để chơi khi triển khai - tuy nhiên trong quá trình phát triểnthử nghiệm, đó là một yêu cầu nếu không được khuyến khích.

Giá trị bạn sẽ nhận được từ virtualenv là nó cho phép bạn đảm bảo rằng các phiên bản thư viện chính xác được cài đặt cho ứng dụng. Vì vậy, không quan trọng bạn gắn chính môi trường ảo ở đâu. Chỉ cần đảm bảo rằng bạn không bao gồm nó như một phần của hệ thống lập phiên bản mã nguồn.

Bố cục hệ thống tệp không quan trọng. Bạn sẽ thấy rất nhiều bài báo ca ngợi những ưu điểm của bố cục thư mục và thậm chí cả các dự án khung mà bạn có thể sao chép như một điểm khởi đầu. Tôi cảm thấy đây là một sở thích cá nhân hơn là một yêu cầu khó. Chắc chắn nó rất tốt khi có; nhưng trừ khi bạn biết lý do tại sao , nó không thêm bất kỳ giá trị nào cho quá trình triển khai của bạn - vì vậy đừng làm điều đó vì một số blog đề xuất nó trừ khi nó phù hợp với kịch bản của bạn. Ví dụ: không cần tạo setup.pytệp nếu bạn không có máy chủ PyPi riêng nằm trong quy trình triển khai của bạn.

Làm cách nào để thiết lập mọi thứ theo cách cho phép một số trang web được lưu trữ trong một máy chủ?

Có hai điều bạn cần thực hiện nhiều thiết lập trang web:

  1. Máy chủ đang lắng nghe IP công cộng trên cổng 80 và / hoặc cổng 443 nếu bạn có SSL.
  2. Một loạt các "quy trình" đang chạy mã nguồn django thực tế.

Mọi người sử dụng nginx cho vị trí số 1 vì nó là proxy rất nhanh và nó không đi kèm với chi phí của một máy chủ toàn diện như Apache. Bạn có thể tự do sử dụng Apache nếu bạn cảm thấy thoải mái với nó. Không có yêu cầu rằng "đối với nhiều trang web, hãy sử dụng nginx"; bạn chỉ cần một dịch vụ đang lắng nghe trên cổng đó, biết cách chuyển hướng (proxy) đến các quy trình của bạn đang chạy mã django thực tế.

Đối với # 2, có một số cách để bắt đầu các quy trình này. gevent / uwsgi là những cái phổ biến nhất. Điều duy nhất cần nhớ ở đây là không sử dụng máy chủ chạy trong sản xuất .

Đó là những yêu cầu tối thiểu tuyệt đối. Thông thường, mọi người thêm một số loại trình quản lý quy trình để kiểm soát tất cả các "máy chủ django" (# 2) đang chạy. Ở đây bạn sẽ thấy upstartsupervisorđề cập. Tôi thích người giám sát hơn vì nó không cần phải tiếp quản toàn bộ hệ thống (không giống như người mới bắt đầu). Tuy nhiên, một lần nữa - đây không phải là một yêu cầu khó . Bạn hoàn toàn có thể chạy một loạt các screenphiên và phát hiện chúng. Nhược điểm là, nếu máy chủ của bạn khởi động lại, bạn sẽ phải khởi chạy lại các phiên màn hình.

Cá nhân tôi muốn giới thiệu:

  1. Nginx cho # 1
  2. Hãy lựa chọn giữa uwsgi và gunicorn - Tôi sử dụng uwsgi.
  3. người giám sát để quản lý các quy trình phụ trợ.
  4. Tài khoản hệ thống cá nhân (người dùng) cho từng ứng dụng bạn đang lưu trữ.

Lý do tôi đề xuất # 4 là cô lập các quyền; một lần nữa, không phải là một yêu cầu.

Tại sao một số người đề xuất sử dụng gunicorn_django -b 0.0.0.0:8000 và những người khác đề xuất gunicorn_django -b 127.0.0.1:8000? Tôi đã thử nghiệm cái sau trong một phiên bản Amazon EC2 nhưng nó không hoạt động trong khi cái trước đó hoạt động mà không có vấn đề gì.

0.0.0.0có nghĩa là "tất cả địa chỉ IP" - địa chỉ meta của nó (nghĩa là địa chỉ giữ chỗ). 127.0.0.1là một địa chỉ dành riêng luôn trỏ đến máy cục bộ. Đó là lý do tại sao nó được gọi là "localhost". Nó chỉ có thể truy cập được đối với các quy trình chạy trên cùng một hệ thống.

Thông thường, bạn có máy chủ giao diện người dùng (# 1 trong danh sách ở trên) lắng nghe địa chỉ IP công cộng. Bạn nên liên kết rõ ràng máy chủ với một địa chỉ IP .

Tuy nhiên, nếu vì lý do nào đó bạn đang sử dụng DHCP hoặc bạn không biết địa chỉ IP sẽ là gì (ví dụ: hệ thống mới được cấp phép của nó), bạn có thể yêu cầu nginx / apache / bất kỳ quy trình nào khác liên kết với 0.0.0.0. Đây nên là một biện pháp dừng khoảng cách tạm thời .

Đối với máy chủ sản xuất, bạn sẽ có một IP tĩnh. Nếu bạn có một IP động (DHCP), thì bạn có thể đăng nhập 0.0.0.0. Tuy nhiên, rất hiếm khi bạn có DHCP cho các máy sản xuất của mình.

Việc ràng buộc gunicorn / uwsgi với địa chỉ này không được khuyến khích trong quá trình sản xuất. Nếu bạn ràng buộc quy trình phụ trợ của mình (gunicorn / uwsgi) 0.0.0.0, nó có thể có thể truy cập "trực tiếp", bỏ qua proxy giao diện người dùng của bạn (nginx / apache / etc); ai đó có thể yêu cầu http://your.public.ip.address:9000/và truy cập trực tiếp vào ứng dụng của bạn, đặc biệt nếu máy chủ front-end (nginx) và back end process của bạn (django / uwsgi / gevent) đang chạy trên cùng một máy .

Tuy nhiên, bạn có thể tự do làm điều đó nếu bạn không muốn gặp rắc rối khi chạy một máy chủ proxy phía trước.

Logic đằng sau tệp cấu hình của nginx là gì? Có rất nhiều hướng dẫn sử dụng các tệp cấu hình khác nhau đến mức tôi bối rối không biết cái nào tốt hơn. Ví dụ: một số người sử dụng "bí danh / đường dẫn / đến / static / thư mục" và những người khác "root / path / to / static / folder". Có thể bạn có thể chia sẻ tệp cấu hình ưa thích của mình.

Điều đầu tiên bạn nên biết về nginx là nó không phải là một máy chủ web như Apache hoặc IIS. Nó là một proxy. Vì vậy, bạn sẽ thấy các thuật ngữ khác nhau như "ngược dòng" / "hạ lưu" và nhiều "máy chủ" đang được định nghĩa. Hãy dành chút thời gian và xem qua hướng dẫn sử dụng nginx trước.

Có rất nhiều cách khác nhau để thiết lập nginx; nhưng đây là một trong những câu trả lời cho câu hỏi của bạn về aliasvs root. rootlà một chỉ thị rõ ràng liên kết gốc tài liệu ("thư mục chính") của nginx. Đây là thư mục mà nó sẽ xem xét khi bạn đưa ra yêu cầu mà không có đường dẫn nhưhttp://www.example.com/

aliascó nghĩa là "ánh xạ tên vào một thư mục". Thư mục bí danh có thể không phải là thư mục con của gốc tài liệu.

Tại sao chúng tôi tạo liên kết tượng trưng giữa trang web có sẵn và trang web được kích hoạt trong / etc / nginx?

Đây là một cái gì đó độc đáo đối với debian (và các hệ thống giống debian như ubuntu). sites-availableliệt kê các tệp cấu hình cho tất cả các máy chủ / trang web ảo trên hệ thống. Liên kết biểu tượng từ sites-enabledđể sites-available"kích hoạt" trang web hoặc máy chủ ảo đó. Đây là một cách để tách các tệp cấu hình và dễ dàng bật / tắt máy chủ.


1
Câu trả lời chính xác! Rất nhiều câu hỏi được làm sáng tỏ. Bạn có thể giải thích kỹ hơn một chút (hoặc thêm một ví dụ) về ý của bạn khi liên kết rõ ràng máy chủ với địa chỉ IP và ràng buộc gunicorn / uwsgi phải được liên kết với 0.0.0.0 không? Thật không may, tôi nghĩ đó là những gì tôi đã làm. Cảm ơn!
Robert Smith

7
Một máy tính điển hình sẽ có ít nhất hai địa chỉ IP: 127.0.0.1và địa chỉ IP được mạng gán cho nó; đây là mức tối thiểu - máy của bạn có thể có nhiều giao diện và nhiều địa chỉ IP. Bạn nên cấu hình máy chủ web của mình (hoặc bất kỳ quy trình nào, thực sự); để nghe trên một địa chỉ IP - đây là ý tôi muốn nói rõ ràng. Khi bạn liên kết với 0.0.0.0, bạn đang yêu cầu chương trình lắng nghe tất cả các địa chỉ IP bao gồm bất kỳ địa chỉ mới nào có thể được gán cho máy của bạn . Đây là một thực tiễn không tốt vì nhiều lý do (bảo mật là một trong số đó).
Burhan Khalid

Hiểu rồi. Tôi đã định cấu hình Gunicorn đúng cách. Cảm ơn rât nhiều!
Robert Smith

nginx có thể phân phát nội dung tĩnh.
Marcin

làm cách nào máy chủ biết được chúng tôi đã định cấu hình địa chỉ máy chủ trong tệp nào/etc/nginx/sites-enabled
Shiva

11

Tôi không phải là chuyên gia triển khai nhưng sẽ chia sẻ một số thực tiễn của tôi để triển khai Django với gevent (mặc dù phải tương tự như gunicorn).

virtualenvlà tuyệt vời vì những lý do tôi sẽ không đi vào. Tuy nhiên, tôi thấy virtualenv-wrapper( tài liệu ) rất hữu ích, đặc biệt khi bạn đang làm việc trên nhiều dự án vì nó cho phép dễ dàng chuyển đổi giữa các Virtualenv khác nhau. Điều này không thực sự áp dụng cho môi trường triển khai tuy nhiên khi tôi cần khắc phục sự cố trên máy chủ bằng SSH, tôi thấy điều này rất hữu ích. Một lợi thế khác của việc sử dụng nó là nó quản lý thư mục virtualenv, do đó, bạn sẽ ít làm việc thủ công hơn. Virtualenv được sử dụng một lần để trong trường hợp bạn gặp sự cố về phiên bản hoặc bất kỳ sự cố cài đặt nào khác, bạn có thể kết xuất env và tạo một env mới. Do đó, cách tốt nhất là không đưa bất kỳ mã dự án nào của bạn vào virtualenv. Nó nên được giữ riêng biệt.

Đối với việc thiết lập nhiều trang web, virtualenvcó khá nhiều câu trả lời. Bạn nên có một virutalenv riêng cho từng dự án. Chỉ vậy thôi cũng có thể giải quyết được nhiều vấn đề. Sau đó, khi bạn triển khai, một quy trình Python khác sẽ chạy các trang web khác nhau để tránh mọi xung đột có thể xảy ra giữa các lần triển khai. Một công cụ tôi đặc biệt thấy rất hữu ích trong việc quản lý nhiều trang web trên cùng một máy chủ là supervisor( tài liệu). Nó cung cấp một giao diện dễ dàng để bắt đầu, dừng và khởi động lại các phiên bản Django khác nhau. Nó cũng có khả năng tự động khởi động lại quá trình khi nó bị lỗi hoặc khi máy tính khởi động. Vì vậy, ví dụ, nếu một số ngoại lệ được đưa ra và không có gì bắt được nó, toàn bộ trang web có thể đi xuống. Người giám sát sẽ nắm bắt được điều đó và sẽ tự động khởi động lại phiên bản Django. Sau đây là cấu hình chương trình giám sát mẫu (một quy trình duy nhất):

[program:foo]
command=/path/toviertualenv/bin/python deploy.py
directory=/path/where/deploy.py/is/located/
autostart=true
autorestart=true
redirect_stderr=True
user=www

Đối với Nginx, tôi biết nó có thể gây choáng ngợp lúc đầu. Tôi thấy cuốn sách Nginx rất hữu ích. Nó giải thích tất cả các chỉ thị nginx chính.

Trong quá trình cài đặt nginx của mình, tôi thấy phương pháp hay nhất là chỉ thiết lập các cấu hình cốt lõi trong nginx.conftệp và sau đó tôi có một thư mục riêng sitesđể giữ các cấu hình nginx cho từng trang web mà tôi lưu trữ. Sau đó, tôi chỉ bao gồm tất cả các tệp từ thư mục đó trong tệp cấu hình lõi. Tôi sử dụng chỉ thị include sites/+*.conf;. Bằng cách này, nó chỉ bao gồm các tệp bắt đầu bằng +ký hiệu trong sitesthư mục. Bằng cách đó, chỉ bằng tên tệp, tôi có thể kiểm soát tệp cấu hình nào sẽ được tải. Vì vậy, nếu tôi muốn vô hiệu hóa một trang web nhất định, tôi chỉ cần đổi tên tệp cấu hình và khởi động lại nginx. Không thực sự chắc chắn ý của bạn về "liên kết tượng trưng giữa trang web có sẵn và trang web được kích hoạt trong / etc / nginx" trong câu hỏi của bạn vì đó là các thư mục có tên Apache nhưng chúng thực hiện nhiệm vụ tương tự như lệnh include.

Đối với rootvà các aliaschỉ thị, chúng khá giống nhau ngoại trừ vị trí gốc của chúng được tính toán. Trong alias, bất cứ điều gì ở locationtrong bị giảm, trong khi gốc trong nó thì không. Hình ảnh mà bạn có cấu hình nginx sau:

location /static {
    alias /some/path/;
}
location /static2 {
    root /some/other/path/;
}

Nếu người dùng truy cập các URL này, thì nginx sẽ cố gắng tìm kiếm các tệp ở những vị trí sau trên hệ thống:

/static/hello/world.pdf => /some/path/hello/world.pdf
/static2/hello/world.pdf => /some/other/path/static2/hello/world.pdf

Đây là một cấu hình đơn giản cho trang web nginx:

server {
    server_name .foodomain.com;
    listen 80;

    access_log logs/foodomain.log;

    gzip                on;
    gzip_http_version   1.0;
    gzip_comp_level     2;
    gzip_proxied        any;
    gzip_min_length     1100;
    gzip_buffers        16 8k;
    gzip_types          text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    # Some version of IE 6 don't handle compression well on some mime-types, so just disable for them
    gzip_disable "MSIE [1-6].(?!.*SV1)";

    # Set a vary header so downstream proxies don't send cached gzipped content to IE6
    gzip_vary on;

    location / {
        proxy_read_timeout      30s;
        proxy_pass              http://localhost:8000;
        proxy_set_header        Host                 $host;
        proxy_set_header        User-Agent           $http_user_agent;
        proxy_set_header        X-Real-IP            $remote_addr;
    }

    location /media {
        alias   /path/to/media/;
        expires 1y;
    }

    location /static {
        autoindex on;
        expires   1y;
        alias     /path/to/static/;
    }

     location /favicon.ico {
        alias /path/to/favicon.ico;
    }
}

Hy vọng rằng điều này sẽ giúp bạn một chút.


Trên thực tế, câu trả lời của bạn giúp ích rất nhiều! Người giám sát nghe có vẻ tuyệt vời và đó là một trong số ít những điều dường như có sự đồng thuận giữa các blogger. Lời khuyên tuyệt vời về môi trường ảo và trình bao bọc của nó. Tôi đã muốn thêm virtualenv-wrapper vào hỗn hợp nhưng tôi không muốn tăng độ phức tạp trong câu hỏi này một cách không cần thiết. Đối với trang web có sẵn và trang web được kích hoạt, nginx chứa các thư mục đó. Bạn tạo tệp cấu hình cho nginx ở đâu? Bên trong dự án Django của bạn?
Robert Smith

Cá nhân tôi có chúng trong thư mục cấu hình nginx. Trong trường hợp của tôi thì đúng như vậy /usr/local/nginx/config/sites. Tuy nhiên, không chắc chắn nếu nó là phương pháp chính xác hoặc tốt hơn. Lý do tại sao tôi giữ chúng ở đó là vì nếu tôi di chuyển nó ra, thì bằng cách nào đó tôi phải đưa nó vào nginx, bằng cách bao gồm includechỉ thị theo cách thủ công hoặc tạo liên kết tượng trưng. Trong cả hai trường hợp, nó là lao động thủ công, vì vậy tôi chỉ giữ nó ở nơi cấu hình chính.
miki725

Tôi đang đọc cuốn sách bạn đề xuất :-) Thật tuyệt và như bạn có thể nhớ, /sites/*.conf là một cách được đề xuất để làm điều đó. Dù sao, cảm ơn bạn cho câu trả lời của bạn.
Robert Smith

Chào mừng bạn. Một phần về cuốn sách tôi mặc dù không hữu ích lắm là cách sử dụng Django với nginx. Sách khuyên bạn nên sử dụng fastcgi, nó không gọn gàng như sử dụng proxy pass. Vì vậy, bạn có thể bỏ qua Chương 6.
miki725

Tôi vừa đọc xong cuốn sách. Thật tuyệt vời. Tôi thực sự đọc chương 6 vì tôi muốn biết các tác phẩm của hoy fastcgi, nhưng bạn nói đúng ... nó không hữu ích cho lắm. Cảm ơn!
Robert Smith

2

Chà, liên quan đến các phương pháp hay nhất mà bạn đã hỏi trong câu hỏi của mình, tôi không thể không chia sẻ một công cụ đã làm việc kỳ diệu cho tôi, theo nghĩa đen! Bản thân tôi đã từng bối rối trong một số tệp cấu hình của gunicorn, nginx, supervisorD cho một số trang web! Nhưng tôi khao khát bằng cách nào đó tự động hóa toàn bộ quy trình để tôi có thể thực hiện các thay đổi đối với ứng dụng / trang web của mình và triển khai nó ngay lập tức. Tên của nó là django-fagungis. Bạn có thể tìm thấy chi tiết về trải nghiệm của tôi với tự động hóa Triển khai Django tại đây . Tôi vừa định cấu hình fabfile.py MỘT LẦN (django-fagungis sử dụng kết cấu để tự động hóa toàn bộ quá trình và tạo một virtualenv trong máy chủ từ xa của bạn, điều này RẤT hữu íchđể quản lý các phần phụ thuộc của một số trang web được lưu trữ trên một máy chủ. Nó sử dụng nginx, gunicorn và supervisorD để xử lý triển khai dự án / trang web Django) và django-fagungis sao chép dự án mới nhất của tôi từ bitbucket (tôi sử dụng để lật đổ) và triển khai nó trên máy chủ từ xa của tôi và tôi chỉ cần nhập ba lệnh trên shell của máy cục bộ của tôi và nó !! Đối với tôi, đây là cách tốt nhất và không phức tạp để triển khai Django.


Cảm ơn!. Tôi sẽ xem qua nó.
Robert Smith

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.