diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54b783b0..4fd62de8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -121,12 +121,24 @@ jobs: - linux/amd64 - linux/arm/v7 - linux/arm64 + variant: + - minimal + - duckdb + exclude: + # DuckDB ODBC is not available for armv7 + - platform: linux/arm/v7 + variant: duckdb steps: - name: Checkout uses: actions/checkout@v4 - id: suffix name: Cache name suffix - run: echo "suffix=-$(tr '/' '-' <<< ${{ matrix.platform }})" >> "$GITHUB_OUTPUT" + run: | + suffix="-$(tr '/' '-' <<< "${{ matrix.platform }}")" + if [[ "${{ matrix.variant }}" != "minimal" ]]; then + suffix="${suffix}-${{ matrix.variant }}" + fi + echo "suffix=${suffix}" >> "$GITHUB_OUTPUT" - name: Docker meta id: meta uses: docker/metadata-action@v5 @@ -149,6 +161,7 @@ jobs: with: context: . platforms: ${{ matrix.platform }} + target: ${{ matrix.variant }} labels: ${{ steps.meta.outputs.labels }} push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta.outputs.tags }} @@ -169,7 +182,7 @@ jobs: uses: actions/upload-artifact@v4 if: github.event_name != 'pull_request' with: - name: digests${{ steps.suffix.outputs.suffix }} + name: digests-${{ matrix.variant }}${{ steps.suffix.outputs.suffix }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 @@ -179,11 +192,16 @@ jobs: if: github.event_name != 'pull_request' needs: - docker_build + strategy: + matrix: + variant: + - minimal + - duckdb steps: - name: Download digests uses: actions/download-artifact@v4 with: - pattern: digests* + pattern: digests-${{ matrix.variant }}* merge-multiple: true path: /tmp/digests - name: Set up Docker Buildx @@ -193,6 +211,7 @@ jobs: uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} + flavor: suffix=${{ matrix.variant != 'minimal' && format('-{0}', matrix.variant) || '' }} - name: Login to Docker Hub uses: docker/login-action@v3 with: diff --git a/Dockerfile b/Dockerfile index fb79c864..a6ceb323 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,8 @@ RUN /usr/local/bin/build-dependencies.sh COPY . . RUN /usr/local/bin/build-project.sh -FROM busybox:glibc +# Default minimal image (busybox-based) +FROM busybox:glibc AS minimal RUN addgroup --gid 1000 --system sqlpage && \ adduser --uid 1000 --system --no-create-home --ingroup sqlpage sqlpage && \ mkdir -p /etc/sqlpage && \ @@ -30,4 +31,37 @@ COPY --from=builder /tmp/sqlpage-libs/* /lib/ USER sqlpage COPY --from=builder --chown=sqlpage:sqlpage /usr/src/sqlpage/sqlpage/sqlpage.db sqlpage/sqlpage.db EXPOSE 8080 -CMD ["/usr/local/bin/sqlpage"] \ No newline at end of file +CMD ["/usr/local/bin/sqlpage"] + +# DuckDB ODBC image (debian-based with DuckDB ODBC driver) +FROM debian:trixie-slim AS duckdb + +ARG TARGETARCH +ENV SQLPAGE_WEB_ROOT=/var/www +ENV SQLPAGE_CONFIGURATION_DIRECTORY=/etc/sqlpage +ENV DATABASE_URL="Driver=/opt/duckdb_odbc/libduckdb_odbc.so;Database=/var/lib/sqlpage/duckdb.db" + +COPY scripts/install-duckdb-odbc.sh scripts/setup-sqlpage-user.sh /usr/local/bin/ + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + unzip \ + adduser \ + odbcinst \ + unixodbc \ + && /usr/local/bin/install-duckdb-odbc.sh "$TARGETARCH" \ + && apt-get purge -y --auto-remove curl unzip \ + && rm -rf /var/lib/apt/lists/* + +RUN /usr/local/bin/setup-sqlpage-user.sh + +COPY --from=builder /usr/src/sqlpage/sqlpage.bin /usr/local/bin/sqlpage + +USER sqlpage +WORKDIR /var/www +EXPOSE 8080 +CMD ["/usr/local/bin/sqlpage"] + +# Default stage +FROM minimal diff --git a/README.md b/README.md index 66fcf064..b534bc8d 100644 --- a/README.md +++ b/README.md @@ -175,6 +175,17 @@ To run on a server, you can use [the docker image](https://hub.docker.com/r/lova We provide compiled binaries only for the x86_64 architecture, but provide docker images for other architectures, including arm64 and armv7. If you want to run SQLPage on a Raspberry Pi or a cheaper ARM cloud instance, using the docker image is the easiest way to do it. +#### DuckDB ODBC Docker Image + +A DuckDB-enabled variant is available with pre-installed DuckDB ODBC drivers: + +- Use the `-duckdb` suffix: `lovasoa/sqlpage:main-duckdb` or `lovasoa/sqlpage:latest-duckdb` +- Comes pre-configured to connect to DuckDB at `/var/lib/sqlpage/duckdb.db` +- To use a custom database location, set `DATABASE_URL`: + - `docker run -e DATABASE_URL="Driver=DuckDB;Database=/path/to/your.db" -p 8080:8080 lovasoa/sqlpage:main-duckdb` +- To persist your DuckDB database, mount a volume: + - `docker run -v ./data:/var/lib/sqlpage lovasoa/sqlpage:main-duckdb` + ### On Mac OS, with homebrew An alternative for Mac OS users is to use [SQLPage's homebrew package](https://formulae.brew.sh/formula/sqlpage). diff --git a/scripts/install-duckdb-odbc.sh b/scripts/install-duckdb-odbc.sh new file mode 100755 index 00000000..19a6225c --- /dev/null +++ b/scripts/install-duckdb-odbc.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -eux + +TARGETARCH="${1:-amd64}" +DUCKDB_VERSION="${2:-v1.4.3.0}" + +# Determine the correct DuckDB ODBC package for the architecture +case "$TARGETARCH" in + amd64) odbc_zip="duckdb_odbc-linux-amd64.zip" ;; + arm64) odbc_zip="duckdb_odbc-linux-arm64.zip" ;; + *) echo "Unsupported TARGETARCH: $TARGETARCH" >&2; exit 1 ;; +esac + +# Download and install DuckDB ODBC driver +curl -fsSL -o /tmp/duckdb_odbc.zip "https://github.com/duckdb/duckdb-odbc/releases/download/${DUCKDB_VERSION}/${odbc_zip}" +mkdir -p /opt/duckdb_odbc +unzip /tmp/duckdb_odbc.zip -d /opt/duckdb_odbc +rm /tmp/duckdb_odbc.zip + +# Configure ODBC driver in odbcinst.ini +cat >> /etc/odbcinst.ini << EOF + +[DuckDB] +Description=DuckDB ODBC Driver +Driver=/opt/duckdb_odbc/libduckdb_odbc.so +Setup=/opt/duckdb_odbc/libduckdb_odbc.so +UsageCount=1 +EOF + +# Configure default DuckDB data source in odbc.ini +cat >> /etc/odbc.ini << EOF + +[DuckDB] +Driver=DuckDB +Database=/var/lib/sqlpage/duckdb.db +EOF diff --git a/scripts/setup-sqlpage-user.sh b/scripts/setup-sqlpage-user.sh new file mode 100755 index 00000000..2977adf6 --- /dev/null +++ b/scripts/setup-sqlpage-user.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -eux + +# Create sqlpage user and group +addgroup --gid 1000 --system sqlpage +adduser --uid 1000 --system --no-create-home --ingroup sqlpage sqlpage + +# Create and configure directories +mkdir -p /etc/sqlpage /var/lib/sqlpage /var/www +chown -R sqlpage:sqlpage /etc/sqlpage /var/lib/sqlpage /var/www