Cannot route traffic with Minikube + ingress + Django - django

In my local development setup, I'm using Django as the webserver (a-la python manage.py runserver 8000) and I'm able to kubectl port-forward <django_pod> 8000 my traffic to my local dev machine so I can interact with my site by browsing to http://localhost:8000/testpage. I've configured my ALLOWED_HOSTS to include localhost to enable this.
However, I'd like to avoid using port-forward and go the more proper route of running my traffic through the Kubernetes ingress controller and service. On the same Minikube cluster, I have ingress configured to point certain traffic urls to a very rudimentary nginx pod to confirm that my ingress+service+pod networking is working properly. All other urls should route to my Django app. The only difference is the nginx traffic is all on port 80.
In my ingress controller logs, I can see the traffic being sent to the k8s service for my Django app:
192.168.64.1 - [192.168.64.1] - - [22/Nov/2019:03:50:52 +0000] "GET /testpage HTTP/2.0" 502 565 "-" "browser" 24 0.002 [default-django-service-8000] [] 172.17.0.5:8000, 172.17.0.5:8000, 172.17.0.5:8000 0, 0, 0 0.000, 0.000, 0.000 502, 502, 502 aa2682896e4d7a2052617f7d12b1a02b
When I look at the Django logs, I don't see any traffic hitting it.
My ingress servicePort is 8000, the django-service port is 8000 (I've just let it default to ClusterIP), the pod's spec.containers.ports.containerPort is 8000, and the process has been set to listen on port 8000 as I mentioned before.
When I check kubectl get endpoints, it correctly shows me an endpoint is connected on port 8000 (and it correctly changes to the new pods' IPs when I restart them).
I've used the following guides to try to debug:
https://kubernetes.io/docs/tasks/debug-application-cluster/debug-service/
https://medium.com/#ManagedKube/kubernetes-troubleshooting-ingress-and-services-traffic-flows-547ea867b120
My guess is it might be a problem with ALLOWED_HOSTS but I added a * wildcard to the list and it's still not working.
What is wrong with my setup?

You need to instruct the server to listen on all interfaces by running python manage.py runserver 0.0.0.0:<port>.
Django's runserver listens on the local loopback interface (localhost/127.0.0.1) by default so, if you run python manage.py runserver 8000, you can can only reach the server on port 8000 from the machine on which the server is running.
There is a lot of documentation around this, but here are just a couple examples:
About IP 0.0.0.0 in Django
http://www.holeintheceiling.com/blog/2012/06/21/django-and-runserver-0-0-0-0/

Related

Remove port from URL - Django Apache2 Gunicorn

I would like to know how to omit the port number from my URL.
I currently host a website on an Apache Ubuntu server on port 443 and redirect any http traffic to the https version of the site.
(www.mycompany.com)
However, I also run a Django server on the same Apache VPS using Gunicorn, currently on port 8000 and would like to achieve the URL of www.mycompany.com/blog
My current situation for the URL is www.mycompany.com:8000/blog
I have tried altering the ports that the Django server runs on to 443 and 80, but quickly realised the firewall won't allow that.
I am not sure what to do. Do I have to do a reverse proxy?

Nginx Proxy Manager and django with nginx

I have a stack Django+Gunicorn+nginx running in docker containers. It is accessible from outside by domain and Port, like web.example.com:1300 . Also, there is Nginx Proxy Manager (NPM) running (uses ports 80 and 443) and succesfully managing some other resources (for example nextcloud). But it doesn't proxy to my django project at port 1300, shows "502 Bad Gateway".
In the Proxy Hosts of NPM I've added config:
domain names: web.example.com
Forward Hostname / IP: nginx_docker_container_name (this way it works with other resources)
Forward Port: 1300
Other settings: tried multiple combinations without success (like with and without SSL certificates etc.)
Is it possible to proxy using NPM?
Sorry if I missed to write some information, actually I do not know what else to state.
I managed to solve the problem myself.
So, nginx in docker container serves web-site with static pages. Nginx proxy manager proxying htpp protocol to nginx and secures communication (and also works from docker container in my set-up).
My mistake was that I didn't connect those docker containers by virtual network.
Ones I put them into one network - everything works.
Then I unpublished nginx port (1300).
NPM proxy settings are "standard", e.g. no "custom location" and nothing in "Advanced" tab. Just "Forward Hostname / IP" is docker container tag and "Forward Port" is nginx port it listens to (80 by default).
With WhiteNoise , you don't need to configure nginx for django static files
❤️❤️❤️

localhost / 127.0.0.1 took too long to respond - Attempting to run Flask App

I am trying to run a Flask App locally and running into connection to localhost refused issues. My app directory structure looks something like this:
Directory
- index.py
- app.py
auth
-- init.py
Contents of `init.py`
from flask import Flask,redirect
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from werkzeug.serving import run_simple
from index import application as dashApp
#server_auth.route('/dashboard')
#login_required
def dashboard():
return redirect('/dashboard')
app = DispatcherMiddleware(server_auth,
{'/dashboard': dashApp.server})
# Change to port 80 to match the instance for AWS EB Environment
if __name__ == '__main__':
run_simple('0.0.0.0', 80, app, use_reloader=True, use_debugger=True)
I launch the App using gunicorn auth:app command.
[2022-02-11 20:57:24 -0800] [2273] [INFO] Starting gunicorn 20.1.0
[2022-02-11 20:57:24 -0800] [2273] [INFO] Listening at: http://127.0.0.1:8000 (2273)
[2022-02-11 20:57:24 -0800] [2273] [INFO] Using worker: sync
[2022-02-11 20:57:24 -0800] [2274] [INFO] Booting worker with pid: 2274
I have tried a few things to troubleshoot the issue.
netstat -avn | grep 8000
tcp4 0 0 127.0.0.1.8000 *.* LISTEN 131072 131072 2273 0 0x0100 0x00000006
Turned off the firewall, flushed dns cache, clear browser cache as mentioned in this link:
https://www.hostinger.com/tutorials/localhost-refused-to-connect-error
with limited info given, I suggest you can try a few other things:
create a simple / get API(without any decorator) and try to hit it with
breakpoint() in code to check.
Instead of gunicorn , first try to run with a normal server
python init.py
If the other answer by #Vismay doesn't work try changing your port from 80 to 8080. Since you didn't provide minimum info, Port 80 might be in use by other services
Could you try run lsof -i:80 and lsof -i:8000 to determine if they are used.
Maybe your problem is related to "# Change to port 80 to match the instance for AWS EB Environment". Assuming that you're trying to run it locally, consider that in Linux "You need root to run at port 80" (i.e. use sudo to run your server) while in Windows usually ports under 1024 are considered privileged ports and might need a similar solution. How to fix? Try using a different port for your Flask app (say, 5000).
In other case, it seems that Elastic Beanstalk only uses port 80 for inbound traffic (connection with other instances), so maybe you should try to use a different port. For example, in this part of the EB docs they just use port 8000. This seems to be the same conclusion reached in another SO question: Running Flask port 80 on Elastic-Beanstalk Worker
The ELB worker is connected to an SQS queue, by a daemon that listens to that queue, and (internally) posts any messages to http://localhost:80. Apache is listening on port 80. (...) So the solution I found, is to change which port the local daemon posts to - by reconfiguring it via a YAML config-file, it will post to port 5001, where my Flask app was running. This mean Apache can continue to handle the health-checks on port 80, and Flask can handle the SQS messages from the daemon.

How do i run django application without port number

How do i run django application without port number: i had tried Django: Run django app on server without port? but didn't work.
Web services must bind a port on a interface of the system. So, you should specify a port number to run your Django application. The default port number for HTTP is 80, for HTTPS 443. But you can use a custom port between [1-65535]:
For example;
python manage.py runserver 7000
You may try the following:
python manage.py runserver 80
or if you don't have permissions (assuming you are using Linux):
sudo python manage.py runserver 80
Then, you can access your application: http://localhost/
In general, web services need a port to run. If the port used is default http (80) or https (443) port, modern web browsers hide it from seeing in the address bar.
In a development server, you can hide the port(because you don't want to see it anymore) by assigning it to port 80 if it is not used by any other web service in the system(otherwise django will complain):
python manage.py runserver 80
In a production server, you need to use servers like Gunicorn to run your django app in the backend and a web server like Nginx or Apache to serve your backend to external world. In that case, since web servers use http/https ports, no ports will be visible in the browser.

Unable to connect to Docker container: Connection Refused

I have a war file deployed as Docker container on linux ec2. But when I try to hit the http://ec2-elastic-ip:8080/AppName, I don't get any response.
I have all the security group inbound rules set up for both http and https. So that's not a problem.
Debugging
I tried debugging by ssh-ing the linux instance. Tried command curl localhost:8080 , this is the response:
curl: (7) Failed to connect to localhost port 8080: Connection refused
Tried with 127.0.0.1:8080 but the same response.
Next thing I did was to list the Docker container: docker ps. I get:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
<ID> <ecr>.amazonaws.com/<my>-registry:2019-05-16.12-17-02 "catalina.sh run" 24 minutes ago Up 24 minutes 0.0.0.0:32772->8080/tcp ecs-app-24-name
Now, I connected to this container using docker exec -it <name> /bin/bash and tried checking tomcat logs which clearly shows that my application war is there and tomcat has started.
I ever tried checking the docker-machine ip default but this gave me error:
Docker machine "default" does not exist. Use "docker-machine ls" to list machines. Use "docker-machine create" to add a new one.
Now am stuck. Not able to debug further. The result am expecting is to access the app through the url above.
What to do? Is it something am doing wrong?
Also, to mention, the entire infrastructure is managed through terraform. I first create the base image,copy the war to webapps using DockerFile, push the registry image and finally do a terraform apply to apply any changes.
Make sure that apache is listening on all IP addresses inside the docker container, not just localhost. The IP should be like 0.0.0.0.
If any service is running inside docker and is listening to only localhost, it can only be accessed inside that container, not from the host.
You can also try to start apache with port 8080 and bind docker 8080 port with host 8080 port
docker run apache -p 8080:8080
Currently your app is working on a random host port i.e 32772, see the docker ps output .You must be able to access you app on http://ec2-ip:32772 once you allow port 32772 in security groups.
In order to make it work on host port 8080, you need to bind/expose the host port during docker run -
$ docker run -p 8080:8080 ......
If you are on ECS, ideally you should use an ALB & TG with your service.
However, if you are not using ALB etc then you can try giving a static hostPort in TD "hostPort": 8080(I haven't tried this). If it works fine, you will need to make sure to change the deployment strategy as "minimum healthy percentage = 0" else you might face port conflict issues.
If the application needs a network port you must EXPOSE it in the docker file.
EXPOSE <port> [<port>/<protocol>...]
In case you need that port to be mapped to a specific port on the network, you must define that when you spin up the new container.
docker run -p 8080:8080/tcp my_app
If you use run each image separately you must bind the port every time.
If you don't want to do this every time you can use docker-compose and add the ports directive in it.
ports:
- "8080:8080/tcp"
Supposing you added expose in the dockerfile, he full docker-compose.yml would look like this:
version: '1'
services:
web:
build:
ports:
- "8080:8080"
my_app:
image: my_app