<p>I am not able to connect a dockerized Spring Boot API managed by Kubernetes via Docker Desktop (Windows) to a local instance of Postgres. Error is as follows:</p>
<blockquote>
<pre class="lang-sh prettyprint-override"><code>org.postgresql.util.PSQLException: Connection to postgres-db-svc.default.svc.cluster.local:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
</code></pre>
</blockquote>
<p>Up until trying to connect to a local DB, everything has been working fine (external clients can connect to pods via Ingress, pods can communicate with each other, etc).</p>
<p>I think somewhere my configuration is off here.</p>
<p><strong>ConfigMap</strong></p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: 2017-12-27T18:38:34Z
  name: test-docker-config
  namespace: default
  resourceVersion: &quot;810136&quot;
  uid: 352c4572-eb35-11e7-887b-42010a8002b8
data:
  spring_datasource_platform: postgres
  spring_datasource_url: jdbc:postgresql://postgres-db-svc.default.svc.cluster.local/sandbox
  spring_datasource_username: postgres
  spring_datasource_password: password
  spring_jpa_properties_hibernate_dialect: org.hibernate.dialect.PostgreSQLDialect
</code></pre>
<p><strong>Service</strong></p>
<pre class="lang-yaml prettyprint-override"><code>kind: Service
apiVersion: v1
metadata:
  name: postgres-db-svc
spec: 
  type: ExternalName
  externalName: kubernetes.docker.internal
  ports:
  - port: 5432
</code></pre>
<p>In my hosts file, &quot;kubernetes.docker.internal&quot; is mapped to 127.0.0.1</p>
<p><strong>Deployment</strong></p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: tester
spec:
  selector:
    matchLabels:
      app: tester
  template:
    metadata:
      labels:
        app: tester
    spec:
      containers:
      - name: tester
        imagePullPolicy: IfNotPresent
        image: test-spring-boot
        resources:
          limits:
            memory: &quot;128Mi&quot;
            cpu: &quot;500m&quot;
        ports:
        - containerPort: 8080
        env:
        - name: SPRING_DATASOURCE_PLATFORM
          valueFrom:
            configMapKeyRef:
              name: test-docker-config
              key: spring_datasource_platform
        - name: SPRING_DATASOURCE_URL
          valueFrom:
            configMapKeyRef:
              name: test-docker-config
              key: spring_datasource_url
        - name: SPRING_DATASOURCE_USERNAME
          valueFrom:
            configMapKeyRef:
              name: test-docker-config
              key: spring_datasource_username
        - name: SPRING_DATASOURCE_PASSWORD
          valueFrom:
            configMapKeyRef:
              name: test-docker-config
              key: spring_datasource_password
        - name: SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT
          valueFrom:
            configMapKeyRef:
              name: test-docker-config
              key: spring_jpa_properties_hibernate_dialect
</code></pre>
<p><strong>Spring Boot application.properties</strong></p>
<pre class="lang-sh prettyprint-override"><code>spring.datasource.platform=${SPRING_DATASOURCE_PLATFORM:postgres}
spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:postgresql://localhost:5432/sandbox}
spring.datasource.username=${SPRING_DATASOURCE_USERNAME:postgres}
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD:password}
spring.jpa.properties.hibernate.dialect=${SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT:org.hibernate.dialect.PostgreSQLDialect}
</code></pre>

Anthony Pham
<p>Kubernetes with Docker runs in the same docker VM, so I'm assuming the <code>/etc/hosts</code> file that you are referring to is the one on your Windows machine.</p>
<p>I'm also assuming that you ran Postgres exposing <code>5432</code> with something like this:</p>
<pre class="lang-sh prettyprint-override"><code>docker run --name some-postgres -e POSTGRES_PASSWORD=mysecretpassword -d -p 5432:5432 postgres
</code></pre>
<p>First, <code>127.0.0.1</code> is not going to work because docker just exposes the ports on the IP address if the VM.</p>
<p>Secondly, Kubernetes will not able able to find <code>kubernetes.docker.internal</code> because the pods use <a href="https://coredns.io/plugins/kubernetes/" rel="nofollow noreferrer"><code>CoreDNS</code></a> to resolve and it has no idea about that domain.</p>
<p>I suggest you do this:</p>
<ul>
<li><p>Don't use <code>kubernetes.docker.internal</code> as it's already used by docker for its own purpose. Use something like <code>mypostgres.local</code></p>
</li>
<li><p>Get the IP address of your docker VM. Run <code>ping docker.local</code> or look under `C:\Windows\System32\drivers\etc\hosts for something like this:</p>
<pre><code>Added by Docker Desktop
10.xx.xx.xx host.docker.internal
</code></pre>
<p>or look at the output from <code>ipconfig /all</code> and find the IP from the docker desktop VM.</p>
</li>
<li><p>Use <a href="https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/#adding-additional-entries-with-hostaliases" rel="nofollow noreferrer"><code>hostAliases</code></a> in your podSpec, so that the <code>/etc/hosts</code> file is actually modified in your pod.</p>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: apps/v1
kind: Deployment
metadata:
  name: tester
spec:
  selector:
    matchLabels:
      app: tester
  template:
    metadata:
      labels:
        app: tester
    spec:
      hostAliases:
      - ip: &quot;10.xx.xx.xx&quot; # The IP of your VM
        hostnames:
        - &quot;mypostgres.local&quot;
      containers:
      - name: tester
        imagePullPolicy: IfNotPresent
        image: test-spring-boot
        resources:
          limits:
            memory: &quot;128Mi&quot;
            cpu: &quot;500m&quot;
</code></pre>
</li>
<li><p>Don't use an <code>ExternalName</code> service as those work only with CoreDNS. If you want the <code>ExternalName</code> service to work you will have to modify your <a href="https://coredns.io/plugins/kubernetes/" rel="nofollow noreferrer"><code>CoreDNS</code></a> config so that it hardcodes the entry for <code>mypostgres.local</code></p>
</li>
</ul>
<p>Note: Another option is just to run Postgresql in Kubernetes and expose it using a regular <a href="https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types" rel="nofollow noreferrer">ClusterIP</a> service.</p>
