Postgres: Enable configurable exposed port to run container in host networking mode on a port different than 5432

Created on 20 Sep 2016  路  9Comments  路  Source: docker-library/postgres

If running the container with --net=host, the db can only be reached on port 5432 (no ports mapping).

It would be great to have the possibility to set the port where postgres will listen to with an environment variable (an example is this image: https://github.com/mesoscloud/chronos).

Most helpful comment

The expose in the Dockerfile does nothing but tell the user what the default is; if you don't explicitly add it to your yaml file it wont matter. Here is an example of running two postgres instances in the same network namespace (the host) but running on different ports:

# edit, this is a bad example; don't run services on "net:host"
version: '3.1'
services:
  postgres1:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example1
    net: host
    command: -p 5000
  postgres2:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example2
    net: host
    command: -p 5001

But we can accomplish the exact same thing by just mapping the container port to a different host port:

version: '3.1'
services:
  postgres1:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example1
    ports: 
      - "5000:5432"
  postgres2:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example2
    ports:
      - "5001:5432"

# edit, removed the net host on this example since it would not work

Both of these examples will have postgres available on the docker host at ports 5000 and 5001.

All 9 comments

FYI, I've made a workaround by adding a .sh file to the /docker-entrypoint-initdb.d folder.

Here's my stuff.

Dockerfile:

FROM postgres:9.5

COPY postgres-port-config.sh /docker-entrypoint-initdb.d
RUN chmod +x /docker-entrypoint-initdb.d/postgres-port-config.sh

postgres-port-config.sh:

#!/usr/bin/env bash

set -e


if [[ -n "$POSTGRES_PORT" ]]; then
  POSTGRES_CONFIGURATION_FILE=$PGDATA/postgresql.conf
  POSTGRES_CONFIGURATION_MARKER="## PostgreSQL port configuration"
  echo "Configuring PostgreSQL port"

  if grep -Fxq "$POSTGRES_CONFIGURATION_MARKER" $POSTGRES_CONFIGURATION_FILE
  then
    # configuration file already written
    echo "Postgresql port already written, skipping" 
  else
    # write configuration file
    gosu postgres pg_ctl -D "$PGDATA" -m fast -w stop
    echo "Postgresql configuration port update being written: $POSTGRES_PORT"
    echo "$POSTGRES_CONFIGURATION_MARKER" >> $POSTGRES_CONFIGURATION_FILE
    echo "port = $POSTGRES_PORT" >> $POSTGRES_CONFIGURATION_FILE

    gosu postgres pg_ctl -D "$PGDATA" -w start
  fi
fi

No need for all that extra work, most (all?) postgres configuration can be set via a flag. Just use the flag to the postgres binary on the docker run; they'll get passed along from the entrypoint to the postgres binary.

# make sure to put the args after the name of the image
$ docker run -d --name postg postgres:9.6 -p 5300
# assuming you have a way to resolve "postg.docker" hostname
$ docker run -it --rm postgres:9.6 psql -h postg.docker -p 5300 -U postgres
psql (9.6.0)
Type "help" for help.

postgres=#

When running via docker-compose this is even an important issue. In the docker-compose.yml there is the possibility to add ports via expose, but there is no config to "unexpose" the standard port. So running two postgres containers in parallel might cause some problems.

Any solution to be able to run two postgres instances in parallel via docker-compose?

The expose in the Dockerfile does nothing but tell the user what the default is; if you don't explicitly add it to your yaml file it wont matter. Here is an example of running two postgres instances in the same network namespace (the host) but running on different ports:

# edit, this is a bad example; don't run services on "net:host"
version: '3.1'
services:
  postgres1:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example1
    net: host
    command: -p 5000
  postgres2:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example2
    net: host
    command: -p 5001

But we can accomplish the exact same thing by just mapping the container port to a different host port:

version: '3.1'
services:
  postgres1:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example1
    ports: 
      - "5000:5432"
  postgres2:
    image: postgres:9.6
    environment:
      POSTGRES_PASSWORD: example2
    ports:
      - "5001:5432"

# edit, removed the net host on this example since it would not work

Both of these examples will have postgres available on the docker host at ports 5000 and 5001.

Closing, given that this is trivially possible via -p passed to the container. :+1:

It's ports: for anyone hitting this issue and not port.

ockerfile does nothing but tell the user what the default is; if you don't explicitly add it to your yaml file it

But i want it to run inside on different ports. For example 5432 and 5433. Cause when they are running inside on the same port, the cache from Jira/Confluence is going nuts.

Had similar issue trying to run two services in bitbucket pipeline: a postgresql db and a second one running timescaledb. bitbucket-pipeline doesn't support (as of today) to run a custom command for its service so relying on ports seems to be the way to go.

Thanks to kaspersorensen's above comment. I created the following:
https://github.com/gableroux/docker-timescaledb

postgres images probably changed since 2016 so suggested script didn't work. I've read the postgres (as of today):
https://github.com/docker-library/postgres/blob/fdf884a/11/docker-entrypoint.sh

I replaced gosu calls with sourcing the entrypoint and calling already defined functions to stop and start the temp server.

I did it with timescaledb docker image, but that solution should also work with postgres. timescaledb is _just_ postgresql with an extension ;)

:v:

Was this page helpful?
0 / 5 - 0 ratings