diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml
deleted file mode 100644
index f7fb82953..000000000
--- a/.github/workflows/build-docker.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-name: Build Docker Images
-
-on:
- workflow_dispatch:
-
-jobs:
- build-images:
- runs-on: ubuntu-latest
-
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Build node-sqitch image
- working-directory: docker/node-sqitch
- run: docker build -t pyramation/node-sqitch:20.12.0 .
-
- - name: Build pgvector image
- working-directory: docker/pgvector
- run: docker build -t pyramation/node-sqitch-pgvector:20.12.0 .
\ No newline at end of file
diff --git a/.github/workflows/docker-launchql.yaml b/.github/workflows/docker-launchql.yaml
new file mode 100644
index 000000000..e3dfbf685
--- /dev/null
+++ b/.github/workflows/docker-launchql.yaml
@@ -0,0 +1,74 @@
+name: Docker LaunchQL
+
+on:
+ push:
+ branches:
+ - main
+ - v1
+ - release/*
+ pull_request:
+ branches:
+ - main
+ - v1
+ types: [opened, reopened, synchronize, ready_for_review]
+ workflow_dispatch: {}
+
+concurrency:
+ group: ${{ github.workflow }}-${{ github.ref }}-docker-launchql
+ cancel-in-progress: true
+
+jobs:
+ build-push-launchql:
+ if: github.event_name != 'pull_request' || !github.event.pull_request.draft
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: read
+ packages: write
+
+ env:
+ REPO: ghcr.io/${{ github.repository_owner }}
+ PLATFORMS: linux/amd64,linux/arm64
+
+ steps:
+ - name: Checkout
+ 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 GHCR
+ if: github.event_name != 'pull_request'
+ uses: docker/login-action@v3
+ with:
+ registry: ghcr.io
+ username: ${{ github.actor }}
+ password: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Extract metadata
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ env.REPO }}/launchql
+ tags: |
+ type=ref,event=branch
+ type=ref,event=pr
+ type=semver,pattern={{version}}
+ type=semver,pattern={{major}}.{{minor}}
+ type=sha,format=short,prefix=
+ type=raw,value=latest,enable={{is_default_branch}}
+
+ - name: Build and push
+ uses: docker/build-push-action@v5
+ with:
+ context: .
+ file: ./Dockerfile
+ platforms: ${{ env.PLATFORMS }}
+ 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/.github/workflows/docker.yaml b/.github/workflows/docker.yaml
index 6189fe6f7..ed208102d 100644
--- a/.github/workflows/docker.yaml
+++ b/.github/workflows/docker.yaml
@@ -20,7 +20,7 @@ on:
workflow_dispatch:
inputs:
process:
- description: 'Process to build (pgvector | node-sqitch | postgis | pgvector-postgis | launchql)'
+ description: 'Process to build (pgvector | node-sqitch | postgis | pgvector-postgis)'
type: choice
required: true
options:
@@ -28,7 +28,6 @@ on:
- node-sqitch
- postgis
- pgvector-postgis
- - launchql
default: pgvector
version:
description: 'Specific version to build (must exist in version.yaml)'
@@ -96,55 +95,3 @@ jobs:
REPO_NAME=$REPO \
PLATFORMS="$PLATFORMS" \
build-push-process
-
- build-launchql:
- if: github.event_name != 'pull_request' || !github.event.pull_request.draft
- runs-on: ubuntu-latest
-
- permissions:
- contents: read
- packages: write
-
- defaults:
- run:
- working-directory: docker
-
- env:
- REPO: ghcr.io/${{ github.repository_owner }}
- PLATFORMS: linux/amd64,linux/arm64
-
- steps:
- - name: Checkout
- 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 GHCR
- if: github.event_name != 'pull_request'
- uses: docker/login-action@v3
- with:
- registry: ghcr.io
- username: ${{ github.actor }}
- password: ${{ secrets.GITHUB_TOKEN }}
-
- - name: Build LaunchQL (no push)
- if: github.event_name == 'pull_request'
- run: |
- make \
- PROCESS=launchql \
- REPO_NAME=$REPO \
- PLATFORMS="$PLATFORMS" \
- build-process
-
- - name: Build and push LaunchQL (all versions)
- if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
- run: |
- make \
- PROCESS=launchql \
- REPO_NAME=$REPO \
- PLATFORMS="$PLATFORMS" \
- build-push-process
diff --git a/docker/launchql/Dockerfile b/Dockerfile
similarity index 99%
rename from docker/launchql/Dockerfile
rename to Dockerfile
index f45fce538..15c687a84 100644
--- a/docker/launchql/Dockerfile
+++ b/Dockerfile
@@ -54,3 +54,4 @@ RUN set -eux; \
ENTRYPOINT ["/usr/local/bin/lql"]
CMD ["--help"]
+
diff --git a/docker/Makefile b/docker/Makefile
index 4e251f212..255d5010e 100644
--- a/docker/Makefile
+++ b/docker/Makefile
@@ -7,8 +7,8 @@ PLATFORMS?=linux/arm64
# default process if none specified (can be overridden: `make PROCESS=postgis build-process`)
PROCESS?=pgvector
-# Convenience: list of known processes
-PROCESSES:=pgvector node-sqitch postgis pgvector-postgis launchql
+# Convenience: list of known processes (launchql moved to root Dockerfile)
+PROCESSES:=pgvector node-sqitch postgis pgvector-postgis
CONTAINER_NAME?=$(PROCESS)
@@ -54,20 +54,13 @@ build-process-version:
@test -n "$(BASE)" || { echo "Error: BASE is required"; exit 1; }
@test -n "$(VERSION)" || { echo "Error: VERSION is required"; exit 1; }
@echo " -> $(BASE):$(VERSION) => $(REPO_NAME)/$(PROCESS):$(VERSION) (build)"
- @DOCKERFILE_PATH="$(PROCESS)/Dockerfile"; \
- CONTEXT=$$( \
- if [ "$(PROCESS)" = "launchql" ]; then \
- echo ".."; \
- else \
- echo "$(PROCESS)"; \
- fi ); \
- docker buildx build \
+ @docker buildx build \
--platform $(PLATFORMS) \
--build-arg BASE=$(BASE) \
--build-arg BASE_VERSION=$(VERSION) \
- --file $$DOCKERFILE_PATH \
+ --file $(PROCESS)/Dockerfile \
-t $(REPO_NAME)/$(PROCESS):$(VERSION) \
- $$CONTEXT
+ $(PROCESS)
# Build+push only a specific VERSION for $(PROCESS). Intended for internal use by build-push-process.
# Usage (internal): $(MAKE) BASE= VERSION= build-push-process-version
@@ -75,21 +68,14 @@ build-push-process-version:
@test -n "$(BASE)" || { echo "Error: BASE is required"; exit 1; }
@test -n "$(VERSION)" || { echo "Error: VERSION is required"; exit 1; }
@echo " -> $(BASE):$(VERSION) => $(REPO_NAME)/$(PROCESS):$(VERSION) (push)"
- @DOCKERFILE_PATH="$(PROCESS)/Dockerfile"; \
- CONTEXT=$$( \
- if [ "$(PROCESS)" = "launchql" ]; then \
- echo ".."; \
- else \
- echo "$(PROCESS)"; \
- fi ); \
- docker buildx build \
+ @docker buildx build \
--platform $(PLATFORMS) \
--build-arg BASE=$(BASE) \
--build-arg BASE_VERSION=$(VERSION) \
- --file $$DOCKERFILE_PATH \
+ --file $(PROCESS)/Dockerfile \
-t $(REPO_NAME)/$(PROCESS):$(VERSION) \
--push \
- $$CONTEXT
+ $(PROCESS)
# Aliases
all: build-all
@@ -107,6 +93,3 @@ postgis:
pgvector-postgis:
$(MAKE) PROCESS=pgvector-postgis build-process
-
-launchql:
- $(MAKE) PROCESS=launchql build-process
diff --git a/docker/README.md b/docker/README.md
index 7b392d76b..2f8a977ac 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -1,3 +1,78 @@
-# Docker Image
+# Docker Images
+
+This directory contains Dockerfiles for PostgreSQL-based images that extend the official PostgreSQL images with additional extensions and tools.
+
+## Available Images
+
+- **pgvector** - PostgreSQL with pgvector extension for vector similarity search
+- **postgis** - PostgreSQL with PostGIS extension for spatial/geographic data
+- **pgvector-postgis** - PostgreSQL with both pgvector and PostGIS extensions, plus CloudNativePG compatibility (pgaudit, pg-failover-slots, barman-cloud)
+- **node-sqitch** - Node.js with Sqitch for database change management
+
+## LaunchQL Main Image
+
+The main LaunchQL application image (built from the codebase) is now at the **root** of the repository:
+- **Dockerfile**: `/Dockerfile` (root level)
+- **GitHub Action**: `.github/workflows/docker-launchql.yaml`
+
+The base image and version are specified directly in the Dockerfile using ARG directives. This separation keeps codebase-dependent images separate from extension-only images.
+
+## Building Images
+
+### Building Extension Images (this directory)
+
+```bash
+# Build a specific process
+make PROCESS=pgvector build-process
+
+# Build all processes
+make build-all
+
+# Build and push a specific process
+make PROCESS=pgvector-postgis build-push-process
+
+# Build and push all processes
+make build-push-all
+```
+
+### Building LaunchQL Image (root level)
+
+```bash
+# From the root of the repository (uses default versions from Dockerfile)
+docker buildx build \
+ --platform linux/amd64,linux/arm64 \
+ --file Dockerfile \
+ -t ghcr.io/launchql/launchql:latest \
+ .
+
+# Or override base/version with build args
+docker buildx build \
+ --platform linux/amd64,linux/arm64 \
+ --build-arg BASE=node \
+ --build-arg BASE_VERSION=22-bookworm \
+ --file Dockerfile \
+ -t ghcr.io/launchql/launchql:22-bookworm \
+ .
+```
+
+## GitHub Actions
+
+- **docker.yaml** - Builds extension images from this directory (pgvector, postgis, etc.)
+- **docker-launchql.yaml** - Builds the main LaunchQL image from the root Dockerfile
+
+## Version Configuration
+
+Each image directory contains a `version.yaml` file that specifies:
+- `base`: The base Docker image to use
+- `versions`: List of version tags to build
+
+Example:
+```yaml
+base: postgres
+versions:
+ - 14
+ - 15
+ - 16
+```
diff --git a/docker/launchql/version.yaml b/docker/launchql/version.yaml
deleted file mode 100644
index ed9cabf40..000000000
--- a/docker/launchql/version.yaml
+++ /dev/null
@@ -1,4 +0,0 @@
-base: node
-versions:
- - 20-bookworm
-
diff --git a/docker/pgvector-postgis/Dockerfile b/docker/pgvector-postgis/Dockerfile
index 94ee4a0ec..e2c361553 100644
--- a/docker/pgvector-postgis/Dockerfile
+++ b/docker/pgvector-postgis/Dockerfile
@@ -1,13 +1,17 @@
ARG BASE=postgres
ARG BASE_VERSION=14
+ARG BARMAN_VERSION=3.14.0
FROM ${BASE}:${BASE_VERSION}
LABEL org.opencontainers.image.source="https://github.com/launchql/launchql"
ARG BASE
ARG BASE_VERSION
+ARG BARMAN_VERSION
ENV BASE_VERSION=${BASE_VERSION}
+ENV PIP_BREAK_SYSTEM_PACKAGES=1
# Debian-based: install both pgvector and postgis from PGDG per-PG-major
+# Plus CloudNativePG requirements: pgaudit, pg-failover-slots, barman-cloud
RUN set -eux; \
export DEBIAN_FRONTEND=noninteractive; \
apt-get update; \
@@ -24,7 +28,22 @@ RUN set -eux; \
postgresql-${PG_MAJOR}-postgis-3-scripts \
postgis \
postgresql-${PG_MAJOR}-pgvector \
+ postgresql-${PG_MAJOR}-pgaudit \
+ postgresql-${PG_MAJOR}-pg-failover-slots \
+ locales-all \
+ build-essential \
+ python3-dev \
+ python3-pip \
+ python3-psycopg2 \
+ python3-setuptools \
make \
bash; \
- rm -rf /var/lib/apt/lists/*
+ pip3 install --no-cache-dir barman[cloud,azure,snappy,google,zstandard,lz4]==${BARMAN_VERSION}; \
+ apt-get remove -y --purge --autoremove build-essential python3-dev; \
+ apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
+ rm -rf /var/lib/apt/lists/* /var/cache/* /var/log/*
+# Change postgres user to UID 26 for CloudNativePG compatibility
+RUN usermod -u 26 postgres
+
+USER 26