My project is created with React (create-react-app), React router (no webpack), -- Django (rest) and Socketio with eventlet on the backend. I have 3 problems with deployment with apache2 - Everything worked perfectly on development:
Created 2 conf files, one for the frontend port 80 and one for the backend port 8000 - separetely they work fine relatively.
The problem I have with deployment:
- Socket.io gives
[wsgi:error]
eventlet.wsgi.server(eventlet.listen(("", 8000)), application, log_output=False)
sock.bind(addr)
Address already in use
- checked what uses the port --> only apache2 and it gives the same result with any other port
- tried to create a separate conf file for socket with port 5000 (changing the port in wsgi eventlet line), same result the socketFile.conf:
Listen 5000
<VirtualHost *:5000>
ServerName www.example.com
ServerAlias example.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /home/path/to/main/folder>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess exampleSocket python-home=/home/path/to/venv python-path=/home/path/to/main/folder
WSGIProcessGroup exampleSocket
WSGIScriptAlias / /path/to/wsgi.py
</VirtualHost>
- the next line is done by default with eventlet (reuse_addr=True, reuse_port=None)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
socketio_app/views.py
async_mode = None
import os
import socketio
basedir = os.path.dirname(os.path.realpath(__file__))
sio = socketio.Server(
async_mode=async_mode,
logger=False,
cors_allowed_origins='http://localhost:3000'
)
thread = None
...
wsgi.py
import os
from django.core.wsgi import get_wsgi_application
from socketio_app.views import sio
import socketio
import eventlet
import eventlet.wsgi
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "server.settings")
application = get_wsgi_application()
application = socketio.WSGIApp(sio, application)
eventlet.wsgi.server(eventlet.listen(("", 8000)), application, log_output=False)
Answer
It seems that the error Address already in use
is happening because the port you're trying to bind to (in this case, port 8000 or 5000) is already in use, possibly by another service like Apache2, or your app is trying to bind twice to the same port.
Here are some steps to troubleshoot and resolve this:
1. Check Port Usage
Make sure no other services are using the port. Run this command to check what process is using the port:
sudo lsof -i :8000
If the port is in use by another process (e.g., Apache2 or an already running instance of your app), kill the process:
sudo kill -9 <PID>
You can also check for port 5000 or whatever other port you are using.
2. Configure Eventlet Correctly
Eventlet is designed to handle concurrent connections asynchronously, but it seems you might have a configuration issue with Apache2 or the way it's being invoked with WSGI.
In wsgi.py
, you're calling eventlet.wsgi.server()
after wrapping the application with socketio.WSGIApp
. However, you should avoid starting the Eventlet server in your WSGI file when using Apache2 with mod_wsgi.
Try removing the line:
eventlet.wsgi.server(eventlet.listen(("", 8000)), application, log_output=False)
Apache should be handling the process of running the WSGI application, so there's no need to manually start an eventlet server. The WSGI application should be run as a service by Apache.
3. Separate Apache Configurations
Ensure your socketFile.conf
(for Socket.io on port 5000) is not conflicting with other Apache configurations. Double-check your Apache config files and ensure that the socket file is being properly handled and isolated.
Here’s a refined example of your configuration for Socket.io:
socketFile.conf
(Apache config for port 5000):
Listen 5000
<VirtualHost *:5000>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /path/to/your/socketapp
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
<Directory /path/to/your/socketapp>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
WSGIDaemonProcess socketApp python-home=/home/path/to/venv python-path=/path/to/socketapp
WSGIProcessGroup socketApp
WSGIScriptAlias / /path/to/socketapp/wsgi.py
</VirtualHost>
4. Use mod_proxy
and mod_proxy_uwsgi
(If Apache2 is fronting)
If you continue to run into issues with eventlet
trying to bind to ports that are managed by Apache, consider using Apache’s mod_proxy
to forward requests to your Socket.io server. For example:
<VirtualHost *:80>
ServerName www.example.com
ProxyPass /socket.io/ http://127.0.0.1:5000/socket.io/
ProxyPassReverse /socket.io/ http://127.0.0.1:5000/socket.io/
# Other Apache configuration for frontend, etc.
</VirtualHost>
This would allow Apache to forward Socket.io traffic to a local eventlet server running on port 5000.
5. Check if async_mode
is set correctly
While you're initializing socketio.Server()
, make sure async_mode
is set correctly. For eventlet, it's typically better to leave it as None
because eventlet
works by default with the gevent
async model.
sio = socketio.Server(async_mode='eventlet', logger=True, cors_allowed_origins='http://localhost:3000')
Let me know if these steps help or if you're still facing issues!