如何将最新 (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" > /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 依赖错误?