Access local postgres database from podman container during build - postgresql

I have a Spring Boot application that runs inside a container and needs to connect to a local Postgresql database.
Now it fails at build time, as that is the moment when it tries to configure Spring beans and to connect to database.
I have configured it like following:
spring
datasource:
initialization-mode: always
platform: postgres
url: jdbc:postgresql://192.168.122.1:5432/academy
username: myuser
password: mypassword
but it fails to connect.
How shall I configure Dockerfile/connection string?

I think you have at least two alternatives
Alternative 1: Connecting via Unix domain socket
If you could have Postgres listen on a Unix domain socket, you could then pass in that socket to the container with a bind-mount. Use podman run with one of the command-line arguments --volume or --mount.
Maybe something like:
--mount type=bind,src=/path/to/socket/on/host,target=/path/to/socket/in/container
If your system has SELINUX enabled, you would need to add the option Z
--volume /path/to/socket/on/host:/path/to/socket/in/container:Z
Alternative 2: Connecting via TCP socket
I think you could add the option
--network slirp4netns:allow_host_loopback=true
to the podman run command and connect to the IP address 10.0.2.2.
Quote "Allow the slirp4netns to reach the host loopback IP (10.0.2.2, which is added to /etc/hosts as host.containers.internal for your convenience)" from the podman run man page.
See also slirp4netns.1.md.
(The IP address 10.0.2.2 is a default value hard coded in the source code of slirp4netns).
Here is an example of a container that connects to a web server running on localhost:
esjolund#laptop:~$ curl -sS http://localhost:8000/file.txt
hello
esjolund#laptop:~$ cat /etc/issue
Ubuntu 20.04.2 LTS \n \l
esjolund#laptop:~$ podman --version
podman version 3.0.1
esjolund#laptop:~$ podman run --rm docker.io/library/fedora cur-l -sS http://10.0.2.2:8000/file.txt
curl: (7) Failed to connect to 10.0.2.2 port 8000: Network is unreachable
esjolund#laptop:~$ podman run --rm --network slirp4netns:allow_host_loopback=true docker.io/library/fedora curl -sS http://10.0.2.2:8000/file.txt
hello
esjolund#laptop:~$

Related

Postgres container does not accept connections when run host mode

I am trying to run Postgres in a container.
When I start the container using the following command wherein I map the port 5432 of my machine with that of the container, the Postgres accepts connections from another process and everything works as intended.
docker run --name postgres --rm -e POSTGRES_HOST_AUTH_METHOD=trust -p 5432:5432 -d postgres
netstat-ing the port also works well i.e
nc -z localhost 5432
Connection to localhost port 5432 [tcp/postgresql] succeeded!
Now if I use the host mode to run the postgres container, it stops accepting connections. Basically the following doesn't work:
docker run --name postgres --rm -e POSTGRES_HOST_AUTH_METHOD=trust --net=host -d postgres
I saw a similar question on StackOverflow but it doesn't explain why things don't work. Here is the link to that question:
Connection Error with docker postgres using network=host
Any ideas why the second command doesn't work are appreciated. Thank you.
I wasn't aware of the fact that host networking is not supported on mac.
A snippet from https://docs.docker.com/network/host/
The host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server.
Another related SO question:
How to tell docker on mac to use host network for all purpose?

No access to docker container's exposed port from host

when I start docker container like this:
sudo docker run -p5432:5432 -d -e POSTGRES_PASSWORD=test_pass -e POSTGRES_USER=test_user -e POSTGRES_DB=test_db --name postgres postgres:12
I can see it's started by command sudo docker ps. But when I try to connect to the container from host using
psql -Utest_user -p5432 -h localhost -d test_db
it just hangs for several minutes and then reports that wasn't able to connect.
But when I add --net host option like this:
sudo docker run --net host -p5432:5432 -d -e POSTGRES_PASSWORD=test_pass -e POSTGRES_USER=test_user -e POSTGRES_DB=test_db --name postgres postgres:12
everything starts working as expected, I can connect to the postgresql the same psql command.
The same happens to other containers which I run, not only created from postgres:12 image.
I can only make requests to them when I set --net host option.
But I need to expose different ports like for example 2000:5432 to run, for example, several postgres containers simultaneously.
What should I do to make it work? My machine is Ubuntu:20, in case if it matters, and docker is fresh new one installed by instruction from the official site yesterday.
You can't connect to database container because by default it only allows connections from the localhost ( local machines in the same network ).
When you start docker container it makes it's own network ( usually in 172.0.0.0/something ip range).
When you set the flag -net host, docker takes your host's ip address for it's own, and that's why you are able to connect to the database ( because then you are both on the same network ).
The solution is either use the -net host flag, or to edit the config file for the database container to allow external connections which is not recommended.

Quarkus native image: postgresql connection refused

I created a quarkus application with access to a postgresql database on localhost. After creating the native image I try to run the application with:
docker run -i --rm -p 8080:8080 quarkusimage
if I try a method with postman I have this result:
addEmployee
Hibernate:
select
nextval ('quarkus.hibernate_sequence')
2020-06-18 20: 43: 38,214 WARN [io.agr.pool] (Agroal_20041415421) Datasource '': Connection to localhost: 5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP / IP connections.
if i try to run the application with
docker run --net = "host" -i --rm -p 8080:8080 quarkusimage
the application accesses the database on localhost, but if I try a postman call it can't reach the service.
What am I doing wrong?
Thank you
This has to do with docker networking. When an application is run inside docker, then localhost is not the hosts localhost unless you use --net = "host".
Aside from using --net = "host", you can could use the IP of host instead of localhost in the URL.
As for the podman issue you mention, that sounds like a podman bug or limitation - I propose you consult the podman documentation and / or open an issue in the podman issue tracker.

Docker port mismatch from inside another container

I have a simple setup of 2 docker containers, one for the database and one for the web service.
I start the DB docker container like so:
docker run -d --name dbs.service -p 5434:5432 -e POSTGRES_DB=my_app -e POSTGRES_USER=my_user -e POSTGRES_PASSWORD=my_password postgres:9.6.2
This works fine. And from localhost, i can connect to it fine as well (using pgcli for connection)
pgcli postgres://my_user:my_password#dbs.service:5434/my_app
Now I start the web service container, which works fine
docker run -d --name web.service --link dbs.service:dbs.service web-service:latest
However here's the problem. From inside the container, I cannot connect to DB using port 5434 but I can connect to DB using port 5432.
So I login to container using
docker exec -it web.service bash
Now this works
pgcli postgres://my_user:my_password#dbs.service:5432/my_app
but this does not
pgcli postgres://my_user:my_password#dbs.service:5434/my_app
I can't understand why it can connect to 5432 but not 5434. Any suggestions?
-p 5434:5432
This option publishes the port for access from outside of the docker host to your container. The host will listen on 5434 and route the traffic through to the container's port 5432.
However, container-to-container traffic doesn't use that. Container to container traffic simply needs a common docker network. From there, any container can talk to any other container on the same network. The port used is the container listening port, not the published port on the host. You don't even need to publish the port for it to be accessible by other containers.

How do you send tcp/ip requests from a docker container to the host?

I'm working out how to run openproject with docker. I'm working through openproject/docker.
I've got the docker image running with an external postgres directory.
I'm now working out how to connect to an existing running instance of postgresql.
The command line I'm using looks ok according to the official documentation.
EDIT. Added in the missing -p.
docker run -p 8082:80 -p 5432:5432 --name openproject_dev -e SECRET_KEY_BASE=secret -e DATABASE_URL=postgresql://openproject:openproject-dev-
password#localhost:5432/openproject_dev \
-v /Users/admin/var/lib/openproject/logs:/var/log/supervisor \
-v /Users/admin/var/lib/openproject/static:/var/db/openproject openproject/community:5.0
I've ommitted the -d [deamon] flag so I can see any errors.
When the docker container is being created I get
-----> You're using an external database. Not initializing a local database cluster.
/usr/src/app /usr/src/app
Starting memcached: memcached.
Which I expect.
Then I get an error about connecting to the postgresql server which I don't expect.
...
PG::ConnectionBad: could not connect to server: Connection refused
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432?
could not connect to server: Cannot assign requested address
Is the server running on host "localhost" (::1) and accepting
TCP/IP connections on port 5432?
/usr/local/bundle/gems/activerecord-
4.2.7.1/lib/active_record/connection_adapters/postgresql_adapter.rb:651:in `initialize'
I'm guessing the script initialising the container is expecting postgres to be running and it's not. How would you make the docker container port forward requests to 5432 to the host machine on the command line? ... the opposite of docker run -p 5432:5432 ... which exposes 5432 from the docker container to the host.
-e DATABASE_URL=postgresql://openproject:openproject-dev-
password#localhost:5432/openproject_dev
When you add this url, the container expects postgres to be running on localhost, i.e. in itself.
If you are running postgres on your host machine, you can let the container share the network stack with the host by passing --network host in the run command. In that case, localhost will refer to the host machine where postgres is running.
Your approach is wrong currently
docker run -p 8082:80 -p 5432:5432 --name openproject_dev -e SECRET_KEY_BASE=secret -e DATABASE_URL=postgresql://openproject:openproject-dev-password#localhost:5432/openproject_dev \
-v /Users/admin/var/lib/openproject/logs:/var/log/supervisor \
-v /Users/admin/var/lib/openproject/static:/var/db/openproject openproject/community:5.0
when you used -p 5432:5432 it means that you expect something to run inside docker on that port and you want your host machine 5432 port to map to 5432 inside docker.
Next if you were able to run that command, even though nothing is listening inside container, then that would imply that the port on your host is available. This means postgress is not listening on 5432 on host also. It may be listening on a socket. You should try to execute below command on host
psql -h 127.0.0.1
If you are not able to connect on host using this that means the postgres db is bind to a socket file and not to a IP. Now you have few options that you can exercise
Mount the socket
docker run -p 8082:80 -p 5432:5432 --name openproject_dev -e SECRET_KEY_BASE=secret -e DATABASE_URL=postgresql://openproject:openproject-dev-password#localhost:5432/openproject_dev \
-v /Users/admin/var/lib/openproject/logs:/var/log/supervisor \
-v : \
-v /Users/admin/var/lib/openproject/static:/var/db/openproject openproject/community:5.0
Bind on 0.0.0.0 on host
If you don't want to mount volume then you should change the bind address of psql to 0.0.0.0 and then change your database url to -e DATABASE_URL=postgresql://openproject:openproject-dev-password#<YOURMACHINEIP>:5432/openproject_dev
Run on host network
docker run --net host --name openproject_dev -e SECRET_KEY_BASE=secret -e DATABASE_URL=postgresql://openproject:openproject-dev-password#localhost:5432/openproject_dev \
-v /Users/admin/var/lib/openproject/logs:/var/log/supervisor \
-v : \
-v /Users/admin/var/lib/openproject/static:/var/db/openproject openproject/community:5.0