dockerでpgvector拡張のPostgreSQLを構築する

1. 要件

  1. コンテナ (docker) でDBが構築されている
  2. PostgreSQL(image)のversionが最新になっている
  3. vector型が使える (vector拡張がインストールされている)
  4. retriever用のDB/USER/Access Controlがセットアップされている

2. 検討

  • officialを見ると17.4が最新になっており、pgvector拡張を見ると拡張追加の方法が明示されてるので、docker-composeに build entryを書いて構築する (1, 2, 3)。
  • restart entryは、unless-stoppedだと手動でcontainerをstopし、そのまま忘れてシステム再起動した時に自動で立ち上がらないので restart: alwaysとする。
  • 検討すべきはretriever向けのAccess Controlだが、retriever用以外はlocal向け用途なのでネットワークレベルで制御する (4)。
    • 他は一般的な制御をする (できるだけ最小の権限を付与)。

3. 作業

掃除

既存のcontainer/imageの削除や、dataファイルの退避 (予めbackupは取っておく)を行う。

psql --version
docker container rm pg
docker image rm postgres
sudo mv db_data/pg/ /tmp/

Dockerfile (pg-dockerfile) の作成

# Dockerfile
FROM postgres:17.4

RUN apt-get update && \
    apt-get install -y git make gcc postgresql-server-dev-17

RUN cd /tmp && \
    git clone --branch v0.8.0 https://github.com/pgvector/pgvector.git && \
    cd pgvector && \
    make && \
    make install && \
    cd ../ && rm -rf pgvector

docker-compose.ymlの更新

build entryを追加し、build後のimage名はvectorを冠するものにしたいのでそうする。

    build:
      context: .
      dockerfile: ./dockerfiles/pg-dockerfile
    image: pg17-vector-enabled

build & up

対応するimageが存在しないので、以下のコマンドで buildup (i.e. running daemon) が実行される。

docker-compose up pg
  • 立ち上がりのログが見たいのでこうするが、無事立ち上がるとterminalを占有するので Ctrl-C-C で落とし、改めて docker-compose startでdaemonizeする。
  • 最初からdaemonizeしたいなら--detachを付ける等あったと思う(お薦めしない)。
  • llvm libraryのインストールに時間がかかった(2~3分程)ので、フリーズしたかと思って調べた。

CREATE ROLE

  • PostgreSQLにおいてROLEはUSERのsynonymになっており、ユーザの設定を変える際、 ALTER USER ではなく ALTER ROLEとする。
  • CREATE DATABASEの TEMPLATE template1公式を見ると不要と分かる (defaultでtemplate1のコピーを作る為)。
  • SCHEMAはDATABASE下の「ディレクトリ」に相当するので、DATABASEに接続し直す必要がある。
    • 論理的な境界線を規定するもので、例えばSELECTでそれ以下のどのTABLEが見える(指定できる)かが決まる (c.f. rolesessionごとに指定できるsearch_pathで設定)
    • SCHEMAへのGRANTは、公式にあるように USAGE, CREATE, ALLのみ指定可能。
    • PRIVILEGES節を見ると, USAGEは参照、CREATEは(TABLE等も含むDATABASE OBJECTの)作成
CREATE USER some_retriever WITH PASSWORD '******';
CREATE DATABASE vector_db TEMPLATE template1;
GRANT ALL PRIVILEGES ON DATABASE vector_db TO some_retriever ;
\c vector_db postgres
# connected to database "vector_db" as user "postgres".
GRANT ALL ON SCHEMA public TO some_retriever ;

vector拡張の有効化

拡張有効化はDATABASEごとに行うことができ、有効化にはsuper user権限が必要。

\c vector_db
CREATE EXTENSION vector;

vector拡張の有効化確認

\dx
                             List of installed extensions
  Name   | Version |   Schema   |                     Description                      
---------+---------+------------+------------------------------------------------------
 plpgsql | 1.0     | pg_catalog | PL/pgSQL procedural language
 vector  | 0.8.0   | public     | vector data type and ivfflat and hnsw access methods

Vectorizeされたdocumentの確認と照合

適当なdocument (c.f. 画像はこのブログの記事のchunk) を準備し、

  • Simple (On Memory / File storage)
  • Vector DB

二つの方法 (i.e. store) でindexを保存した (c.f. 例ではindexingにllamaindexを使用)。

  • 左はSimpleで永続化して出力されるファイルの一つで docstore.jsonというファイル。
  • 右は先に準備したDATABASE (i.e. vector_db.metadata_)に保存されたdocumentのmetaデータ。
  • それぞれ異なるタイミング・方法で永続化しても整合している事が分かる。
  • llamaindexの場合、DATABASEだけ作ればTABLEはパラメタから導出されて自動で作られる。

4. まとめ

今回はvector拡張付きのPostgreSQLを構築し、データが入る所までを確認した。

仕事で余り使う機会がないPostgreSQLは、個人的に一番好きなRDBMS (実際、個人のプロジェクトはSQLiteかPostgreSQLを使う)。

  • 非常に堅牢でありつつ、vectorを始めデーの拡張性が◎。Range TypeやComposite TypeはOSSでは他にない。
  • ACID Complianceは一見分かり辛いが、過去Multi-Subscriber構成でReplicaを作った時に問題になった事が無いので結構利いてると思う。
  • Windowsにも対応 (サーバー専用インストーラもある)