diff --git a/.dockerignore b/.dockerignore index b49ccca..d9a62a2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -15,6 +15,8 @@ docker-compose*.yml Makefile .vscode/ .idea/ +.zed/ +.target/ # OS .DS_Store diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..f33df92 --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,48 @@ +name: Build and Push Docker Images + +on: + push: + branches: + - main + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + build-and-push: + runs-on: ubuntu-latest + strategy: + matrix: + postgres_version: ["18", "17", "17.6", "16", "16.10"] + fail-fast: false + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PERSONAL_KEY }} + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/riscv64,linux/s390x + push: ${{ github.event_name != 'pull_request' }} + tags: | + ${{ secrets.DOCKER_USERNAME }}/postgres:${{ matrix.postgres_version }} + ${{ secrets.DOCKER_USERNAME }}/postgres:latest + build-args: | + POSTGRES_VERSION=${{ matrix.postgres_version }} + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml deleted file mode 100644 index 6e8d2d2..0000000 --- a/.github/workflows/docker-image.yml +++ /dev/null @@ -1,51 +0,0 @@ -name: Docker Image CI - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - -env: - IMAGE_VERSION: "0.1.1" - POSTGRES_VERSION: "17.5" - -jobs: - build-and-push: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - - name: Log in to Docker Hub - uses: docker/login-action@v3 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PERSONAL_KEY }} - - - name: Set combined version - run: echo "COMBINED_VERSION=${{ env.POSTGRES_VERSION }}-v${{ env.IMAGE_VERSION }}" >> $GITHUB_ENV - - - name: Extract metadata - id: meta - uses: docker/metadata-action@v5 - with: - images: ruxwez/postgres - tags: | - type=raw,value=${{ env.COMBINED_VERSION }} - type=raw,value=latest,enable={{is_default_branch}} - - - name: Build and push Docker image - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name != 'pull_request' }} - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/ADDING_VERSIONS.md b/ADDING_VERSIONS.md deleted file mode 100644 index c26591d..0000000 --- a/ADDING_VERSIONS.md +++ /dev/null @@ -1,75 +0,0 @@ -# Cómo añadir una nueva versión de PostgreSQL - -Este documento explica cómo añadir soporte para una nueva versión de PostgreSQL al repositorio. - -## Pasos para añadir una nueva versión - -### 1. Crear la estructura de carpetas - -Crea una nueva carpeta con el número de la versión mayor de PostgreSQL: - -```bash -mkdir 16 # Para PostgreSQL 16 -``` - -### 2. Crear el Dockerfile - -Copia el Dockerfile de una versión existente y modifica las referencias de versión: - -```bash -cp 17/Dockerfile 16/ -``` - -Edita `16/Dockerfile` y cambia: -- `FROM postgres:17` → `FROM postgres:16` -- `postgresql-17-postgis-3` → `postgresql-16-postgis-3` -- `postgresql-17-postgis-3-scripts` → `postgresql-16-postgis-3-scripts` -- `postgresql-server-dev-17` → `postgresql-server-dev-16` - -### 3. Copiar archivos de configuración - -```bash -cp 17/init.sql 16/ -cp 17/docker-compose.yml 16/ -``` - -### 4. Actualizar el GitHub Action - -Edita `.github/workflows/docker-image.yml` y añade la nueva versión a la matriz: - -```yaml -strategy: - matrix: - postgres-version: [15, 16, 17] # Añade la nueva versión aquí -``` - -### 5. Actualizar el README - -Actualiza el `README.md` para documentar la nueva versión disponible. - -## Estructura esperada - -Después de añadir una nueva versión, deberías tener: - -``` -16/ -├── Dockerfile -├── docker-compose.yml -└── init.sql -``` - -## Tags que se generarán - -El GitHub Action automáticamente creará tags con el prefijo de la versión: - -- `ruxwez/postgres:16-latest` -- `ruxwez/postgres:16-main` -- `ruxwez/postgres:16-YYYYMMDD-HHmmss` - -## Verificación - -Para verificar que todo funciona correctamente: - -1. Haz commit y push de los cambios -2. El GitHub Action debería buildear automáticamente todas las versiones -3. Verifica que las imágenes aparezcan en Docker Hub con los tags correctos diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..73c09d2 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,281 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "install-extensions" +version = "0.1.0" +dependencies = [ + "tokio", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "mio" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "proc-macro2" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e0f6df8eaa422d97d72edcd152e1451618fed47fabbdbd5a8864167b1d4aff7" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + +[[package]] +name = "syn" +version = "2.0.108" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da58917d35242480a05c2897064da0a80589a2a0476c9a3f2fdc83b53502e917" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +dependencies = [ + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "462eeb75aeb73aea900253ce739c8e18a67423fadf006037cd3ff27e82748a06" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..719ffa9 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,8 @@ + +[package] +name = "install-extensions" +version = "0.1.0" +edition = "2024" + +[dependencies] +tokio = { version = "1.48.0", features = ["full"] } diff --git a/Dockerfile b/Dockerfile index d2eeb91..0b8bde6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,48 +1,23 @@ -# Use the official PostgreSQL 17 base image -FROM postgres:17.5 +ARG POSTGRES_VERSION=17.5 -# Define the pgvector version to install -ARG PG_VECTOR_RELEASE="v0.8.0" +# Builder stage: compile the Rust binary +FROM rust:slim AS builder +WORKDIR /installer -# Install necessary extensions and build tools -RUN apt-get update && apt-get install -y \ - postgresql-contrib \ - postgresql-17-postgis-3 \ - postgresql-17-postgis-3-scripts \ - git \ - build-essential \ - postgresql-server-dev-17 \ - && apt-get clean && rm -rf /var/lib/apt/lists/* +# Copy dependency files first for better caching +COPY . . -# Install pgvector from source code -RUN git clone --branch ${PG_VECTOR_RELEASE} https://github.com/pgvector/pgvector.git /tmp/pgvector \ - && cd /tmp/pgvector \ - && make clean \ - && make OPTFLAGS="" \ - && make install \ - && cd / \ - && rm -rf /tmp/pgvector +RUN cargo build --release -# Install pgmq from source -RUN git clone https://github.com/pgmq/pgmq.git /tmp/pgmq \ - && cd /tmp/pgmq/pgmq-extension \ - && make \ - && make install \ - && cd / \ - && rm -rf /tmp/pgmq +# Final stage: only Postgres +FROM postgres:${POSTGRES_VERSION} +ARG POSTGRES_VERSION +# Copy the compiled binary +COPY --from=builder /installer/target/release/install-extensions /usr/local/bin/installer +# Run installer (all logic including cleanup is inside the binary) +RUN /usr/local/bin/installer ${POSTGRES_VERSION} && \ + rm /usr/local/bin/installer -# Clean up build packages to reduce image size -RUN apt-get update && apt-get remove -y \ - git \ - build-essential \ - postgresql-server-dev-17 \ - && apt-get autoremove -y \ - && apt-get clean && rm -rf /var/lib/apt/lists/* - -# Copy the optional initialization script -COPY init.sql /docker-entrypoint-initdb.d/ - -# Expose the default PostgreSQL port EXPOSE 5432 diff --git a/Makefile b/Makefile deleted file mode 100644 index 8c49fd1..0000000 --- a/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -.PHONY: build start stop clean test help - -# Default target -help: - @echo "Available commands:" - @echo " build - Build PostgreSQL image" - @echo " start - Start PostgreSQL container" - @echo " stop - Stop PostgreSQL container" - @echo " clean - Remove all containers and volumes" - @echo " test - Test the image" - @echo " help - Show this help message" - -# Build targets -build: - docker compose build - -# Start targets -start: - docker compose up -d - -# Stop targets -stop: - docker compose down - -# Clean target -clean: - docker compose down -v - docker system prune -f - -# Test target -test: - @echo "Testing image..." - docker compose up -d - sleep 10 - @echo "PostgreSQL Version:" - docker exec postgres17 psql -U postgres -d postgres -c "SELECT version();" - @echo "\nInstalled Extensions:" - docker exec postgres17 psql -U postgres -d postgres -c "\dx" - @echo "\nAvailable Extensions:" - docker exec postgres17 psql -U postgres -d postgres -c "SELECT name, default_version, comment FROM pg_available_extensions ORDER BY name;" - docker compose down diff --git a/README.md b/README.md deleted file mode 100644 index 2b26c2f..0000000 --- a/README.md +++ /dev/null @@ -1,278 +0,0 @@ -# PostgreSQL with PostGIS and pgvector - -A Docker-based PostgreSQL setup with PostGIS and pgvector extensions for geospatial and vector similarity search capabilities. - -## 🏗️ Version Management - -This repository allows specifying static versions for Docker images: - -### Version Control Methods - -1. **Static Version (Automatic)**: Modify `IMAGE_VERSION` in `.github/workflows/docker-image.yml` -2. **Manual Version**: Use the `docker-image-manual.yml` workflow to specify versions when running -3. **Configuration File**: See the `VERSION` file for current versions - -### Changing the Image Version - -To publish a new version: - -1. **Static Method**: Edit `.github/workflows/docker-image.yml`: - ```yaml - env: - IMAGE_VERSION: "0.1.0" # Change this line - POSTGRES_VERSION: "17.5" - ``` - -2. **Manual Method**: Go to GitHub Actions → "Docker Image CI (Manual Version)" → "Run workflow" - -## Repository Structure - -``` -├── Dockerfile # PostgreSQL 17 with PostGIS and pgvector -├── docker-compose.yml # Docker Compose configuration -├── init.sql # Database initialization script -├── VERSION # Version configuration -└── .github/ - └── workflows/ - ├── docker-image.yml # Automatic build with static version - └── docker-image-manual.yml # Manual build with version input -``` - -## Docker Hub Tags - -The images are available with the following tags: - -- `ruxwez/postgres:latest` - Latest build from the main branch -- `ruxwez/postgres:17.5-0.1.0` - Specific version (example) -- `ruxwez/postgres:[VERSION]` - Version specified in the workflow - -### Current Version -- **Image**: `17.5-0.1.0` -- **PostgreSQL**: `17.5` -- **pgvector**: `v0.8.0` -- **PostGIS**: `3.x` - -## Features - -- **PostgreSQL**: Latest PostgreSQL versions -- **PostGIS**: Spatial database extender for PostgreSQL -- **pgvector**: Open-source vector similarity search for PostgreSQL -- **Docker Compose**: Easy deployment and management -- **Pre-configured**: Ready-to-use with extensions automatically enabled -- **Multi-architecture**: Supports AMD64 and ARM64 platforms - -## Extensions Included - -- **PostGIS 3**: Advanced geospatial functionality -- **pgvector v0.8.0**: Vector embeddings and similarity search -- **postgresql-contrib**: Additional PostgreSQL extensions - -## Quick Start - -### Prerequisites - -- Docker and Docker Compose installed on your system - -### Installation - -1. Clone this repository: -```bash -git clone https://github.com/ruxwez/postgres.git -cd postgres -``` - -2. Start the PostgreSQL container: -```bash -docker-compose up -d -``` - -**Or use the pre-built image directly:** -```bash -docker run -d \ - --name postgres17 \ - -e POSTGRES_USER=postgres \ - -e POSTGRES_PASSWORD=1234 \ - -e POSTGRES_DB=postgres \ - -p 5432:5432 \ - ruxwez/postgres:latest -``` - -3. Connect to the database: -```bash -# Using psql -docker exec -it postgres17 psql -U postgres -d postgres - -# Or using any PostgreSQL client -# Host: localhost -# Port: 5432 -# Database: postgres -# Username: postgres -# Password: 1234 -``` - -### Verification - -Check that extensions are available: -```sql --- Verify PostGIS extension -SELECT PostGIS_Version(); - --- Verify pgvector extension -SELECT * FROM pg_extension WHERE extname = 'vector'; - --- List all available extensions -\dx -``` - -## Configuration - -### Environment Variables - -The default configuration can be modified in `docker-compose.yml`: - -```yaml -environment: - POSTGRES_USER: postgres # Database username - POSTGRES_PASSWORD: 1234 # Database password - POSTGRES_DB: postgres # Default database name -``` - -### Custom Initialization - -Add your SQL initialization scripts to the `init.sql` file or create additional `.sql` files in the project directory and mount them to `/docker-entrypoint-initdb.d/` in the container. - -## Usage Examples - -### PostGIS Example - -```sql --- Create a table with geometry column -CREATE TABLE locations ( - id SERIAL PRIMARY KEY, - name VARCHAR(100), - geom GEOMETRY(POINT, 4326) -); - --- Insert some sample data -INSERT INTO locations (name, geom) VALUES - ('New York', ST_GeomFromText('POINT(-74.006 40.7128)', 4326)), - ('London', ST_GeomFromText('POINT(-0.1276 51.5074)', 4326)); - --- Find distance between points -SELECT - a.name, - b.name, - ST_Distance(a.geom::geography, b.geom::geography) / 1000 AS distance_km -FROM locations a, locations b -WHERE a.id != b.id; -``` - -### pgvector Example - -```sql --- Create a table with vector column -CREATE TABLE embeddings ( - id SERIAL PRIMARY KEY, - content TEXT, - embedding vector(3) -); - --- Insert sample vectors -INSERT INTO embeddings (content, embedding) VALUES - ('document 1', '[1, 2, 3]'), - ('document 2', '[4, 5, 6]'), - ('document 3', '[1, 1, 1]'); - --- Find similar vectors using cosine similarity -SELECT content, embedding <=> '[1, 2, 2]' AS distance -FROM embeddings -ORDER BY embedding <=> '[1, 2, 2]' -LIMIT 3; -``` - -## Docker Commands - -### Start the container -```bash -docker-compose up -d -``` - -### Stop the container -```bash -docker-compose down -``` - -### View logs -```bash -docker-compose logs -f postgres -``` - -### Access the container shell -```bash -docker exec -it postgres17 /bin/bash -``` - -### Backup database -```bash -docker exec postgres17 pg_dump -U postgres postgres > backup.sql -``` - -### Restore database -```bash -docker exec -i postgres17 psql -U postgres postgres < backup.sql -``` - -## Data Persistence - -Database data is persisted using Docker volumes. The `postgres_data` volume ensures your data survives container restarts and updates. - -## Port Configuration - -- **PostgreSQL**: 5432 (mapped to host port 5432) - -## Building from Source - -If you want to customize the Docker image: - -```bash -docker build -t custom-postgres . -``` - -**With Docker Compose:** -```bash -docker-compose build -``` - -## Troubleshooting - -### Connection Issues -- Ensure the container is running: `docker-compose ps` -- Check the logs: `docker-compose logs postgres` -- Verify port 5432 is not in use by another service - -### Extension Issues -- Extensions are automatically installed during image build -- If extensions are missing, rebuild the image: `docker-compose build --no-cache` - -## Contributing - -1. Fork the repository -2. Create a feature branch -3. Make your changes -4. Test your changes -5. Submit a pull request - -## License - -This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. - -## Resources - -- [PostgreSQL Documentation](https://www.postgresql.org/docs/) -- [PostGIS Documentation](https://postgis.net/documentation/) -- [pgvector Documentation](https://github.com/pgvector/pgvector) -- [Docker Documentation](https://docs.docker.com/) - -## Author - -Jose Garcia - [@ruxwez](https://github.com/ruxwez) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index 859ae7f..0000000 --- a/docker-compose.yml +++ /dev/null @@ -1,15 +0,0 @@ -services: - postgres: - build: . - container_name: postgres17 - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: 1234 - POSTGRES_DB: postgres - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - -volumes: - postgres_data: diff --git a/init.sql b/init.sql deleted file mode 100644 index c67e4b6..0000000 --- a/init.sql +++ /dev/null @@ -1,5 +0,0 @@ --- Initialize the necessary extensions - --- By default they will be disabled --- CREATE EXTENSION IF NOT EXISTS postgis; --- CREATE EXTENSION IF NOT EXISTS vector; diff --git a/src/common.rs b/src/common.rs new file mode 100644 index 0000000..638ce5c --- /dev/null +++ b/src/common.rs @@ -0,0 +1,13 @@ +use std::process::Command; + +pub fn run(cmd: &str) { + let status = Command::new("sh") + .arg("-c") + .arg(cmd) + .status() + .expect("Failed to execute command"); + + if !status.success() { + panic!("Command failed: {}", cmd); + } +} diff --git a/src/extensions/mod.rs b/src/extensions/mod.rs new file mode 100644 index 0000000..f25c3f1 --- /dev/null +++ b/src/extensions/mod.rs @@ -0,0 +1,13 @@ +mod pgmq; +mod pgvector; +mod postgis; + +pub async fn install(pg_version: String) { + postgis::install(pg_version); + + let pgmq_handle = pgmq::install(); + let pgvector_handle = pgvector::install(); + + // Wait for all installations to complete + let _ = tokio::join!(pgmq_handle, pgvector_handle); +} diff --git a/src/extensions/pgmq.rs b/src/extensions/pgmq.rs new file mode 100644 index 0000000..b31f6eb --- /dev/null +++ b/src/extensions/pgmq.rs @@ -0,0 +1,21 @@ +use crate::common::run; +use std::fs; +use tokio::task::JoinHandle; + +static EXTENSION_VERSION: &str = "1.7.0"; + +pub fn install() -> JoinHandle<()> { + tokio::spawn(async move { + tokio::task::spawn_blocking(|| { + run(&format!( + "git clone --branch v{} --depth 1 https://github.com/pgmq/pgmq.git /tmp/pgmq", + EXTENSION_VERSION + )); + + run("cd /tmp/pgmq/pgmq-extension && make && make install"); + fs::remove_dir_all("/tmp/pgmq").ok(); + }) + .await + .expect("Blocking task failed"); + }) +} diff --git a/src/extensions/pgvector.rs b/src/extensions/pgvector.rs new file mode 100644 index 0000000..3483478 --- /dev/null +++ b/src/extensions/pgvector.rs @@ -0,0 +1,23 @@ +use crate::common::run; +use std::fs; +use tokio::task::JoinHandle; + +static EXTENSION_VERSION: &str = "0.8.1"; + +pub fn install() -> JoinHandle<()> { + tokio::spawn(async move { + tokio::task::spawn_blocking(|| { + // Clone the repository + run(&format!( + "git clone --branch v{} --depth 1 https://github.com/pgvector/pgvector.git /tmp/pgvector", + EXTENSION_VERSION + )); + + // Build and install pgvector + run("cd /tmp/pgvector && make clean && make OPTFLAGS='' && make install"); + + // Clean up the temporary directory + fs::remove_dir_all("/tmp/pgvector").ok(); + }).await.expect("Blocking task failed"); + }) +} diff --git a/src/extensions/postgis.rs b/src/extensions/postgis.rs new file mode 100644 index 0000000..175fd6a --- /dev/null +++ b/src/extensions/postgis.rs @@ -0,0 +1,14 @@ +use crate::common::run; + +static EXTENSION_VERSION: &str = "3"; + +pub fn install(pg_version: String) { + let pg_major = pg_version.split('.').next().unwrap().to_owned(); + + run(&format!( + "apt-get install -y \ + postgresql-{}-postgis-{} \ + postgresql-{}-postgis-{}-scripts", + pg_major, EXTENSION_VERSION, pg_major, EXTENSION_VERSION + )); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..cf03fff --- /dev/null +++ b/src/main.rs @@ -0,0 +1,62 @@ +use std::env; + +use crate::common::run; + +mod common; +mod extensions; + +#[tokio::main] +async fn main() { + // Collect command-line arguments + let args: Vec = env::args().collect(); + + if args.len() != 2 { + panic!("Insert PostgreSQL version as argument"); + } + + let pg_version = &args[1]; + let pg_major = pg_version.split(".").next().unwrap(); + + println!( + "🚀 Installing PostgreSQL extensions for version {}", + pg_version + ); + + // Install necessary packages + println!("📦 Installing build dependencies..."); + run(&format!( + "apt-get update && apt-get install -y --no-install-recommends \ + postgresql-contrib \ + git \ + build-essential \ + postgresql-server-dev-{} \ + ca-certificates", + pg_major + )); + + // Install extensions + println!("🔧 Installing extensions in parallel..."); + extensions::install(pg_version.clone()).await; + + // Clean up build packages to reduce image size + println!("🧹 Cleaning up to reduce image size..."); + run(&format!( + "apt-get purge -y --auto-remove \ + git \ + build-essential \ + postgresql-server-dev-{} \ + && apt-get autoremove -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf /tmp/* \ + && rm -rf /var/tmp/* \ + && rm -rf /root/.cache \ + && rm -rf /var/cache/apt/* \ + && rm -rf /usr/share/doc/* \ + && rm -rf /usr/share/man/* \ + && find /var/log -type f -delete", + pg_major + )); + + println!("✅ Installation completed successfully!"); +}