12

I'm new to Postgres.

I updated the Dockerfile I use and successfully installed Postgresql on it. (My image runs Ubuntu 16.04 and I'm using Postgres 9.6.)

Everything worked fine until I tried to move the database to a Volume with docker-compose (that was after making a copy of the container's folder with cp -R /var/lib/postgresql /somevolume/.)

The issue is that Postgres just keeps crashing, as witnessed by supervisord:

2017-07-26 18:55:38,346 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:39,355 INFO spawned: 'postgresql' with pid 195
2017-07-26 18:55:40,430 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:40,763 INFO exited: postgresql (exit status 1; not expected)
2017-07-26 18:55:41,767 INFO spawned: 'postgresql' with pid 197
2017-07-26 18:55:42,841 INFO success: postgresql entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2017-07-26 18:55:43,179 INFO exited: postgresql (exit status 1; not expected)
(and so on…)

Logs

It's not clear to me what's happening as /var/log/postgresql remains empty.

chown?

I suspect it has to do with the user. If I compare the data folder inside the container and the copy I made of it to the volume, the only difference is that the original is owned by postgres while the copy is owned by root.

I tried running chown -R postgres:postgres on the copy. The operation was performed successfully, however postmaster.pid remains owned by root and I think that would be the issue.

Questions

  • How can I get more information about the cause of the crash?
  • How can I make it so that postmaster.id be owned by postgres ?
  • Should I consider running postgres with root instead?

Any hint welcome.


EDIT: links to the Dockerfile and the docker-compose.xml.

Fabien Snauwaert
  • 4,995
  • 5
  • 52
  • 70
  • 1
    If possible please can you add you `docker-compose.yml` and `Dockerfile` it will help a lot to understand your problem. – vedarthk Jul 26 '17 at 20:02
  • 2
    from the files it looks like you are trying to run everything in one container, I would suggest you to separate each process that you want to run into separate container. Also for PosgreSQL data, I would suggest you to dump SQL and restore it, or su to postgres and take the backup. – vedarthk Jul 29 '17 at 04:35
  • Any .pid file can be safety removed as long the application is not running. Just do it and try again. Also you have a typo here: "however postmaster.pid remains owned by **postgres**" you meant to say **root** – Robert Jul 29 '17 at 13:14
  • @Robert Thank you fixed the typo. The .pid keeps disappearing and reappearing as postgres keeps crashing and rebooting. – Fabien Snauwaert Jul 29 '17 at 20:43
  • http://stackoverflow.com/help/mcve (in particular, see the minimal section) – BMitch Jul 29 '17 at 21:23
  • @FabienSnauwaert, are you sure that the directory structure inside volume is correct? You are mounting to `/var/lib/postgresql/9.6/main`. I always use this for simplicity: `/var/lib/postgresql` – Robert Jul 29 '17 at 21:26
  • There is 2 rules on data directory : The user need to be postgres ( or the name on postgres.conf file) AND permission is 700. If you use volume usually you need to declare a level before. For instance, postgres image declare data in "/var/lib/postgresql/data/pgdata" you need to map the volume to /var/lib/postgresql/data and setup a pgdata directory with correct permission on it. – wargre Jul 31 '17 at 13:43
  • What does your supervisord.conf look like? Doesn't that task handle starting up your postgresql server. Is it setup to use the postgres user? – Ed Mendez Jul 31 '17 at 19:44
  • @vedarthk: what's the benefit of using a multi-container approach for a local development platform? – Fabien Snauwaert Aug 01 '17 at 13:18
  • @Robert: using the default directory (`data_directory = '/var/lib/postgresql/9.6/main'` set in postgresql.conf) – Fabien Snauwaert Aug 01 '17 at 13:19
  • @EdMendez: supervisord.conf includes `user=postgres` for the `[program:postgresql]` section. I wonder if I wouldn't be better off configuring the image to allow root to run it instead, since it seems root is going to bind the Docker volume to the host's directory. I'd love to know if anyone got persistent data for Postgres inside Docker and how they configured it. @all: thanks for the replies. I'll work on that minimal example. – Fabien Snauwaert Aug 01 '17 at 13:25
  • Try this in the container bash: `supervisorctl tail postgresql` – Robert Aug 01 '17 at 13:29
  • 1
    what command are you running in supervisor for postgres? what error do you get if you run it manually inside the container? – Miguel Marques Aug 01 '17 at 16:01

4 Answers4

6

I'll answer my own question:

Logs & errors

What made matters more complicated was that I was not getting any specific error message.

To change that, I disabled the [program:postgresql] section in supervisord and, instead, started postgres manually from the command-line (thanks to Miguel Marques for setting me on the right track with his comment.)

Then I finally got some useful error messages:

2017-08-02 08:27:09.134 UTC [37] LOG:  could not open temporary statistics file "/var/run/postgresql/9.6-main.pg_stat_tmp/global.tmp": No such file or directory

Fixing the configuration

I fixed the error above with this, eventually adding them to my Dockerfile:

mkdir -p /var/run/postgresql/9.6-main.pg_stat_tmp
chown postgres.postgres /var/run/postgresql/9.6-main.pg_stat_tmp -R

(Kudos to this guy for the fix.)

To make the data permanent, I also had to do this, for the volume to be accessible by postgres:

mkdir -p /var/lib/postgresql/9.6/main
chmod 700 /var/lib/postgresql/9.6/main 

I also used initdb to initialize the data directory. BEWARE! This will erase any data found in that folder. Like so:

rm -R /var/lib/postgresql/9.6/main/*
ls /var/lib/postgresql/9.6/main/
/usr/lib/postgresql/9.6/bin/initdb  -D /var/lib/postgresql/9.6/main

Testing

After the above, I could finally run postgres properly. I used this command to run it and test from the command-line:

su postgres
/usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf # as per the Docker docs

To test, I kept it running and then, from another prompt, checked everything ran fine with this:

su postgres
psql
CREATE TABLE cities ( name varchar(80), location point );
INSERT INTO cities VALUES ('San Francisco', '(-194.0, 53.0)');
select * from cities; # repeat this command after restarting the container to check that the data does persist

…making sure to restart the container and test again to check the data did persist.

And then finally restored the [program:postgresql] section in supervisord, rebuilt the image and restarted the container, making sure everything ran fine (in particular supervisord: tail /var/log/supervisor/supervisord.log), which it did.

(The command I used inside of supervisord.conf is also /usr/lib/postgresql/9.6/bin/postgres -D /var/lib/postgresql/9.6/main -c config_file=/etc/postgresql/9.6/main/postgresql.conf, as per this Docker article and other postgres+supervisord examples. Other options would have been using pg_ctl or an init.d script, but it's not clear to me why/when one would use those.)


I spent a lot of time on this. Hopefully the detailed answer will help someone down the line.

P.S.: I did end up producing a minimal example of my issue. If that can help anyone, here they are: Dockerfile, supervisord.conf and docker-compose.yml.

Fabien Snauwaert
  • 4,995
  • 5
  • 52
  • 70
3

I do not know if this would be another way to achieve the same result (I'm new on Docker and Postgres too), but have you try the oficial repository image for Postgres (https://hub.docker.com/_/postgres/)?

I'm getting the data out of the container setting the environment variable PGDATA to '/var/lib/postgresql/data/pgdata' and binding this to an external volume on the run command:

docker run --name bd_TEST --network=my_network --restart=always -e POSTGRES_USER="superuser" -e POSTGRES_PASSWORD="myawesomepass" -e PGDATA="/var/lib/postgresql/data/pgdata" -v /var/local/db_data:/var/lib/postgresql/data/pgdata -itd -p 5432:5432 postgres:9.6

When the volume is empty, all the files are created by the image startup script, and if they already exist, the database start to used it.

1

From past experience I can see what may be a problem. I can't say if this will help but it is worth a try. I would have added this as a comment, but I can't because my rep isn't hight enough.

I've spied a couple problems with how you have structured your statements in your Dockerfile. You have installed various things multiple times and also updated sporadically through the code. In my own files i've noticed that this can lead to somewhat random behaviour of my services and installation because of the different layers.

This may not seem to solve your problem directly, but cleaning up your file as is outlined in the best practices has solved many Dockerfile problems for me in the past.

One of the first places upon finding such problems is to start here at the best practices for RUN. This has helped me solve tricky problems in the past and I hope it'll solve or at least make it easier.

Pay special attention to this part:

After building the image, all layers are in the Docker cache. Suppose you later modify apt-get install by adding extra package:

 FROM ubuntu:14.04
 RUN apt-get update
 RUN apt-get install -y curl nginx 

Docker sees the initial and modified instructions as identical and reuses the cache from previous steps. As a result the apt-get update is NOT executed because the build uses the cached version. Because the apt-get update is not run, your build can potentially get an outdated version of the curl and nginx packages.

After reading this I would start by consolidating all your dependencies.

Archernar
  • 463
  • 5
  • 6
0

In my case, having the same error, I debugged it until I found out:

the disk was full and I increased the diskspace to solve this.

(stupid error, easy fix - maybe reading this here helps someone not wasting time)

also linking this questiong for other options:

MacMartin
  • 2,366
  • 1
  • 24
  • 27