Accessing PostgreSQL on docker container from pgAdmin4 in another docker container - postgresql

I have a PostgreSQL instance running on a docker with these commands:
mkdir -p $HOME/vols/postgres
docker pull postgres:12.0
docker run --rm --name pg-docker -e POSTGRES_PASSWORD=docker \
-v $HOME/vols/postgres:/var/lib/postgresql/data \
-d -p 5432:5432 postgres
It's up and running and I can access it from DBeaver which is installed on my local-machine. Also, I've installed pgAdmin4 by these commands:
mkdir -p $HOME/vols/pgadmin4
docker pull dpage/pgadmin4
docker run --rm --name pgadmin4 -p 5050:80 \
-v $HOME/vols/pgadmin4:/var/lib/pgadmin \
-e 'PGADMIN_DEFAULT_EMAIL=amiry#manexapp.com' \
-e 'PGADMIN_DEFAULT_PASSWORD=12345678' \
-d dpage/pgadmin4
The pgAdmin is also up and running well and I can easily access it and login to it through http://localhost:5050.
But when I want to connect to my postgre-container instance via pgAdmin4-container instance, I get this error:
Unable to connect to server:
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: Address not available Is the
server running on host "localhost" (::1) and accepting TCP/IP
connections on port 5432?
Does anybody has an idea what's going wrong here please? Thanks in advance.
NOTE: My host machine is Fedora 31.

Inside a container, the loopback address (localhost or 127.0.0.1) refers to "this container". When you try to connect to 127.0.0.1 inside the pgAdmin4 container, it fails because your Postgres service is not running inside the pgAdmin4 container.
The easiest way to make this work is to put both of your containers on a user defined network, in which case they can simply refer to each other by name.
Start by creating a network:
docker network create dbnet
Then launch the postgres container on that network:
docker run --rm --name pg-docker -e POSTGRES_PASSWORD=docker \
--net dbnet \
-v $HOME/vols/postgres:/var/lib/postgresql/data \
-d -p 5432:5432 postgres
And finally launch the pgAdmin4 container on that network:
docker run --rm --name pgadmin4 -p 5050:80 \
--net dbnet \
-v $HOME/vols/pgadmin4:/var/lib/pgadmin \
-e 'PGADMIN_DEFAULT_EMAIL=amiry#manexapp.com' \
-e 'PGADMIN_DEFAULT_PASSWORD=12345678' \
-d dpage/pgadmin4
Now when you access your pgadmin ui, you can connect to the host pg-docker instead of localhost.

UPDATE: OK. larsks added a full detailed answer with creating a custom network approach, which makes more sense. I'll try it and let you know.
OK. I recognized there is a network problem and pgAdmin4-docker cannot see pg12-docker. So, I did these steps to solve the problem:
A. Stop pgadmin4 container by:
docker stop pgadmin4
This will also delete the container, because I have ran it by --rm flag.
B. Find the network-name and IP associated to pg12-docker by running:
docker inspect pg12-docker
This will echo a large JSON-file. Find the Networks node:
"Networks": {
"bridge": {
"Gateway": "172.17.0.1",
"IPAddress": "172.17.0.2",
// other lines omitted
}
}
You will see the network-name as the first child of JSON (bridge in this example) and also the IPAddress. Note theme somewhere.
C. Re-run the pgAdmin4-docker again with --network [NetworkName] parameter; replace [NetworkName] with the name you got in previous step (bridge in this example).
docker run --rm --name pgadmin4 -p 5050:80 --network bridge \
-v $HOME/vols/pgadmin4:/var/lib/pgadmin \
-e 'PGADMIN_DEFAULT_EMAIL=amiry#manexapp.com' \
-e 'PGADMIN_DEFAULT_PASSWORD=12345678' \
-d dpage/pgadmin4
D. Access (or refresh) http://localhost:5050 and login to it. In Add server section, use the IPAddress you got in step B. and you are good to go.

Using
host.docker.internal
instead of localhost

Related

How to connect to postgresql in docker

I have a postgresql db running in a docker container on my machine. I started it with this run command.
docker run -p 5432:5432 -d \
-e POSTGRES_PASSWORD=$PG_PASS \
-e POSTGRES_USER=$PG_USER \
-e POSTGRES_DB=$PG_NAME \
-v pgdata:/var/lib/postgresql/data \
--name $PG_CONTAINER_NAME \
postgres:alpine
I have confirmed that this created the db using the environment variables by also running a pgadmin4 container and connecting to this container using its container name.
Now I am trying to connect my express app to the db. I am using a orm called mikroorm. The ts code is
const orm = await MikroORM.init({
dbName: 'ketopal',
user: 'ketopaladmin',
password: 'ketopaladmin',
type: 'postgresql',
debug: !__prod__,
entities: [Post],
host: '172.17.0.2',
port: 5432
})
This produces a one line error,
MikroORM failed to connect to database ketopal on postgresql://ketopaladmin:*****#172.17.0.2:5432
But I don't know why or how to fix it. 172.17.0.2 is the IP docker gave to the container.
In my perfect world, you all could tell me how to get docker to make localhost:5432 point to the docker container, but any help would be appreciated.
Thought I'd document here incase someone also runs into this. I had a local postgres process running on port 5432, so when I attempted to "publish" the container to that same port, it failed to do so, even though it created the container and was otherwise working. I adjusted the run command to map port 54321 to 5432.
docker run -p 54321:5432 -d \
-e POSTGRES_PASSWORD=$PG_PASS \
-e POSTGRES_USER=$PG_USER \
-e POSTGRES_DB=$PG_NAME \
-v pgdata:/var/lib/postgresql/data \
--name $PG_CONTAINER_NAME \
postgres:alpine
TLDR; If you have something running that already claimed a port, running a container on that port won't work.

PostgreSQL and pgAdmin both running in Docker containers and connecting

I am attempting to run both PostgreSQL and pgAdmin in Docker containers. The idea is that the PostgreSQL database should be accessible to any applications I have running on the host machine, and also to pgAdmin.
I am using this command to run PostgreSQL:
docker run -d -e POSTGRES_USER=username -e POSTGRES_PASSWORD=password --name postgres -p 5432:5432 postgres
And to run pgAdmin:
docker run -d -p 1111:1111 --name pgadmin -e "PGADMIN_LISTEN_PORT=1111" -e "PGADMIN_DEFAULT_EMAIL=admin#test.com" -e "PGADMIN_DEFAULT_PASSWORD=test" dpage/pgadmin4
If I go to localhost:1111, I can connect to pgAdmin and login. However, when I try to connect to my local PostgreSQL instance, it gets no response.
Therefore, I tried to run pgAdmin with access to the host internet using --net=host instead of -p 1111:1111:
docker run -d --net=host --name pgadmin -e "PGADMIN_LISTEN_PORT=1111" -e "PGADMIN_DEFAULT_EMAIL=admin#test.com" -e "PGADMIN_DEFAULT_PASSWORD=test" dpage/pgadmin4
Now, when I try to go to localhost:1111 to connect to pgAdmin, I get no response in my browser.
Docker Compose is a possible solution, as I could link the two containers together so they could access each other without having to worry about ports, but I also need pgAdmin to be able to access PostgreSQL instances on other machines, as well as my local one.
I feel like --net=host is broken in Docker. There's a whole thread here with a lot of confusion.
My setup:
Host: Windows 10
Docker: Docker Desktop Community v2.0.0.3 (31259)
Update
I have now tried using --link postgres on the pgAdmin container and it allows me to connect to my local instance of PostgreSQL but not non-local ones, the full command is:
docker run -d -p 1111:1111 --link postgres --name pgadmin -e "PGADMIN_LISTEN_PORT=1111" -e "PGADMIN_DEFAULT_EMAIL=admin#test.com" -e "PGADMIN_DEFAULT_PASSWORD=test" dpage/pgadmin4
The commands were not wrong, only the connection in pgAdmin, so the full list of commands are:
For PostgreSQL:
docker run -d -e POSTGRES_USER=username -e POSTGRES_PASSWORD=password --name postgres -p 5432:5432 postgres
And pgAdmin:
docker run -d -p 1111:1111 --name pgadmin -e "PGADMIN_LISTEN_PORT=1111" -e "PGADMIN_DEFAULT_EMAIL=admin#test.com" -e "PGADMIN_DEFAULT_PASSWORD=test" dpage/pgadmin4
Now the pgAdmin container won't connect to localhost but needs the IP of the PostgreSQL container. Run:
docker inspect postgres
Inspect result:
[
{
...
"NetworkSettings": {
...
"Networks": {
...
"IPAddress": "172.17.0.3",
...
}
}
}
]
We're only interested in the IPAddress from the inspect command. This is the IP which pgAdmin should connect to.
pgAdmin is also capable of access external IPs from your machine.
When you create docker containers it creates a bridge network. First find the network range for the bridge network. You can use ifconfig to find it. Let's say 172.17.0.5 is ip of pgAdmin, Then create a user 'root'#'172.17.0.5' for PostgreSQL and give database permissions for that user. Then you can connect to the database. Also check if port 3306 is accessible using telnet.

How can I connect to Postgres database in the container via port 5432

I am running a postgres docker container by using the commands below: (reference: https://docs.docker.com/engine/examples/postgresql_service/)
docker build -t eg_postgresql .
docker run --rm -P --name pg_test eg_postgresql
This works but the port number is dynamic. I can connect to the database by giving the port number. (the port I see in docker ps command)
I would like to connect to this docker database from Python so I need a static port number.
I tried the parameters below:
-p 127.0.0.1:5432:5432
-p 5432:5432
In that case, the docker container's port number was set as 5432. However, I could not connect to the database. I get docker user does not exist error message.
What is your advice?
I took the Dockerfile from the link you posted. After building the container with
docker build -t eg_postgresql .
I started the container with
docker run --rm -p 5432:5432 --name pg_test eg_postgresql (which binds localhost port 5432 to the container port 5432)
and then I tried to connect with
psql -h localhost -p 5432 -d docker -U docker --password
It works like a charm. If you get a message that docker user does not exist please double check that all steps from the Dockerfile are executed succesfully during the docker build command as the creation of the docker user is done in the command RUN /etc/init.d/postgresql start &&\
psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&\
createdb -O docker docker. Make also sure that you have no PostgreSQL server running on your localhost so that you can be sure that you are trying to connect to PostgreSQL inside the container.

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

can't run docker image of jhipster webapp

I have a jhipster monolithic web app with postgress database. I built a docker image using
./gradlew bootRepackage -Pprod buildDocker
Now when I try to run the image using docker run , it fails with following error.
Caused by: org.postgresql.util.PSQLException: Connection to localhost:5432 refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:247)
at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:65)
I tried few things like, but still get the same error:
docker create -v /var/lib/postgresql/data --name spring_app_data postgres:9.5.1
docker run --volumes-from spring_app_data --name spring_app_pg -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=password -d -P postgres:9.5.1
docker run -it --link spring_app_pg:postgres --rm postgres sh -c 'exec psql -h "$POSTGRES_PORT_5432_TCP_ADDR" -p "$POSTGRES_PORT_5432_TCP_PORT" -U postgres'
docker run --name spring_app_container --link spring_app_pg:spring_app_pg -p 8080:8080 -d wmd_server_pg
Any suggestions on how to run the docker image for a webapp with PostgreSQL. BTW I get same kind of error when I use mongodb.
Going by your example commands your database won't be accessible as localhost from the app, it will be via the named container. Configure your apps database connection to use spring_app_pg:5432.
Also, don't use links. Use a user defined network, most likely a bridge is all you will need.
docker network create my_app
docker run --net=my_app --name=spring_app_pg <dbimage>
docker run --net=my_app --name=spring_app_container <appimage>
That should give you the same result as your linked setup.