如何将最新 (2020) Django 安装到 AWS EC2 Linux 2 实例并使用 Apache Hello World 服务

Posted

技术标签:

【中文标题】如何将最新 (2020) Django 安装到 AWS EC2 Linux 2 实例并使用 Apache Hello World 服务【英文标题】:How to Install Latest (2020) Django to AWS EC2 Linux 2 Instance and Serve w/ Apache Hello World 【发布时间】:2020-10-13 07:06:13 【问题描述】:

我错过了什么?这是我第一次尝试使用 Django。内置在 Django 中的服务器可以很好地在本地提供文件,但我不能让 Apache 做同样的事情。以下是我在一个全新的、干净的 Linux 2 实例中所做的事情。

sudo yum update
sudo yum install -y python3
sudo yum install httpd-devel
sudo yum install -y mod_wsgi
cd /etc/httpd/modules     (verify that mod_wsgi is there)
cd /var/www/
sudo mkdir myApp
sudo chown ec2-user myApp
cd myApp
sudo pip3 install virtualenv
virtualenv myprojectenv
source myprojectenv/bin/activate
sudo pip3 install django==2.1.1
django-admin startproject myApp
cd myApp
python manage.py migrate
python manage.py runserver
wget http://127.0.0.1:8000/      (works correctly as it should and I receive test page)
python manage.py startapp hello
cd myApp
vim settings.py

settings.py:将此部分编辑为如下所示:

INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
     'django.contrib.staticfiles',
      'hello.apps.HelloConfig',
]

.

vim urls.py

urls.py:整个文件如下所示:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('hello.urls')),
]

.

cd ..
cd hello
vim views.py

views.py:整个文件看起来像这样

from django.shortcuts import render
# Create your views here.

# hello/views.py
from django.http import HttpResponse
def homePageView(request):
return HttpResponse('Hello, World!')

.

vim urls.py

hello/urls.py:整个文件如下所示:

# hello/urls.py
from django.urls import path
from .views import homePageView

urlpatterns = [
         path('', homePageView, name='home')
]

.

cd ..
python manage.py runserver
wget http://127.0.0.1:8000/      (works correctly as it should, now gets “Hello World!”)

现在是 Apache 部分:

sudo vim /etc/httpd/conf/httpd.conf
    

将以下内容粘贴到 httpd.conf 的底部:

WSGIScriptAlias / /var/www/myApp/myApp/myApp/wsgi.py
WSGIPythonHome /var/www/myApp/myprojectenv
WSGIPythonPath /var/www/myApp

<Directory /var/www/myApp/myApp/myApp>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

.

sudo service httpd restart
wget http://127.0.0.1

正在连接到 127.0.0.1:80... 已连接。 HTTP 请求已发送,正在等待响应...

这就是它所做的一切,直到它超时。通过浏览器连接到公共 IP 地址做同样的事情;它会连接并坐在那里等待响应。

Apache 错误日志 (/var/log/httpd/error_log) 说:

Django ImportError: No module named site

快速搜索表明这是因为 mod_wsgi 使用的 python 版本与我的虚拟环境不同。我正在使用python3.7

cd /etc/httpd/modules
ldd mod_wsgi.so

输出

    linux-vdso.so.1 (0x00007ffd7dec3000)
    libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0 (0x00007fe35815d000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe357f3f000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007fe357d3b000)
    libutil.so.1 => /lib64/libutil.so.1 (0x00007fe357b38000)
    libm.so.6 => /lib64/libm.so.6 (0x00007fe3577f8000)
    libc.so.6 => /lib64/libc.so.6 (0x00007fe35744d000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fe358755000)

显然这是一个不同的版本。我已经卸载了它,在python3.7虚拟环境中重新安装了它,但结果是一样的。它仍然说“libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0”。

【问题讨论】:

在顶部的第一个代码块中,我必须使用 python3 运行 python 命令,例如python3 manage.py migrate - 否则我得到一个语法错误。顺便说一句,这是迄今为止在 Amazon EC2 上的 Apache 中设置 Django 的最佳教程。 【参考方案1】:

最终,这里的问题是让 Python 使用正确/新版本的 sqlite3。位于 /var/log/httpd/error_log 的错误日志证明对故障排除非常有用(惊喜)。

在搜索其他问答时,我发现了很多涉及 LD_LIBRARY_PATH 和 LD_RUN_PATH 的答案。然而,随着更深入的研究,我发现这些并不是指导编译器了解库路径的首选方法。如下所示,使用 ldconfig 代替,以及放置在 /etc/ld.so.conf.d/ 目录中的 .conf 文件。

以下是获取 Apache 提供的最新 Django 的分步说明;从一个新的 Linux 2 EC2 实例开始。

sudo yum update
sudo su
yum groupinstall "Development Tools"
crtl-d
sudo yum -y install libffi-devel
sudo yum install -y openssl-devel
sudo vim /etc/ld.so.conf.d/usrlocal.conf

在您创建的这个空文件中,添加:

/usr/local/lib
/usr/local/lib64

下一个:

sudo ldconfig -v
cd ~
mkdir downloads
cd downloads
wget https://sqlite.org/2020/sqlite-autoconf-3320300.tar.gz
tar -xvf sqlite-autoconf-3320300.tar.gz
cd sqlite-autoconf-3320300
./configure --prefix=/usr/local
make -L
sudo make install
sudo ldconfig -v
cd ~downloads
wget https://www.python.org/ftp/python/3.7.7/Python-3.7.7.tgz
tar -xvf Python-3.7.7.tgz
cd Python-3.7.7
./configure --enable-shared --enable-optimizations --with-threads --enable-loadable-sqlite-extensions --with-openssl=/usr/local/lib64
sudo make -L
sudo make altinstall        (altinstall keeps old 2.7 version)
sudo ldconfig -v
python 3.7                  (to verify installation ctrl-d to quit)
>>>import sqlite3
>>> sqlite3.sqlite_version
ctrl-d
sudo chown -R ec2-user /usr/local/lib/python3.7
sudo chown ec2-user /usr/local/bin
sudo chown ec2-user /usr/local/lib
sudo yum install httpd-devel
sudo ldconfig -v
cd /var/www/
sudo mkdir django
sudo chown ec2-user django
cd django
pip3.7 install virtualenv
virtualenv myprojectenv
source myprojectenv/bin/activate
python -c 'import sys; print(sys.prefix)'
pip3.7 install mod_wsgi           
mod_wsgi-express module-config

这将输出如下内容。您将复制它并将其粘贴到 httpd.conf 文件的底部。须藤 vim /etc/httpd/conf/httpd.conf

LoadModule wsgi_module "/var/www/django/myprojectenv/lib/python3.7/site-packages/mod_wsgi/server/mod_wsgi-py37.cpython-37m-x86_64-linux-gnu.so"
WSGIPythonHome "/var/www/django/myprojectenv"

下一个:

pip3.7 install Django==3.0.7
django-admin startproject myApp
cd myApp
python manage.py migrate
python manage.py startapp hello
cd myApp
vim wsgi.py

编辑如下(添加“import sys”和“sys.path……”)

import os
import sys
from django.core.wsgi import get_wsgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myApp.settings')
sys.path.append('/var/www/myApp/myApp/myApp')
sys.path.append('/var/www/myApp/myApp')

application = get_wsgi_application()

下一个:

vim settings.py

编辑成如下所示,替换您的 EC2 实例公共 IP

    ALLOWED_HOSTS = ['xx.xxx.xx.xxx']     (substitute your EC2 public IP address)

    INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
      'django.contrib.sessions',
      'django.contrib.messages',
     'django.contrib.staticfiles',
      'hello.apps',
     ]


vim urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('hello.urls')),
]

下一个:

cd ../hello
vim views.py

编辑如下。这些是 Python 文件。所以,请注意你的缩进

from django.shortcuts import render
# Create your views here.

# hello/views.py
from django.http import HttpResponse
def homePageView(request):
    return HttpResponse('Hello, World!')

您将创建下一个文件。

vim urls.py

粘贴:

# hello/urls.py
from django.urls import path
from .views import homePageView

urlpatterns = [
    path('', homePageView, name='home')
]

现在回到 Apache:

sudo vim /etc/httpd/conf/httpd.conf
    

将以下内容粘贴到 httpd.conf 的底部:

WSGIScriptAlias / /var/www/django/myApp/myApp/wsgi.py
WSGIPythonPath /var/www/django

<Directory /var/www/django/myApp/myApp>
<Files wsgi.py>
Require all granted
</Files>
</Directory>

.

sudo service httpd start

此时,您应该能够向实例的公共 IP 发出请求并获得“Hello World!”回应。

最后:

sudo su
vim /var/log/httpd/error_log

还有 viola,你们有一些新问题要解决!

【讨论】:

以上说明让您的生活变得更加困难。当库存包很容易获得时,没有理由从源代码编译 SQLite 或 Python 3.7.7。库存的 yum 软件包更易于维护,并且不需要对库路径进行任何混乱。在某个时候,您可能只是不想费心运行 Amazon Linux 2 并在机器上运行不同的发行版。另外需要注意的是,这一切都超出了原始问题的范围。但只要它有效! 抱歉,我想我没有明确说明我是从那里开始的。我的意思是,显然最好用 yum 安装所有东西,因为它更容易。当这不起作用时,你必须开始做这种事情。是的,我试图让它与股票 yum 包一起工作,但它要么不起作用,要么某些依赖项只对旧版本的 Django 有用。 除了 Amazon Linux 2 和其他 AMI,您能否详细说明我为什么要运行不同的发行版? 嗯,我当时的想法是,如果您主要将 AWS Linux 2 作为 Web 主机运行,但要自己编译所有软件包,因为它们对您来说不够最新,然后运行Ubuntu 或其他保持最新的东西可能更适合?这样,您仍然可以进行软件包维护以更新任何安全问题,而现在您只能自己做这些,并且每次都监视/编译新版本。就是说,如果您愿意,那么我想您使用哪个发行版并不重要!【参考方案2】:

在 Amazon Linux 2 上,您需要自己针对 Python 3.7 编译 mod_wsgi(编辑:如果您想安装 mod_wsgi 的传统 apache 模块版本)。出于某种原因,Amazon 仅包含 2.7 编译版本的 yum 包。

我最近也做了同样的事情,并按照http://www.marek.tokyo/2018/08/apache-24-modwsgi-python-37-django.html 的说明进行操作。但本质上:

    下载 mod_wsgi(最新为 4.7.1) 展开 tar.gz 存档 运行./configure --with-python=/usr/bin/python3 运行LD_RUN_PATH=/usr/local/lib make 运行make install 打开/etc/ld.so.conf 并在文件末尾添加:/usr/local/lib(如果该文件不存在) 运行ldconfig 通过运行ldd /usr/lib64/httpd/modules/mod_wsgi.so 检查mod_wsgi 是否正确链接,如果是,您将看到指向libpython3.7 的链接 最后,您需要告诉 Apache 加载新模块,因此在 apache 配置中创建一个模块文件 (echo "LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so" &gt; /etc/httpd/conf.modules.d/01-wsgi.conf)

如果尚未安装 gcc 或其他一些构建工具,您可能需要安装它们。

编辑: 如果不清楚,您应该只从您信任的来源下载源代码,所以在这种情况下,虽然该说明页面有链接,但您也可以使用 mod_wsgi github 页面 (https://github.com/GrahamDumpleton/mod_wsgi/releases)。

作为替代方案,您也可以使用 pip 安装不需要额外 apache 配置的 mod_wsgi-express (https://modwsgi.readthedocs.io/en/develop/)。

无论如何,如果您使用的是最新版本的 Python 3,则无法使用 Amazon Linux 2 软件包。

【讨论】:

自从发布这个,我也停止使用 yum 安装 mod_wsgi。我现在使用 pip3.7 来安装它。因此,由于 Python 本质上是在安装 mod_wsgi 本身,所以我认为它是正确的版本。也就是说,我仍然在 sqlite3 版本上遇到错误。 对 sqlite 无能为力,但这可能值得提出一个新问题。我很幸运能够从源代码安装 mod-wsgi,反正它是全球性的。 事实证明,你必须自己编译 mod-wsgi 是不正确的。所有官方文档似乎都指向 pypi.org,它说使用 pip 进行安装。我有点担心您提供的用于下载源代码的链接,因为它似乎很容易被黑客入侵。 mod_wsgi 网站本身讨论了两种方式(从源代码或包 vs pypi),请参阅此处modwsgi.readthedocs.io/en/develop。该链接只是我安装和配置的说明,我没有说从那里下载代码,就像从 github 上拉一样容易(github.com/GrahamDumpleton/mod_wsgi/releases)

以上是关于如何将最新 (2020) Django 安装到 AWS EC2 Linux 2 实例并使用 Apache Hello World 服务的主要内容,如果未能解决你的问题,请参考以下文章

我将如何打印从最旧到最新的模型字段? [复制]

将 Django 从 2.1 升级到 2.2.13 时如何修复 pyodbc 依赖错误?

如何在python文件中,引用django1.10的model

pip 安装最新版本

Django应用

Django 2021年最新版教程16pycharm model模型修改之后如何同步更新到mysql数据库