I have a Django application that talks to a Postgresql database running in a remote Kubernetes cluster. There is a docker-compose.yml
file for local development. For Kubernetes deployment, I have a simple deployment.yaml
file for the Django Application and I'm using the helm chart from bitnami for Postgresql deployment.
I want to be able to connect to the Postgresql instance from within the Docker container running the Django API. Now, when I do a port-forward to the Postgresql instance I can connect to the database from my local machine using psql
or other tools. From what I've found, to be able to access services running on localhost from within a container, you need to access it through host.docker.internal
.
I've added the extra_hosts
parameter in my docker compose file and can access services running on my local machine just fine. However, I can't connect to the port-forwarded Postgresql instance from within the Django API container. It seems that I can't connect to any port-forwarded service from the container this way. Am I doing something wrong or is this the expected behavior?
kubectl port-forward
is normally intended as a developer or debugger tool; it doesn't see itself as the "normal" way to access services that are in the cluster. One consequence of this is that, by default, it listens on only the 127.0.0.1 (host) localhost interface.
You can fix this, specifically on a native-Linux host not running Docker Desktop, by setting kubectl port-forward
to listen on all host interfaces
kubectl port-forward --address 0.0.0.0 service/some-name-postgresql 5432
If you're using Docker Desktop (as in for example this question) then everything Docker-related runs inside a hidden Linux virtual machine. For calls out of that VM, whether to host.docker.internal
or to the broader Internet, Docker Desktop needs to run a proxy to forward those requests out of the VM. Since this proxy is on the host, it can also reach things that listen on 127.0.0.1. (This is also related to host networking not working inside the container: the "host" is actually the Linux VM.)
But if you're using the core Docker engine directly on a native-Linux host, Docker just uses the Linux iptables subsystem to forward packets around. If you look around with debugging tools, docker network inspect
might show you that the Compose default
network is 172.18.0.0/16, and on the host there might be a docker1
interface with IPv4 address 172.18.0.1 on that network.
This means, from a Unix networking point of view, that the request is coming from the docker1
interface, but the kubectl port-forward
is bound only to the lo0
(localhost) interface. It doesn't match, and that's why you get a "connection refused" error. Changing the port-forward to listen on all interfaces removes this restriction.