21

I have a Springboot app that I have Dockerized. I have it exposed on port 8081, and can access it as expected.

http://<ipaddress>:8081

Problem

The Springboot app in the docker container needs to connect to a postgres database on the same host (not in a container), but it appears like it does not gave access to the host network.

Connection to localhost:5432 refused

Docker cmd:

docker run -t --rm -d -p 8081:8081 --name nexct-approval-service-container nexct-approval-service-image

So I have read in order to connect to the network, you can use:

--network host 

However, then it stops allowing access to the application itself (port 8081):

WARNING: Published ports are discarded when using host network mode

Question

How can I allow access to the SpringBoot app on port 8081 and allow the Springboot app access to the host network so it can connect to the database?


UPDATE

My database connection is defined in Spring Boot:

application.properties

spring.datasource1.driver-class-name=org.postgresql.Driver
spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/pims
spring.datasource1.username=postgres
spring.datasource1.password=

MultipleDBConfig.java

@Configuration
@ComponentScan(basePackages = "com.nexct")
public class MultipleDBConfig {

    @Bean(name = "datasource1")
    @ConfigurationProperties("spring.datasource1")
    @Primary
    public DataSource dataSource1(){
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "datasource2")
    @ConfigurationProperties("spring.datasource2")
    public DataSource dataSource2(){
        return DataSourceBuilder.create().build();
    }
}
bathyscapher
  • 1,615
  • 1
  • 13
  • 18
Richard
  • 8,193
  • 28
  • 107
  • 228
  • 2
    have you checked this link: https://stackoverflow.com/questions/28056522/access-host-database-from-a-docker-container – mangusta Jul 24 '20 at 07:17
  • Also [From inside of a Docker container, how do I connect to the localhost of the machine?](https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach?rq=1). – David Maze Jul 24 '20 at 11:05
  • Link suggested by @mangusta above does seem to work. Essentially services on the host are accessible via the host ip. Using ifconfig or ipconfig you can find the host ip and then the same. – sandeepkunkunuru Aug 26 '23 at 17:34

3 Answers3

17

In my service, I replaced the references to localhost with host.docker.internal, and I was able to publish the container's ports with -p and connect to services on localhost without having to use --network host. My services references a .env file that has the hostnames, so I just created another .env file with the updated hostname.

user2233706
  • 6,148
  • 5
  • 44
  • 86
  • How did you replace the reference to localhost. did you run command. `host.docker.internal` – palamuGuy Jul 23 '23 at 17:54
  • The .env file had the reference to `localhost`, so I just replaced that. The code used the environment variable that pointed to the appropriate domain name. – user2233706 Jul 24 '23 at 00:00
13

You can not publish port in the network mode host.

Note: Given that the container does not have its own IP-address when using host mode networking, port-mapping does not take effect, and the -p, --publish, -P, and --publish-all option are ignored, producing a warning instead:

host networking

How can I allow access to the SpringBoot app on port 8081 and allow the Springboot app access to the host network so it can connect to the database?

Still, you can not reach to Host network by assigning host network to the container. To reach host Network you can use Host IP or use special DNS for mac and window.

host.docker.internal:DB_PORT

Or you can use Host IP if you are on linux

HOST_IP:DB_PORT

or you can try (works on ubuntu)

docker run -it --rm -e HOST_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p') image_name

Now use HOST_IP as a host name in your application.

Adiii
  • 54,482
  • 7
  • 145
  • 148
  • thanks for the answer. I am on a Linux machine. Where to I configure `HOST_IP:DB_PORT`? on the `docker run` cmd? – Richard Jul 24 '20 at 07:22
  • 1
    That's your host IP. Use `ifconfig`or `hostname -I`. You may have more than one (such as one for ethernet and one for wifi). Note that your DB server must listen on this IP or `0.0.0.0` (all hosts), otherwise you may not be able to connect (if DB listen on `localhost` you won't for instance) – Pierre B. Jul 24 '20 at 07:30
  • yes Agree @PierreB, also you can try `$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')` it worked for me – Adiii Jul 24 '20 at 07:33
  • I am still confused (excuse my ignorance). Where do I set the IP? On the `docker run` command? How? – Richard Jul 24 '20 at 07:36
  • 1
    `docker run -it --rm -e HOST_DB=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p') image_name` see this, passing IP to ENV `HOST_DB` and use this env in the application to connect with `DB` or use `IP` in the application if you do not want to set in run command. – Adiii Jul 24 '20 at 07:38
  • Thanks, I have tried that but get `PSQLException: Connection to localhost:5432 refused` still. Is that because the database is on `localhost`? My full docker cmd: `docker run -t --rm -e HOST_DB=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p') -p 8081:8081 --name nexct-approval-service-container nexct-approval-service-image` – Richard Jul 24 '20 at 07:47
  • How is your DB base connection look like? it should `getenv.HOST_DB` seems like you are still not using valid value in code? – Adiii Jul 24 '20 at 07:48
  • I have made an update to the original question above. I am storing the database config in the Spring `application.properties`. – Richard Jul 24 '20 at 07:50
  • 1
    Replace localhost to ip return by `ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p'` applications properties – Adiii Jul 24 '20 at 08:11
  • I change the application.properties to: `spring.datasource1.jdbc-url=jdbc:postgresql://:5432/pims` and the docker cmd: `docker run -t --rm -p 8081:8081 --name nexct-approval-service-container nexct-approval-service-image`. I get the following error when Spring tries to connect to the database: `NoRouteToHostException: No route to host`. – Richard Jul 24 '20 at 08:20
5

You should change : localhost in connection string to :

172.17.0.1 its an IP address of containers network

Then check again.

Thanh Nguyen Van
  • 10,292
  • 6
  • 35
  • 53
  • Thanks, I gave that a try, but now the SpringBoot app throws the following exception. `java.net.NoRouteToHostException: No route to host`. and. `org.postgresql.util.PSQLException: The connection attempt failed.` – Richard Jul 24 '20 at 08:00
  • on the host machine, try to telnet : telnet 172.17.0.1 5432 , to see its opened or not ?make sure postgres that is listening on host machine. – Thanh Nguyen Van Jul 24 '20 at 08:01
  • `$ telnet 172.17.0.1:5432` gives me: `telnet: 172.17.0.1:5432: Name or service not known 172.17.0.1:5432: Unknown host` – Richard Jul 24 '20 at 08:02
  • without `:` in the between – Thanh Nguyen Van Jul 24 '20 at 08:02
  • `$ telnet 172.17.0.1 5432` gives: `Trying 172.17.0.1... Connected to 172.17.0.1. Escape character is '^]'.` then after a while `Connection closed by foreign host.` – Richard Jul 24 '20 at 08:03
  • it's open, remove `--network host ` in the dockerfile and run again – Thanh Nguyen Van Jul 24 '20 at 08:04
  • If I remove `--network host` then I can access the rest api on port 8081. But when the Spring Boot app tries to connect to the database, I get `connection refused` (if `spring.datasource1.jdbc-url=jdbc:postgresql://localhost:5432/pims`). However, if `spring.datasource1.jdbc-url=jdbc:postgresql://172.17.0.1:5432/pims`, then I get `No route to host`. – Richard Jul 24 '20 at 08:08
  • 2
    can you do the command : `docker inspect container_id` then get : `"Gateway": "x.x.x.x"`, replace x.x.x.x to 172.17.0.1 – Thanh Nguyen Van Jul 24 '20 at 08:10
  • How do I know what the container_id is? I try the following: `docker inspect nexct-approval-service-container` and get: `Error: No such object: nexct-approval-service-container` – Richard Jul 24 '20 at 08:12
  • If I inspect the image id (`docker inspect d19bc10c50bc`), I get a lot of output. – Richard Jul 24 '20 at 08:14
  • ` "Container": "817796160b6609ca3bad59f5bfb641771846a2fd26e5ee3531ddfb5d478df4f6", "ContainerConfig": { "Hostname": "817796160b66", "Domainname": "", "User": "", "AttachStdin": false, "AttachStdout": false, "AttachStderr": false, "ExposedPorts": { "8081/tcp": {}` – Richard Jul 24 '20 at 08:15
  • if you are using Mac for running the container, please refer to the first answer – Thanh Nguyen Van Jul 25 '20 at 05:52