0

I have written a Dockerfile like this:

FROM postgres:11.2-alpine
ADD ./db/postgresql.conf /etc/postgresql/postgresql.conf
CMD ["-c", "config_file=/etc/postgresql/postgresql.conf"]

It just adds custom config location to a generic Postgres image.

Now I have the following docker-compose service description

db:
  build:
    context: .
    dockerfile: ./db/Dockerfile
  environment:
    POSTGRES_PASSWORD passwordhere
    POSTGRES_USER: user
    POSTGRES_DB: db_name
  ports:
    - 5432:5432
  volumes:
    - ./run/db-data:/var/lib/db/data

The problem is I can no longer remotely connect to DB using these credentials if I add this Config option. Without that CMD line it works just fine.

If I prepend "postgres" in CMD it has the same effect due to the underlying script prepending it itself.

Gherman
  • 6,768
  • 10
  • 48
  • 75

2 Answers2

5

Provided all the files are where they need to be, I believe the only problem with your setup is that you've omitted an actual executable from the CMD -- specifying just the option. You need to actually run postgres:

CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

That should work!

EDIT in response to OP's first comment below

First, I did confirm that behavior doesn't change whether "postgres" is in the CMD or not. It's exactly as you said. Onward!

Then I thought there must be a problem with the particular postgresql.conf in use. If we could just figure out what the default file is.. turns out we can!

How to get the existing postgres.conf out of the postgres image

1. Create docker-compose.yml with the following contents:

version: "3"

services:
  db:
    image: postgres:11.2-alpine
    environment:
      - POSTGRES_PASSWORD=passwordhere
      - POSTGRES_USER=user
      - POSTGRES_DB=db_name
    ports:
      - 5432:5432
    volumes:
      - ./run/db-data:/var/lib/db/data

2. Spin up the service using

$ docker-compose run --rm --name=postgres db

3. In another terminal get the location of the file used in this release:

$ docker exec -it postgres psql --dbname=db_name --username=user --command="SHOW config_file"
               config_file
------------------------------------------
 /var/lib/postgresql/data/postgresql.conf
(1 row)

4. View the contents of default postgresql.conf

$ docker exec -it postgres cat /var/lib/postgresql/data/postgresql.conf

5. Replace local config file

Now all we have to do is replace the local config file ./db/postgresql.conf with the contents of the known-working-state config and modify it as necessary.

Database objects are only created once!

Database objects are only created once by the postgres container (source). So when developing the database parameters we have to remove them to make sure we're in a clean state.

Here's a nuclear (be careful!) option to
(1) remove all exited Docker containers, and then
(2) remove all Docker volumes not attached to containers:

$ docker rm $(docker ps -a -q) -f && docker volume prune -f

So now we can be sure to start from a clean state!

Final setup

Let's bring our Dockerfile back into the picture (just like you have in the question).

docker-compose.yml

version: "3"

services:
  db:
    build:
      context: .
      dockerfile: ./db/Dockerfile
    environment:
      - POSTGRES_PASSWORD=passwordhere
      - POSTGRES_USER=user
      - POSTGRES_DB=db_name
    ports:
      - 5432:5432
    volumes:
      - ./run/db-data:/var/lib/db/data

Connect to the db

Now all we have to do is build from a clean state.

# ensure all volumes are deleted (see above)
$ docker-compose build
$ docker-compose run --rm --name=postgres db

We can now (still) connect to the database:

$ docker exec -it postgres psql --dbname=db_name --username=user --command="SELECT COUNT(1) FROM pg_database WHERE datname='db_name'"

Finally, we can edit the postgres.conf from a known working state.

Mikhail Golubitsky
  • 590
  • 1
  • 8
  • 10
  • 1
    Like I said in other comment, it produces the same effect. – Gherman Oct 21 '19 at 19:31
  • I think this should work @Gherman. That was quite a rabbit hole. Hope that helps! – Mikhail Golubitsky Oct 21 '19 at 23:56
  • This is not an answer to the question. I want to change config file location. I already know where the file is. The location must be changed. That's because I don't want it within the volume accessible outside container. – Gherman Oct 24 '19 at 12:41
  • If you follow the directions exactly, at the end you can re-run the `docker .. SHOW config_file` command (provided earlier in the answer); it outputs `/etc/postgresql/postgresql.conf`, which is specified in your Dockerfile. – Mikhail Golubitsky Oct 24 '19 at 13:10
  • The answer does not include where you change `CMD`, though it is included in my question. That's why I misunderstood. Yes, this is a working solution. In short I should have added my setiings on top of existing ones. Should have guessed. – Gherman Oct 25 '19 at 08:55
1

As per this other discussion, your CMD command only has arguments and is missing a command. Try:

CMD ["postgres", "-c", "config_file=/etc/postgresql/postgresql.conf"]

richyen
  • 8,114
  • 4
  • 13
  • 28
  • This has exactly the same effect. Actually the underlying shell-script in `ENTRYPOINT` prepends `postgres` if it's absent. In fact I can access db from inside the container but not outside. And `SHOW config_file;` returns the correct config. – Gherman Oct 21 '19 at 19:29
  • can you paste the contents of your custom `postgresql.conf` somewhere? What is the `listen_addresses` setting? – richyen Oct 21 '19 at 20:56