feat: PostgreSQL image with TimescaleDB, VectorChord, pgvector
All checks were successful
🚀 Docker Build and Push / build-and-push (15) (push) Successful in 5m44s
🚀 Docker Build and Push / build-and-push (16) (push) Successful in 5m33s
🚀 Docker Build and Push / build-and-push (18) (push) Successful in 6m7s
🚀 Docker Build and Push / build-and-push (17) (push) Successful in 7m54s
All checks were successful
🚀 Docker Build and Push / build-and-push (15) (push) Successful in 5m44s
🚀 Docker Build and Push / build-and-push (16) (push) Successful in 5m33s
🚀 Docker Build and Push / build-and-push (18) (push) Successful in 6m7s
🚀 Docker Build and Push / build-and-push (17) (push) Successful in 7m54s
- Multi-stage Dockerfile for optimized image size (676MB vs 2GB) - Support for PostgreSQL 15, 16, 17, 18 - TimescaleDB 2.24.0, VectorChord 1.0.0, pgvector 0.8.1 - Auto-creation of extensions on first startup - CI/CD with tests for all versions - OCI labels and healthcheck included
This commit is contained in:
104
.gitea/workflows/docker-build.yml
Normal file
104
.gitea/workflows/docker-build.yml
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
name: 🚀 Docker Build and Push
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-push:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
pg_version: [15, 16, 17, 18]
|
||||||
|
steps:
|
||||||
|
- name: 📥 Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: 🛠️ Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: 🔐 Login to Gitea Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: gitea.killinger.fr
|
||||||
|
username: maxime.killinger
|
||||||
|
password: ${{ secrets.DOCKER_TOKEN }}
|
||||||
|
|
||||||
|
- name: 📦 Build Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
load: true
|
||||||
|
build-args: |
|
||||||
|
PG_VERSION=${{ matrix.pg_version }}
|
||||||
|
tags: |
|
||||||
|
postgres-ts-vectors:pg${{ matrix.pg_version }}-test
|
||||||
|
|
||||||
|
- name: 🧪 Test image - Start container
|
||||||
|
run: |
|
||||||
|
docker run -d --name test-pg${{ matrix.pg_version }} \
|
||||||
|
-e POSTGRES_PASSWORD=testpass \
|
||||||
|
postgres-ts-vectors:pg${{ matrix.pg_version }}-test
|
||||||
|
|
||||||
|
# Wait for PostgreSQL to be ready
|
||||||
|
echo "Waiting for PostgreSQL to start..."
|
||||||
|
for i in {1..30}; do
|
||||||
|
if docker exec test-pg${{ matrix.pg_version }} pg_isready -U postgres > /dev/null 2>&1; then
|
||||||
|
echo "PostgreSQL is ready!"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: 🧪 Test image - Verify extensions
|
||||||
|
run: |
|
||||||
|
# Wait a bit more for init scripts to complete
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Check extensions are installed
|
||||||
|
RESULT=$(docker exec test-pg${{ matrix.pg_version }} psql -U postgres -t -c \
|
||||||
|
"SELECT count(*) FROM pg_extension WHERE extname IN ('timescaledb', 'vector', 'vchord');")
|
||||||
|
|
||||||
|
EXTENSIONS=$(echo $RESULT | tr -d ' ')
|
||||||
|
echo "Found $EXTENSIONS extensions"
|
||||||
|
|
||||||
|
if [ "$EXTENSIONS" -eq "3" ]; then
|
||||||
|
echo "✅ All 3 extensions are installed!"
|
||||||
|
else
|
||||||
|
echo "❌ Expected 3 extensions, found $EXTENSIONS"
|
||||||
|
docker exec test-pg${{ matrix.pg_version }} psql -U postgres -c \
|
||||||
|
"SELECT extname, extversion FROM pg_extension;"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show extension versions
|
||||||
|
docker exec test-pg${{ matrix.pg_version }} psql -U postgres -c \
|
||||||
|
"SELECT extname, extversion FROM pg_extension WHERE extname IN ('timescaledb', 'vector', 'vchord');"
|
||||||
|
|
||||||
|
- name: 🧹 Cleanup test container
|
||||||
|
if: always()
|
||||||
|
run: docker rm -f test-pg${{ matrix.pg_version }} || true
|
||||||
|
|
||||||
|
- name: 🚀 Push Docker image
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
build-args: |
|
||||||
|
PG_VERSION=${{ matrix.pg_version }}
|
||||||
|
tags: |
|
||||||
|
gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:pg${{ matrix.pg_version }}
|
||||||
|
|
||||||
|
- name: 🏷️ Tag latest (PG18 only)
|
||||||
|
if: matrix.pg_version == 18
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
build-args: |
|
||||||
|
PG_VERSION=18
|
||||||
|
tags: |
|
||||||
|
gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:latest
|
||||||
|
|
||||||
|
|
||||||
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.DS_Store
|
||||||
|
*.log
|
||||||
|
tmp/
|
||||||
|
build/
|
||||||
|
.env
|
||||||
56
Dockerfile
Normal file
56
Dockerfile
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
ARG PG_VERSION=18
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Builder stage - Compile TimescaleDB
|
||||||
|
# =============================================================================
|
||||||
|
FROM tensorchord/vchord-postgres:pg${PG_VERSION}-v1.0.0 AS builder
|
||||||
|
|
||||||
|
USER root
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
git \
|
||||||
|
build-essential \
|
||||||
|
cmake \
|
||||||
|
libssl-dev \
|
||||||
|
libkrb5-dev \
|
||||||
|
postgresql-server-dev-$PG_MAJOR \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Build TimescaleDB from source (stable release)
|
||||||
|
ARG TIMESCALEDB_VERSION=2.24.0
|
||||||
|
WORKDIR /build/timescaledb
|
||||||
|
RUN git clone --branch ${TIMESCALEDB_VERSION} --depth 1 https://github.com/timescale/timescaledb.git . \
|
||||||
|
&& ./bootstrap -DREGRESS_CHECKS=OFF -DWARNINGS_AS_ERRORS=OFF \
|
||||||
|
&& cd build && make -j$(nproc) && make install DESTDIR=/tmp/timescaledb
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Final stage - Clean runtime image
|
||||||
|
# =============================================================================
|
||||||
|
FROM tensorchord/vchord-postgres:pg${PG_VERSION}-v1.0.0 AS final
|
||||||
|
|
||||||
|
# OCI Labels
|
||||||
|
LABEL org.opencontainers.image.title="TimescaleDB + VectorChord + pgvector"
|
||||||
|
LABEL org.opencontainers.image.description="PostgreSQL with TimescaleDB, VectorChord, and pgvector extensions pre-installed"
|
||||||
|
LABEL org.opencontainers.image.source="https://gitea.killinger.fr/maxime.killinger/postgres-ts-vectors"
|
||||||
|
LABEL org.opencontainers.image.vendor="Maxime Killinger"
|
||||||
|
LABEL org.opencontainers.image.licenses="Apache-2.0"
|
||||||
|
LABEL org.opencontainers.image.base.name="tensorchord/vchord-postgres:pg${PG_VERSION}-v1.0.0"
|
||||||
|
|
||||||
|
# Copy TimescaleDB from builder
|
||||||
|
COPY --from=builder /tmp/timescaledb/usr/lib/postgresql/ /usr/lib/postgresql/
|
||||||
|
COPY --from=builder /tmp/timescaledb/usr/share/postgresql/ /usr/share/postgresql/
|
||||||
|
|
||||||
|
# Add init script for auto-extension creation
|
||||||
|
COPY init-extensions.sh /docker-entrypoint-initdb.d/
|
||||||
|
RUN chmod +x /docker-entrypoint-initdb.d/init-extensions.sh
|
||||||
|
|
||||||
|
# Healthcheck
|
||||||
|
HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \
|
||||||
|
CMD pg_isready -U postgres || exit 1
|
||||||
|
|
||||||
|
USER postgres
|
||||||
|
|
||||||
|
# Preload required libraries
|
||||||
|
CMD ["postgres", "-c", "shared_preload_libraries=timescaledb,vchord"]
|
||||||
90
README.md
Normal file
90
README.md
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
# TimescaleDB + VectorChord + pgvector
|
||||||
|
|
||||||
|
[](https://gitea.killinger.fr/maxime.killinger/postgres-ts-vectors/actions)
|
||||||
|
|
||||||
|
Docker image combining **PostgreSQL** with three powerful extensions:
|
||||||
|
|
||||||
|
- **[TimescaleDB](https://www.timescale.com/)** - Time-series database extension
|
||||||
|
- **[VectorChord](https://vectorchord.ai/)** - High-performance vector similarity search
|
||||||
|
- **[pgvector](https://github.com/pgvector/pgvector)** - Open-source vector similarity search
|
||||||
|
|
||||||
|
## Supported PostgreSQL Versions
|
||||||
|
|
||||||
|
| Tag | PostgreSQL | TimescaleDB | VectorChord | pgvector |
|
||||||
|
|-----|------------|-------------|-------------|----------|
|
||||||
|
| `pg15` | 15 | 2.24.0 | 1.0.0 | 0.8.1 |
|
||||||
|
| `pg16` | 16 | 2.24.0 | 1.0.0 | 0.8.1 |
|
||||||
|
| `pg17` | 17 | 2.24.0 | 1.0.0 | 0.8.1 |
|
||||||
|
| `pg18`, `latest` | 18 | 2.24.0 | 1.0.0 | 0.8.1 |
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name my-postgres \
|
||||||
|
-e POSTGRES_PASSWORD=mysecretpassword \
|
||||||
|
-p 5432:5432 \
|
||||||
|
gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
All extensions are **automatically created** on first startup.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
| Variable | Description | Default |
|
||||||
|
|----------|-------------|---------|
|
||||||
|
| `POSTGRES_PASSWORD` | PostgreSQL password (required) | - |
|
||||||
|
| `POSTGRES_USER` | PostgreSQL user | `postgres` |
|
||||||
|
| `POSTGRES_DB` | Default database | `postgres` |
|
||||||
|
|
||||||
|
## Extensions Usage
|
||||||
|
|
||||||
|
### TimescaleDB
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Create a hypertable
|
||||||
|
CREATE TABLE conditions (
|
||||||
|
time TIMESTAMPTZ NOT NULL,
|
||||||
|
device_id INTEGER,
|
||||||
|
temperature DOUBLE PRECISION
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT create_hypertable('conditions', 'time');
|
||||||
|
```
|
||||||
|
|
||||||
|
### VectorChord / pgvector
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Create a table with vector embeddings
|
||||||
|
CREATE TABLE documents (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
content TEXT,
|
||||||
|
embedding vector(1536)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Create an index for fast similarity search
|
||||||
|
CREATE INDEX ON documents USING vchordrq (embedding vector_l2_ops);
|
||||||
|
|
||||||
|
-- Query similar documents
|
||||||
|
SELECT * FROM documents
|
||||||
|
ORDER BY embedding <-> '[0.1, 0.2, ...]'
|
||||||
|
LIMIT 10;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building Locally
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Build for PG18
|
||||||
|
docker build --build-arg PG_VERSION=18 -t my-image:pg18 .
|
||||||
|
|
||||||
|
# Build for PG16
|
||||||
|
docker build --build-arg PG_VERSION=16 -t my-image:pg16 .
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
This project is licensed under the Apache 2.0 License.
|
||||||
|
|
||||||
|
- TimescaleDB: [Timescale License](https://github.com/timescale/timescaledb/blob/main/LICENSE)
|
||||||
|
- VectorChord: [Apache 2.0](https://github.com/tensorchord/VectorChord/blob/main/LICENSE)
|
||||||
|
- pgvector: [PostgreSQL License](https://github.com/pgvector/pgvector/blob/master/LICENSE)
|
||||||
14
build.sh
Normal file
14
build.sh
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Build script for TimescaleDB + VectorChord + pgvector
|
||||||
|
|
||||||
|
PG_VERSION=${1:-18}
|
||||||
|
IMAGE_NAME="timescaledb-vectorchord"
|
||||||
|
|
||||||
|
echo "Building for PostgreSQL ${PG_VERSION}..."
|
||||||
|
|
||||||
|
docker build \
|
||||||
|
--build-arg PG_VERSION=${PG_VERSION} \
|
||||||
|
-t ${IMAGE_NAME}:pg${PG_VERSION} \
|
||||||
|
.
|
||||||
|
|
||||||
|
echo "Build complete: ${IMAGE_NAME}:pg${PG_VERSION}"
|
||||||
10
init-extensions.sh
Normal file
10
init-extensions.sh
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
|
||||||
|
CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;
|
||||||
|
CREATE EXTENSION IF NOT EXISTS vector;
|
||||||
|
CREATE EXTENSION IF NOT EXISTS vchord CASCADE;
|
||||||
|
EOSQL
|
||||||
|
|
||||||
|
echo "Extensions timescaledb, vector, and vchord have been created."
|
||||||
4
init-timescale.sh
Normal file
4
init-timescale.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# This script is run during the first database initialization
|
||||||
|
# TimescaleDB requires being preloaded - this message is informational only
|
||||||
|
echo "TimescaleDB is installed. Remember to set shared_preload_libraries = 'timescaledb' in postgresql.conf or use the POSTGRES_SHARED_PRELOAD_LIBRARIES environment variable."
|
||||||
Reference in New Issue
Block a user