What am I missing? This is my first time trying to use Django. The server that is built into Django will serve the file locally just fine, but I can’t get Apache to do the same. The following is what I’m doing from a brand new, clean, Linux 2 instance.
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: edit this part to look like this:
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: entire file looks like this:
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: entire file looks like this
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: entire file looks like this:
# 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!”)
Now for the Apache part:
sudo vim /etc/httpd/conf/httpd.conf
Paste the following to the bottom of 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
Connecting to 127.0.0.1:80… connected.
HTTP request sent, awaiting response…
and that is all it does until it times out. Connecting to the public IP address through a browser does the same thing; it connects and just sits there waiting for a response.
Apache error log (/var/log/httpd/error_log) says this:
Django ImportError: No module named site
A quick search suggests that this is because mod_wsgi is using a different version of python than my virtual environment. I’m using python3.7
cd /etc/httpd/modules
ldd mod_wsgi.so
outputs
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)
Clearly that is a different version. I’ve uninstalled it, and installed it again while in the python3.7 virtual environment, but the result is the same. It still says "libpython2.7.so.1.0 => /lib64/libpython2.7.so.1.0".
2
Answers
Ultimately, the problem here was a matter of getting Python to use the correct/new version of sqlite3. The error log located at /var/log/httpd/error_log proved very useful for troubleshooting (surprise).
In searching through other Q&A I found a lot of answers that involved LD_LIBRARY_PATH and LD_RUN_PATH. However, with deeper research I found that these are not the preferred method for instructing the compiler as to library paths. As shown below, ldconfig is used instead, along with a .conf file placed in the /etc/ld.so.conf.d/ directory.
The following is the step-by-step instructions for getting the latest Django served up by Apache; beginning with a fresh Linux 2 EC2 instance.
In this empty file you created, add:
next:
That will output something like the following. You will copy that and paste it to the bottom of your httpd.conf file. sudo vim /etc/httpd/conf/httpd.conf
next:
edit to look like the following (add ‘import sys’ and ‘sys.path…….’)
next:
edit to look like the following, substituting your EC2 instance public IP
next:
Edit to look like the following. These are Python files. So, mind your indentations
This next file you will create.
Paste:
Now back to Apache:
Paste the following to the bottom of httpd.conf:
.
At this point you should be able to make a request to the public IP of your instance and get the “Hello World!” response.
Finally:
and viola, you have some new issues to address!
On Amazon Linux 2 you need to compile the
mod_wsgi
against Python 3.7 yourself (EDIT: If you want to install the traditional apache module version of mod_wsgi). For some reason Amazon only has a yum package for a 2.7 compiled version included.I recently did the same and followed the instructions here http://www.marek.tokyo/2018/08/apache-24-modwsgi-python-37-django.html. But essentially:
./configure --with-python=/usr/bin/python3
LD_RUN_PATH=/usr/local/lib make
make install
/etc/ld.so.conf
and add:/usr/local/lib
to the end of the file if it’s not there alreadyldconfig
mod_wsgi
is linked properly by runningldd /usr/lib64/httpd/modules/mod_wsgi.so
, if it is you’ll see a link tolibpython3.7
echo "LoadModule wsgi_module /usr/lib64/httpd/modules/mod_wsgi.so" > /etc/httpd/conf.modules.d/01-wsgi.conf
)You might need to install gcc or some other build tools if they aren’t installed already.
EDIT:
In case it’s not clear, you should only download source code from sources you trust, so in this case, while that instruction page has a link, you could also just use the mod_wsgi github page (https://github.com/GrahamDumpleton/mod_wsgi/releases).
As an alternative, you can also use pip to install a mod_wsgi-express which doesn’t take additional apache config (https://modwsgi.readthedocs.io/en/develop/).
Either way, you can’t use the Amazon Linux 2 package if you are using the latest build of Python 3.