skim
skim

Reputation: 171

Unix socket connection in postgres docker

I'm using flyway to version the state of my DB and the postgres docker. I'm trying to run a script in /docker-entrypoint-initdb.d/ that I want to run before postgres listens on TCP. The script creates scadb database and runs a flyway migration, however I'm having trouble connecting to the unix socket that postgres runs at. I know that any scripts that runs in /docker-entrypoint-initdb.d/ will not be able to connect to postgres by TCP so I'm using junixsocket v2.4.0; I placed the junixsocket jar files at /<FLYWAY_DIR>/drivers in order to connect by unix socket. However, I get the following errors:

Flyway Community Edition 7.9.2 by Redgate
ERROR: 
Unable to obtain connection from database (jdbc:postgresql://localhost:5432/scadb) for user 'postgres': The SocketFactory class provided org.newsclub.net.unix.AFUNIXSocketFactory could not be instantiated.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL State  : 08006
Error Code : 0
Message    : The SocketFactory class provided org.newsclub.net.unix.AFUNIXSocketFactory could not be instantiated.

Caused by: org.postgresql.util.PSQLException: The SocketFactory class provided org.newsclub.net.unix.AFUNIXSocketFactory could not be instantiated.
Caused by: java.lang.InstantiationException

versions:

If I run the same script within the postgres docker after postgres runs and listens on TCP, the script runs fine with TCP parameters.

Here is the script that runs in /docker-entrypoint-initdb.d/:

#!/bin/bash
ENDPOINT="${ENDPOINT:-127.0.0.1}"
PORT="${PORT:-5432}"
USERNAME="${USERNAME:-postgres}"
USER_PASSWD="${USER_PASSWD:-postgres}"
DB_NAME="${DB_NAME:-scadb}"
echo $ENDPOINT:$PORT:*:$USERNAME:$USER_PASSWD > ~/.pgpass
chmod 600 ~/.pgpass
#
# Create Database SCADB which flyway cannot do
#
echo "SELECT 'CREATE DATABASE scadb' WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = '${DB_NAME}')\gexec" | psql -U $USERNAME
#
# flyway migrate
#
PROFILE="${1:-default}"
flyway -url=jdbc:postgresql://localhost/scadb -jdbcProperties.socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg -jdbcProperties.socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432 -jdbcProperties.sslMode=disable migrate -locations=filesystem:/viab/ddl/$PROFILE/init/ -user=postgres -password=postgres -configFiles=/viab/ddl/$PROFILE/init.public.conf

If I remove the junixsocket jar files from /<FLYWAY_DIR>/drivers, I get

Caused by: java.lang.ClassNotFoundException: org.newsclub.net.unix.AFUNIXSocketFactory

instead of java.lang.InstantiationException so I think I'm installing junixsocket correctly. I know that I can run the flyway script as a separate entity after the postgres service is up and listening on TCP but running the flyway script in /docker-entrypoint-initdb.d/ is ideal for my situation.

I followed the postgres usage instructions of junixsocket from https://kohlschutter.github.io/junixsocket/dependency.html but I'm unable to proceed past the connection issue. I'm unclear why it is unable to instantiate org.newsclub.net.unix.AFUNIXSocketFactory. Any help would be appreciated.

Upvotes: 0

Views: 1798

Answers (1)

In the last line of your script

flyway -url=jdbc:postgresql://localhost/scadb -jdbcProperties.socketFactory=org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg -jdbcProperties.socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432 -jdbcProperties.sslMode=disable migrate -locations=filesystem:/viab/ddl/$PROFILE/init/ -user=postgres -password=postgres -configFiles=/viab/ddl/$PROFILE/init.public.conf

you need to put org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg in single quotes, i.e.

flyway -url=jdbc:postgresql://localhost/scadb -jdbcProperties.socketFactory='org.newsclub.net.unix.AFUNIXSocketFactory$FactoryArg' -jdbcProperties.socketFactoryArg=/var/run/postgresql/.s.PGSQL.5432 -jdbcProperties.sslMode=disable migrate -locations=filesystem:/viab/ddl/$PROFILE/init/ -user=postgres -password=postgres -configFiles=/viab/ddl/$PROFILE/init.public.conf

Without quotes, your shell tries to resolve $FactoryArg as a variable, which results in an empty string.

It's an interesting failure mode I had not considered when I implemented these inner subclasses back in the day.

Upvotes: 1

Related Questions