I am in the process of deploying a Django project on an Ubuntu EC2. It should connect to a MySQL server on AWS RDS. The project works fine on the built-in Django development server you start with runserver
and it also connects to the RDS instance properly there. However, if I try running it in production, it throws a 500 Internal Server Error
that creates the following output in the error log:
mod_wsgi (pid=18656): Exception occurred processing WSGI script '/home/ubuntu/mysite/mysite/wsgi.py'.
Traceback (most recent call last):
File "/home/ubuntu/mysite/mysite_venv/lib/python3.8/site-packages/pymysql/connections.py", line 613, in connect
sock = socket.create_connection(
File "/usr/lib/python3.8/socket.py", line 808, in create_connection
raise err
File "/usr/lib/python3.8/socket.py", line 796, in create_connection
sock.connect(sa)
ConnectionRefusedError: [Errno 111] Connection refused
During handling of the above exception, another exception occurred:
...
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 111] Connection refused)")
This socket error occurs both with my custom views and with the mydomain.com/admin view. The relevant snippet of views.py
looks like this:
# get environment variables
db_host = os.environ.get('DB_HOST')
db_user = os.environ.get('DB_USER')
db_pass = os.environ.get('DB_PASS')
# connect to db
conn = pymysql.connect(host=db_host,
user=db_user,
password=db_pass)
c = conn.cursor()
c.execute('''USE mysitedatabase''')
The file is generally executed properly, log statements I inserted as a test before the database connection are created without errors. I have already tried removing all inbound traffic rules from my RDS security group, setting it to all IPv4 traffic with 0.0.0.0/0
but the error persisted. I assume that the socket error and the localhost error are connected since I don’t think it would make sense to connect via a unix socket when not being on localhost.
How do I stop pymysql from trying to connect on localhost when it should connect to RDS?
I use Ubuntu 20.04, Django 4.0, Apache/2.4.41 (Ubuntu) and Python 3.8.
CodePudding user response:
The environment variables were not configured in production, thank you @Mark B for pointing me in the right direction. There are multiple ways of going about this. I decided to take an easy route and add the database credentials to settings.py
like so:
DB_HOST = 'your_rds_endpoint'
DB_PASS = 'your_secure_password'
DB_USER = 'your_username'
Then just import settings.py
into views.py
and access the variable you need. In views.py
:
from django.conf import settings as my_settings
db_host = my_settings.DB_HOST
db_user = my_settings.DB_USER
db_pass = my_settings.DB_PASS
However, this is not the best way to do it because from what I could find, you should reference the settings file as little as possible because of security concerns.