Postgres on Docker. How can I create a database and a user? - postgresql

I'm trying to create simple postgres server with docker. I use the official postgres image as a base for my container.
My Dockerfile contains these commands:
FROM postgres
USER postgres
RUN /etc/init.d/postgresql start &&\
psql --command "CREATE USER user WITH SUPERUSER PASSWORD 'user';" &&\
createdb -O user app
And when I try to run it I have an error:
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
What I'm doing wrong?

It's possible that it takes some time for postgres to start accepting connections. The way you've written it, it will call CREATE USER immediately after the start function returns. Try putting a sleep in there and see if it's still a problem.

Use pg_ctl with the -w flag so the command will finish when the server has started. No more wondering about whether we have waited long enough. And we can actually stop the server the same way
sudo -u postgres pg_ctl start -w -D ${PGDATA}
sudo -u postgres psql --command "CREATE USER user WITH SUPERUSER PASSWORD 'user';" &&\
sudo -u postgres createdb -O user app
sudo -u postgres pg_ctl stop -w

Had the same problem inside a script in entry point. Following is my Dockerfile excerpt
# init execution
ENTRYPOINT ["/usr/local/sbin/initpostgres.sh"]
with following commands inside the intipostgres.sh script
su postgres -c "pg_ctl start -l /var/lib/postgresql/logpostgres"
su postgres -c "createuser -s $OPENERPUSER"
adding sleep 1 before the createuser command per #seanmcl suggested correction worked for me :
su postgres -c "pg_ctl start -l /var/lib/postgresql/logpostgres"
sleep 1
su postgres -c "createuser -s $OPENERPUSER"

The problem seems to be that the postgres unix socket is not on your host machine. You can fix this by running the following command.
docker run -p 5432:5432 --volume="/run/postgresql:/run/postgresql" -d --name postgres postgres
The essential part is the --volume flag. It links the folder that includes the unix socket file .s.PGSQL.5432 to the host machine in order to be read by other processes.
This seems like a duplicate question of Installing PostgreSQL within a docker container, is that right OP?

Related

Psql can not connect to server, password authentication failed for user postgres

I know this has been asked a lot before but none of the other answers have helped. I have tried changing the pg_hba.conf. I have tried altering the password for postgres with sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'postgres';". But to do that I need password for user postgres. I have tried changing password for postgres with sudo passwd postgres. It still fails authenticating. I have tried using my own password when asked for it but authentication fails.
I'm using PostgreSQL 12.2
pg_hba.conf
sudo -u postgres psql
I fixed this error by looking for live processes on the port postgres uses, port: 5432. Once these processes are killed postgres worked.
So..
lsof -i :5432 to print any current processes that may be running as well as their PID
kill -9 <PID> to kill the process.
initdb testdb to test
NOTE: Running GUI's for postgres will take up these processes and will restart them even if you kill the process on the certain PID. Close any giu's.
If this doesn't work I suggest checking launch daemons
sudo launchctl list | fgrep postgres to print out the daemon
sudo launchctl stop <printed process name>
initdb testdb to test

executing a .sql file through ubuntu command line for postgres

I have installed postgresql on ubuntu using:
$ sudo apt install postgresql
Now, I have a series of sql queries I would like to fire to create schemas and users and tables etc. I have put those queries in a .sql file as below:
$ sudo nano postgressetup.sql
CREATE SCHEMA schma;
CREATE USER a2i WITH PASSWORD 'password';
GRANT CONNECT ON DATABASE postgres TO schma;
This file has all the queries. I tried something like:
$ psql -U postgres -d postgres -a -f postgressetup.sql
and received error:
psql: FATAL: Peer authentication failed for user "postgres"
I want to know the way I can execute this .sql file.
Note: I've just installed postgres and no further operation is done on it. Any help is appreciated.
You can use the following command explicitly providing db context user
sudo -u postgres psql -U postgres -d postgres -a -f postgressetup.sql

Modifying postgresql.conf through shell?

I want to modify a postgresql.conf parameter through the shell. From the documentation I can see that I can use the postgres command with the -c flag.
However, on my attempt, for example,
postgres -c autovacuum=off
postgres returns:
Execution of PostgreSQL by a user with administrative permissions is not permitted.
The server must be started under an unprivileged user ID to prevent possible system security compromises. See the documentation for more information on how to properly start the server.
How can I overcome this or what is the correct procedure? Also, I don't really mind for security compromises.
Given the differences on the underlying OS, I usually prefer to do this via PostgreSQL itself, which comes handy when you're dealing with a managed service that do not give you filesystem access, like so:
sudo -u postgres psql -U postgres -d database_name -c "alter system set postgresql_parameter = 'new_value';"
As an example when I have to install TimeScaleDB extension, I can do:
sudo -u postgres psql -U postgres -d database_name -c "alter system set shared_preload_libraries = 'timescaledb';"
sudo service postgresql restart
sudo -u postgres psql -U postgres -d database_name -c "create extension if not exists timescaledb;"

Error building docker image while trying to import sql dump to postgres container

I'm making a Dockerfile for an application that connects to a postgres container inside the same docker network. To populate the database, inside the Dockerfile I first install the postgres client and all the dependencies and then try to execute the sql dump like this:
RUN apt-get install python python-dev libpq-dev postgresql-client
RUN psql -h $SQL_HOST -U $SQL_USER -W $SQL_DB < some_dump.sql
I get this error:
The command '/bin/sh -c psql -h $SQL_HOST -U $SQL_USER -W $SQL_DB < some_dump.sql' returned a non-zero code: 2
The variable $SQL_HOST has the name of the docker container, which I can ping postgres with no problem.
When I manually set up the container, I can execute with no problem the following:
psql -h $SQL_HOST -U $SQL_USER
postgres=#
Or even this:
/bin/sh
> psql -h $SQL_HOST -U $SQL_USER
postgres=#
But I get an error when I try to connect to postgres (I'm guessing) the way docker does when building the image:
/bin/sh -c psql -h $SQL_HOST -U $SQL_USER
Error message:
psql: could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?
Any ideas of why I get this error? My guesses were that the env vars were not available in the /bin/sh shell, but it's not the case. I even pinged postgres inside the /bin/sh shell and succeeded.
It was pretty obvious, docker can't identify hosts of other containers when building the image, it is until you execute the docker run --net <network> that you can communicate with other containers.

How to properly set VOLUME and CMD instructions in Postgres Dockerfile?

I have a working Postgres Dockerfile that I modify and unfortunately after applying modifications Postgres container stops working as expected. I'd like to ask your for explanation of what I'm doing wrong.
Working example
Here's the Postgres Dockerfile that works and which I modify:
# Use ubuntu image
FROM ubuntu
# Install database
RUN apt-get update && apt-get install -y postgresql-9.3
# Switch to postgres user.
USER postgres
# Create databse and user with all privileges to the database.
RUN /etc/init.d/postgresql start && \
psql --command "CREATE DATABASE docker;" && \
psql --command "CREATE USER docker WITH SUPERUSER PASSWORD 'docker';" &&\
psql --command "GRANT ALL PRIVILEGES ON DATABASE docker TO docker;"
# Allow remote connections to the database.
RUN echo "host all all 0.0.0.0/0 md5" >> /etc/postgresql/9.3/main/pg_hba.conf
RUN echo "listen_addresses='*'" >> /etc/postgresql/9.3/main/postgresql.conf
# Add VOLUMEs to allow backup of config, logs and databases
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]
# Set the default command to run when starting the container
CMD ["/usr/lib/postgresql/9.3/bin/postgres", "-D", "/var/lib/postgresql/9.3/main", "-c", "config_file=/etc/postgresql/9.3/main/postgresql.conf"]
I build it like that:
docker build --tag postgres-image .
Then I create a container:
docker run -d -it -p 32768:5432 --name=postgres postgres-image
And I connect with database:
psql -h localhost -p 32768 -d docker -U docker --password
First modification
I don't need to have any volumes because I'm going to use data-only container that will store all Postgres data. When I remove the line:
VOLUME ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]
and do all steps like in working example I get the following error after passing password in the last step:
psql: FATAL: the database system is starting up
FATAL: the database system is starting up
So the question is: Why do I need VOLUME instruction in the Dockerfile?
Second modification
This modification doesn't include the first one. Both modification are independent.
The parameters used in CMD instraction points to default Postgres data directory and configuration file so I wanted to simplify it by setting CMD to the command I always use to start Posgres:
service postgres start
After setting CMD to:
CMD ["service", "postgres", "start]
and doing all steps like in working example I get the following error after passing password in the last step:
psql: 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 32768?
The question is: Why the command that works on my host system doesn't work in Docker container?
I'm not sure about the first problem. It may be that Postgres doesn't like running on top of the UFS.
The second problem is just that a container will exit when its main process ends. So the command "service postgres start" runs, starts Postgres in the background then immediately exits and the container halts. The first version works because Postgres stays running in the foreground.
But why are you doing this? Why not just use the official Postgres image?