Postgres and extensions in docker

I have a simple flake that builds a postgres container with dockerTools. When I include the pgvector extension, postgres in the resulting container can’t find the vector.control. It seems like it’s looking in the lib folder in the nix store, and not in the `share/postgresql/extensions/’ folder where it gets installed. Does anyone know how to get it to build with the right pg_config path?

Here is the postgres.nix file:

{ pkgs, lib, stdenv, pkgsMusl, dockerTools, buildEnv, ... }:

let

  postgres = pkgs.postgresql_16;
  pgvector = pkgs.postgresql16Packages.pgvector;
  
in dockerTools.buildImage {
  name = "brauer";
  tag = postgres.version;
  created = "now";
  
  copyToRoot = buildEnv {
    name = "image-root";
    paths = [
      (dockerTools.fakeNss.override {
        extraPasswdLines = [
          "postgres:x:1000:1000:postgres:/var/empty:/bin/sh"
        ];
        extraGroupLines = [
          "postgres:x:1000:"
        ];
      })
      pkgs.bashInteractive
      pkgs.coreutils
      pkgs.findutils
      pkgs.ripgrep
      pkgs.vim
      postgres
      pgvector
    ];
  };

  runAsRoot = ''
    #!${pkgs.bash}/bin/bash
    mkdir /data
    chown postgres:postgres /data
  '';

  config = {
    Cmd = [ "postgres" ];
    Env = [ "PGDATA=/data" ];
    User = "postgres";
    Group = "postgres";
  };
}

It looks like postgres is expects extension .control files to be in the NIX_PGLIBDIR which is in the nix store. The extensions install in the PG_DATA directory under share/extension/ folder. I guess I will try some hack overlay to get postgres to build pointing to the right folder for extensions. Maybe a simlink, or possibly by overriding these postinstall instructions:

      mkdir -p $out/bin
      rm $out/bin/{pg_config,postgres,pg_ctl}
      cp --target-directory=$out/bin ${postgresql}/bin/{postgres,pg_config,pg_ctl}
      wrapProgram $out/bin/postgres --set NIX_PGLIBDIR $out/lib
    '';```
If anyone knows this stuff, please help a brother out.

You could probably take a look at how the NixOS module includes its support for extensions, for inspiration.

I believe it indicates that you can use this to compose a derivation containing Postgres and your desired extensions:

This would be instead of including pgvector as a sibling to Postgres in your list.

2 Likes

Thanks for the suggestion!
So would this be like the inline overlays that people do with python, e.g. something like (postgresql16.withPackages(ps: with ps; [ pgvector ]))
Or would it be an overlay that sets cfg.extraPlugins? Or neither?

Much much closer to the first example if I’ve understood your question accurately.

2 Likes

In case anyone has the same problem, the suggestion in post #3 worked. I just got it running by changing postgres and pgvector in the original file up top, to ( postgres.withPackages(ps: with ps; [ pgvector ])) I also added pathsToLink = [ "/bin" "/etc" "/var" "/share" ] although I don’t know if that was necessary or not.