update with latest build versions, includes custom build for postgres and migrating from v16 to v18
This commit is contained in:
@@ -1,35 +1,270 @@
|
||||
# CloudNativePG-compatible PostGIS image
|
||||
# Uses imresamu/postgis as base which has ARM64 support
|
||||
FROM imresamu/postgis:16-3.4
|
||||
# =============================================================================
|
||||
# PostgreSQL 18 + PostGIS 3.6 for CloudNativePG (ARM64 build from source)
|
||||
# =============================================================================
|
||||
# This Dockerfile builds PostGIS from source for ARM64 architecture since
|
||||
# the official postgis/postgis images don't have ARM64 support for PG18 yet.
|
||||
#
|
||||
# Build: docker build --platform linux/arm64 -t cnpg-postgis:18-3.6 .
|
||||
# Test: docker run --rm -e POSTGRES_PASSWORD=test cnpg-postgis:18-3.6 postgres --version
|
||||
# =============================================================================
|
||||
|
||||
# Get additional tools from CloudNativePG image
|
||||
FROM ghcr.io/cloudnative-pg/postgresql:16.6 as cnpg-tools
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build arguments - Pin versions for reproducible builds
|
||||
# -----------------------------------------------------------------------------
|
||||
ARG PG_MAJOR=18
|
||||
ARG POSTGIS_VERSION=3.6.1
|
||||
ARG GEOS_VERSION=3.13.0
|
||||
# PROJ 9.4.1 is more stable for building; 9.5.x has additional deps
|
||||
ARG PROJ_VERSION=9.4.1
|
||||
ARG GDAL_VERSION=3.10.1
|
||||
ARG SFCGAL_VERSION=2.0.0
|
||||
|
||||
# Final stage: PostGIS with CloudNativePG tools
|
||||
FROM imresamu/postgis:16-3.4
|
||||
# =============================================================================
|
||||
# Stage 1: Build PostGIS and dependencies from source
|
||||
# =============================================================================
|
||||
FROM postgres:${PG_MAJOR}-bookworm AS builder
|
||||
|
||||
USER root
|
||||
ARG PG_MAJOR
|
||||
ARG POSTGIS_VERSION
|
||||
ARG GEOS_VERSION
|
||||
ARG PROJ_VERSION
|
||||
ARG GDAL_VERSION
|
||||
|
||||
# Fix user ID compatibility with CloudNativePG (user ID 26)
|
||||
# CloudNativePG expects postgres user to have ID 26, but imresamu/postgis uses 999
|
||||
# The tape group (ID 26) already exists, so we'll change postgres user to use it
|
||||
RUN usermod -u 26 -g 26 postgres && \
|
||||
delgroup postgres && \
|
||||
chown -R postgres:tape /var/lib/postgresql && \
|
||||
chown -R postgres:tape /var/run/postgresql
|
||||
|
||||
# Copy barman and other tools from CloudNativePG image
|
||||
COPY --from=cnpg-tools /usr/local/bin/barman* /usr/local/bin/
|
||||
|
||||
# Install any additional packages that CloudNativePG might need
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends \
|
||||
curl \
|
||||
jq \
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# Build tools
|
||||
build-essential \
|
||||
cmake \
|
||||
ninja-build \
|
||||
pkg-config \
|
||||
git \
|
||||
wget \
|
||||
ca-certificates \
|
||||
# PostgreSQL development
|
||||
postgresql-server-dev-${PG_MAJOR} \
|
||||
# Required libraries
|
||||
libxml2-dev \
|
||||
libjson-c-dev \
|
||||
libprotobuf-c-dev \
|
||||
protobuf-c-compiler \
|
||||
libsqlite3-dev \
|
||||
sqlite3 \
|
||||
libtiff-dev \
|
||||
libcurl4-openssl-dev \
|
||||
libssl-dev \
|
||||
zlib1g-dev \
|
||||
liblzma-dev \
|
||||
libzstd-dev \
|
||||
libpng-dev \
|
||||
libjpeg-dev \
|
||||
libwebp-dev \
|
||||
# Additional dependencies
|
||||
libpcre2-dev \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
# PROJ additional requirements
|
||||
nlohmann-json3-dev \
|
||||
libgeotiff-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Switch back to postgres user (now with correct ID 26)
|
||||
WORKDIR /build
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build GEOS (Geometry Engine)
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN wget -q https://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& tar xjf geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& cd geos-${GEOS_VERSION} \
|
||||
&& mkdir build && cd build \
|
||||
&& cmake .. \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF \
|
||||
&& ninja \
|
||||
&& ninja install \
|
||||
&& cd /build && rm -rf geos-*
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build PROJ (Cartographic Projections)
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN wget -q https://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz \
|
||||
&& tar xzf proj-${PROJ_VERSION}.tar.gz \
|
||||
&& cd proj-${PROJ_VERSION} \
|
||||
&& mkdir build && cd build \
|
||||
&& cmake .. \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DENABLE_CURL=ON \
|
||||
-DENABLE_TIFF=ON \
|
||||
&& ninja \
|
||||
&& ninja install \
|
||||
&& cd /build && rm -rf proj-*
|
||||
|
||||
# Update library cache after PROJ install
|
||||
RUN ldconfig
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build GDAL (Geospatial Data Abstraction Library)
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN wget -q https://github.com/OSGeo/gdal/releases/download/v${GDAL_VERSION}/gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& tar xzf gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& cd gdal-${GDAL_VERSION} \
|
||||
&& mkdir build && cd build \
|
||||
&& cmake .. \
|
||||
-G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF \
|
||||
-DBUILD_APPS=OFF \
|
||||
-DGDAL_BUILD_OPTIONAL_DRIVERS=OFF \
|
||||
-DOGR_BUILD_OPTIONAL_DRIVERS=OFF \
|
||||
-DGDAL_USE_GEOS=ON \
|
||||
-DGDAL_USE_PROJ=ON \
|
||||
-DGDAL_USE_TIFF=ON \
|
||||
-DGDAL_USE_GEOTIFF=ON \
|
||||
-DGDAL_USE_PNG=ON \
|
||||
-DGDAL_USE_JPEG=ON \
|
||||
-DGDAL_USE_WEBP=ON \
|
||||
-DGDAL_USE_CURL=ON \
|
||||
-DGDAL_USE_SQLITE3=ON \
|
||||
-DGDAL_USE_POSTGRESQL=ON \
|
||||
&& ninja \
|
||||
&& ninja install \
|
||||
&& cd /build && rm -rf gdal-*
|
||||
|
||||
# Update library cache after GDAL install
|
||||
RUN ldconfig
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build PostGIS
|
||||
# -----------------------------------------------------------------------------
|
||||
# Set library paths so configure can find GDAL, GEOS, PROJ
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||
|
||||
RUN wget -q https://download.osgeo.org/postgis/source/postgis-${POSTGIS_VERSION}.tar.gz \
|
||||
&& tar xzf postgis-${POSTGIS_VERSION}.tar.gz \
|
||||
&& cd postgis-${POSTGIS_VERSION} \
|
||||
&& LDFLAGS="-L/usr/local/lib" \
|
||||
CPPFLAGS="-I/usr/local/include" \
|
||||
./configure \
|
||||
--with-pgconfig=/usr/lib/postgresql/${PG_MAJOR}/bin/pg_config \
|
||||
--with-geosconfig=/usr/local/bin/geos-config \
|
||||
--with-projdir=/usr/local \
|
||||
--with-gdalconfig=/usr/local/bin/gdal-config \
|
||||
--with-protobufdir=/usr \
|
||||
--without-sfcgal \
|
||||
&& make -j$(nproc) \
|
||||
&& make install DESTDIR=/postgis-install \
|
||||
&& cd /build && rm -rf postgis-*
|
||||
|
||||
# =============================================================================
|
||||
# Stage 2: Get CNPG tools (barman-cloud for backup/restore)
|
||||
# =============================================================================
|
||||
FROM ghcr.io/cloudnative-pg/postgresql:${PG_MAJOR} AS cnpg-tools
|
||||
|
||||
# =============================================================================
|
||||
# Stage 3: Final runtime image
|
||||
# =============================================================================
|
||||
FROM postgres:${PG_MAJOR}-bookworm
|
||||
|
||||
ARG PG_MAJOR
|
||||
ARG POSTGIS_VERSION
|
||||
|
||||
LABEL maintainer="Keyboard Vagabond <admin@mail.keyboardvagabond.com>"
|
||||
LABEL description="PostgreSQL ${PG_MAJOR} with PostGIS ${POSTGIS_VERSION} for CloudNativePG (ARM64)"
|
||||
LABEL org.opencontainers.image.source="https://keyboardvagabond.com"
|
||||
|
||||
ENV POSTGIS_MAJOR=3
|
||||
ENV POSTGIS_VERSION=${POSTGIS_VERSION}
|
||||
|
||||
# Install runtime dependencies only (no build tools)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# Runtime libraries for GEOS/PROJ/GDAL/PostGIS
|
||||
libxml2 \
|
||||
libjson-c5 \
|
||||
libprotobuf-c1 \
|
||||
libsqlite3-0 \
|
||||
libtiff6 \
|
||||
libcurl4 \
|
||||
libssl3 \
|
||||
zlib1g \
|
||||
liblzma5 \
|
||||
libzstd1 \
|
||||
libpng16-16 \
|
||||
libjpeg62-turbo \
|
||||
libwebp7 \
|
||||
libpcre2-8-0 \
|
||||
# Additional utilities
|
||||
ca-certificates \
|
||||
curl \
|
||||
jq \
|
||||
# Python for barman-cloud
|
||||
python3 \
|
||||
python3-boto3 \
|
||||
python3-botocore \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy compiled libraries from builder
|
||||
COPY --from=builder /usr/local/lib/ /usr/local/lib/
|
||||
COPY --from=builder /usr/local/share/proj/ /usr/local/share/proj/
|
||||
COPY --from=builder /usr/local/share/gdal/ /usr/local/share/gdal/
|
||||
COPY --from=builder /usr/local/bin/geos-config /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/gdal-config /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/proj /usr/local/bin/
|
||||
COPY --from=builder /usr/local/bin/projinfo /usr/local/bin/
|
||||
|
||||
# Copy PostGIS installation (modern PostGIS uses extension dir, not contrib)
|
||||
COPY --from=builder /postgis-install/usr/lib/postgresql/${PG_MAJOR}/lib/ /usr/lib/postgresql/${PG_MAJOR}/lib/
|
||||
COPY --from=builder /postgis-install/usr/share/postgresql/${PG_MAJOR}/extension/ /usr/share/postgresql/${PG_MAJOR}/extension/
|
||||
|
||||
# Update library cache
|
||||
RUN ldconfig
|
||||
|
||||
# Copy barman-cloud tools from CNPG image (they're in /usr/local/bin/)
|
||||
COPY --from=cnpg-tools /usr/local/bin/barman* /usr/local/bin/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Fix user ID for CloudNativePG compatibility (requires UID 26)
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN set -eux; \
|
||||
CURRENT_UID=$(id -u postgres); \
|
||||
if [ "$CURRENT_UID" != "26" ]; then \
|
||||
# Check if UID 26 is already in use
|
||||
if getent passwd 26 >/dev/null 2>&1; then \
|
||||
EXISTING_USER=$(getent passwd 26 | cut -d: -f1); \
|
||||
usermod -u 9999 "$EXISTING_USER" 2>/dev/null || true; \
|
||||
fi; \
|
||||
# Change postgres user to UID 26
|
||||
usermod -u 26 postgres; \
|
||||
# Fix ownership of postgres directories
|
||||
find /var/lib/postgresql -user $CURRENT_UID -exec chown -h 26 {} \; 2>/dev/null || true; \
|
||||
find /var/run/postgresql -user $CURRENT_UID -exec chown -h 26 {} \; 2>/dev/null || true; \
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql 2>/dev/null || true; \
|
||||
fi
|
||||
|
||||
# Copy initialization and update scripts
|
||||
RUN mkdir -p /docker-entrypoint-initdb.d
|
||||
COPY ./initdb-postgis.sh /docker-entrypoint-initdb.d/10_postgis.sh
|
||||
COPY ./update-postgis.sh /usr/local/bin/
|
||||
RUN chmod +x /docker-entrypoint-initdb.d/10_postgis.sh /usr/local/bin/update-postgis.sh
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Verify installation
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN set -eux; \
|
||||
postgres --version; \
|
||||
echo "GEOS: $(geos-config --version)"; \
|
||||
echo "PROJ: $(projinfo 2>&1 | head -1 || echo 'installed')"; \
|
||||
echo "GDAL: $(gdal-config --version)"; \
|
||||
id postgres; \
|
||||
ls -la /usr/lib/postgresql/${PG_MAJOR}/lib/postgis*.so || true
|
||||
|
||||
# Switch to postgres user
|
||||
USER postgres
|
||||
|
||||
# Keep the standard PostgreSQL entrypoint
|
||||
# CloudNativePG operator will manage the container lifecycle
|
||||
EXPOSE 5432
|
||||
|
||||
267
build/postgresql-postgis/Dockerfile.upgrade
Normal file
267
build/postgresql-postgis/Dockerfile.upgrade
Normal file
@@ -0,0 +1,267 @@
|
||||
# =============================================================================
|
||||
# PostgreSQL 16→18 Upgrade Image for CloudNativePG pg_upgrade
|
||||
# =============================================================================
|
||||
# This special image contains BOTH PG16 and PG18 binaries + PostGIS, required
|
||||
# for CloudNativePG's declarative pg_upgrade feature.
|
||||
#
|
||||
# Use this image ONLY for the upgrade process. After upgrade completes,
|
||||
# switch to the regular cnpg-postgis:18-3.6 image.
|
||||
#
|
||||
# Build: docker build --platform linux/arm64 -f Dockerfile.upgrade -t cnpg-postgis:upgrade-16-to-18 .
|
||||
# =============================================================================
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build arguments - Pin versions for reproducible builds
|
||||
# -----------------------------------------------------------------------------
|
||||
ARG PG_OLD=16
|
||||
ARG PG_NEW=18
|
||||
ARG POSTGIS_OLD=3.4.3
|
||||
ARG POSTGIS_NEW=3.6.1
|
||||
ARG GEOS_VERSION=3.13.0
|
||||
ARG PROJ_VERSION=9.4.1
|
||||
ARG GDAL_VERSION=3.10.1
|
||||
|
||||
# =============================================================================
|
||||
# Stage 1: Build PostGIS for PG16 (old version)
|
||||
# =============================================================================
|
||||
FROM postgres:16-bookworm AS builder-pg16
|
||||
|
||||
ARG POSTGIS_OLD
|
||||
ARG GEOS_VERSION
|
||||
ARG PROJ_VERSION
|
||||
ARG GDAL_VERSION
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential cmake ninja-build pkg-config git wget ca-certificates \
|
||||
postgresql-server-dev-16 \
|
||||
libxml2-dev libjson-c-dev libprotobuf-c-dev protobuf-c-compiler \
|
||||
libsqlite3-dev sqlite3 libtiff-dev libcurl4-openssl-dev libssl-dev \
|
||||
zlib1g-dev liblzma-dev libzstd-dev libpng-dev libjpeg-dev libwebp-dev \
|
||||
libpcre2-dev autoconf automake libtool nlohmann-json3-dev libgeotiff-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Build GEOS
|
||||
RUN wget -q https://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& tar xjf geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& cd geos-${GEOS_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTING=OFF \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf geos-*
|
||||
|
||||
# Build PROJ
|
||||
RUN wget -q https://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz \
|
||||
&& tar xzf proj-${PROJ_VERSION}.tar.gz \
|
||||
&& cd proj-${PROJ_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF -DENABLE_CURL=ON -DENABLE_TIFF=ON \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf proj-* && ldconfig
|
||||
|
||||
# Build GDAL
|
||||
RUN wget -q https://github.com/OSGeo/gdal/releases/download/v${GDAL_VERSION}/gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& tar xzf gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& cd gdal-${GDAL_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF -DBUILD_APPS=OFF \
|
||||
-DGDAL_BUILD_OPTIONAL_DRIVERS=OFF -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \
|
||||
-DGDAL_USE_GEOS=ON -DGDAL_USE_PROJ=ON -DGDAL_USE_TIFF=ON \
|
||||
-DGDAL_USE_GEOTIFF=ON -DGDAL_USE_PNG=ON -DGDAL_USE_JPEG=ON \
|
||||
-DGDAL_USE_WEBP=ON -DGDAL_USE_CURL=ON -DGDAL_USE_SQLITE3=ON \
|
||||
-DGDAL_USE_POSTGRESQL=ON \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf gdal-* && ldconfig
|
||||
|
||||
# Build PostGIS for PG16
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||
|
||||
RUN wget -q https://download.osgeo.org/postgis/source/postgis-${POSTGIS_OLD}.tar.gz \
|
||||
&& tar xzf postgis-${POSTGIS_OLD}.tar.gz \
|
||||
&& cd postgis-${POSTGIS_OLD} \
|
||||
&& LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include" \
|
||||
./configure \
|
||||
--with-pgconfig=/usr/lib/postgresql/16/bin/pg_config \
|
||||
--with-geosconfig=/usr/local/bin/geos-config \
|
||||
--with-projdir=/usr/local \
|
||||
--with-gdalconfig=/usr/local/bin/gdal-config \
|
||||
--with-protobufdir=/usr \
|
||||
--without-sfcgal \
|
||||
&& make -j$(nproc) \
|
||||
&& make install DESTDIR=/postgis-install-pg16 \
|
||||
&& cd /build && rm -rf postgis-*
|
||||
|
||||
# =============================================================================
|
||||
# Stage 2: Build PostGIS for PG18 (new version)
|
||||
# =============================================================================
|
||||
FROM postgres:18-bookworm AS builder-pg18
|
||||
|
||||
ARG POSTGIS_NEW
|
||||
ARG GEOS_VERSION
|
||||
ARG PROJ_VERSION
|
||||
ARG GDAL_VERSION
|
||||
|
||||
# Install build dependencies (same as PG16)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential cmake ninja-build pkg-config git wget ca-certificates \
|
||||
postgresql-server-dev-18 \
|
||||
libxml2-dev libjson-c-dev libprotobuf-c-dev protobuf-c-compiler \
|
||||
libsqlite3-dev sqlite3 libtiff-dev libcurl4-openssl-dev libssl-dev \
|
||||
zlib1g-dev liblzma-dev libzstd-dev libpng-dev libjpeg-dev libwebp-dev \
|
||||
libpcre2-dev autoconf automake libtool nlohmann-json3-dev libgeotiff-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /build
|
||||
|
||||
# Build GEOS
|
||||
RUN wget -q https://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& tar xjf geos-${GEOS_VERSION}.tar.bz2 \
|
||||
&& cd geos-${GEOS_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTING=OFF \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf geos-*
|
||||
|
||||
# Build PROJ
|
||||
RUN wget -q https://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz \
|
||||
&& tar xzf proj-${PROJ_VERSION}.tar.gz \
|
||||
&& cd proj-${PROJ_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF -DENABLE_CURL=ON -DENABLE_TIFF=ON \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf proj-* && ldconfig
|
||||
|
||||
# Build GDAL
|
||||
RUN wget -q https://github.com/OSGeo/gdal/releases/download/v${GDAL_VERSION}/gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& tar xzf gdal-${GDAL_VERSION}.tar.gz \
|
||||
&& cd gdal-${GDAL_VERSION} && mkdir build && cd build \
|
||||
&& cmake .. -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local \
|
||||
-DBUILD_TESTING=OFF -DBUILD_APPS=OFF \
|
||||
-DGDAL_BUILD_OPTIONAL_DRIVERS=OFF -DOGR_BUILD_OPTIONAL_DRIVERS=OFF \
|
||||
-DGDAL_USE_GEOS=ON -DGDAL_USE_PROJ=ON -DGDAL_USE_TIFF=ON \
|
||||
-DGDAL_USE_GEOTIFF=ON -DGDAL_USE_PNG=ON -DGDAL_USE_JPEG=ON \
|
||||
-DGDAL_USE_WEBP=ON -DGDAL_USE_CURL=ON -DGDAL_USE_SQLITE3=ON \
|
||||
-DGDAL_USE_POSTGRESQL=ON \
|
||||
&& ninja && ninja install \
|
||||
&& cd /build && rm -rf gdal-* && ldconfig
|
||||
|
||||
# Build PostGIS for PG18
|
||||
ENV LD_LIBRARY_PATH=/usr/local/lib
|
||||
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
|
||||
|
||||
RUN wget -q https://download.osgeo.org/postgis/source/postgis-${POSTGIS_NEW}.tar.gz \
|
||||
&& tar xzf postgis-${POSTGIS_NEW}.tar.gz \
|
||||
&& cd postgis-${POSTGIS_NEW} \
|
||||
&& LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include" \
|
||||
./configure \
|
||||
--with-pgconfig=/usr/lib/postgresql/18/bin/pg_config \
|
||||
--with-geosconfig=/usr/local/bin/geos-config \
|
||||
--with-projdir=/usr/local \
|
||||
--with-gdalconfig=/usr/local/bin/gdal-config \
|
||||
--with-protobufdir=/usr \
|
||||
--without-sfcgal \
|
||||
&& make -j$(nproc) \
|
||||
&& make install DESTDIR=/postgis-install-pg18 \
|
||||
&& cd /build && rm -rf postgis-*
|
||||
|
||||
# =============================================================================
|
||||
# Stage 3: Get CNPG tools
|
||||
# =============================================================================
|
||||
FROM ghcr.io/cloudnative-pg/postgresql:18 AS cnpg-tools
|
||||
|
||||
# =============================================================================
|
||||
# Stage 4: Final multi-version runtime image
|
||||
# =============================================================================
|
||||
FROM postgres:18-bookworm
|
||||
|
||||
ARG PG_OLD=16
|
||||
ARG PG_NEW=18
|
||||
ARG POSTGIS_NEW
|
||||
|
||||
LABEL maintainer="Keyboard Vagabond <admin@mail.keyboardvagabond.com>"
|
||||
LABEL description="PostgreSQL 16→18 upgrade image with PostGIS for CloudNativePG pg_upgrade (ARM64)"
|
||||
LABEL org.opencontainers.image.source="https://keyboardvagabond.com"
|
||||
LABEL pg.upgrade.from="16"
|
||||
LABEL pg.upgrade.to="18"
|
||||
|
||||
ENV POSTGIS_MAJOR=3
|
||||
ENV POSTGIS_VERSION=${POSTGIS_NEW}
|
||||
|
||||
# Install runtime dependencies + PostgreSQL 16 binaries
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
# Runtime libraries for GEOS/PROJ/GDAL/PostGIS
|
||||
libxml2 libjson-c5 libprotobuf-c1 libsqlite3-0 libtiff6 libcurl4 \
|
||||
libssl3 zlib1g liblzma5 libzstd1 libpng16-16 libjpeg62-turbo libwebp7 \
|
||||
libpcre2-8-0 ca-certificates curl jq \
|
||||
# Python for barman-cloud
|
||||
python3 python3-boto3 python3-botocore \
|
||||
# PostgreSQL 16 binaries (required for pg_upgrade)
|
||||
postgresql-16 \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Copy compiled libraries from PG18 builder (shared between both versions)
|
||||
COPY --from=builder-pg18 /usr/local/lib/ /usr/local/lib/
|
||||
COPY --from=builder-pg18 /usr/local/share/proj/ /usr/local/share/proj/
|
||||
COPY --from=builder-pg18 /usr/local/share/gdal/ /usr/local/share/gdal/
|
||||
COPY --from=builder-pg18 /usr/local/bin/geos-config /usr/local/bin/
|
||||
COPY --from=builder-pg18 /usr/local/bin/gdal-config /usr/local/bin/
|
||||
COPY --from=builder-pg18 /usr/local/bin/proj /usr/local/bin/
|
||||
COPY --from=builder-pg18 /usr/local/bin/projinfo /usr/local/bin/
|
||||
|
||||
# Copy PostGIS for PG16 (old version)
|
||||
COPY --from=builder-pg16 /postgis-install-pg16/usr/lib/postgresql/16/lib/ /usr/lib/postgresql/16/lib/
|
||||
COPY --from=builder-pg16 /postgis-install-pg16/usr/share/postgresql/16/extension/ /usr/share/postgresql/16/extension/
|
||||
|
||||
# Copy PostGIS for PG18 (new version)
|
||||
COPY --from=builder-pg18 /postgis-install-pg18/usr/lib/postgresql/18/lib/ /usr/lib/postgresql/18/lib/
|
||||
COPY --from=builder-pg18 /postgis-install-pg18/usr/share/postgresql/18/extension/ /usr/share/postgresql/18/extension/
|
||||
|
||||
# Update library cache
|
||||
RUN ldconfig
|
||||
|
||||
# Copy barman-cloud tools from CNPG image
|
||||
COPY --from=cnpg-tools /usr/local/bin/barman* /usr/local/bin/
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Fix user ID for CloudNativePG compatibility (requires UID 26)
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN set -eux; \
|
||||
CURRENT_UID=$(id -u postgres); \
|
||||
if [ "$CURRENT_UID" != "26" ]; then \
|
||||
if getent passwd 26 >/dev/null 2>&1; then \
|
||||
EXISTING_USER=$(getent passwd 26 | cut -d: -f1); \
|
||||
usermod -u 9999 "$EXISTING_USER" 2>/dev/null || true; \
|
||||
fi; \
|
||||
usermod -u 26 postgres; \
|
||||
find /var/lib/postgresql -user $CURRENT_UID -exec chown -h 26 {} \; 2>/dev/null || true; \
|
||||
find /var/run/postgresql -user $CURRENT_UID -exec chown -h 26 {} \; 2>/dev/null || true; \
|
||||
chown -R postgres:postgres /var/lib/postgresql /var/run/postgresql 2>/dev/null || true; \
|
||||
fi
|
||||
|
||||
# Copy initialization scripts
|
||||
RUN mkdir -p /docker-entrypoint-initdb.d
|
||||
COPY ./initdb-postgis.sh /docker-entrypoint-initdb.d/10_postgis.sh
|
||||
COPY ./update-postgis.sh /usr/local/bin/
|
||||
RUN chmod +x /docker-entrypoint-initdb.d/10_postgis.sh /usr/local/bin/update-postgis.sh
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Verify installation - both PG versions and PostGIS
|
||||
# -----------------------------------------------------------------------------
|
||||
RUN set -eux; \
|
||||
echo "=== PostgreSQL Versions ==="; \
|
||||
/usr/lib/postgresql/16/bin/postgres --version; \
|
||||
/usr/lib/postgresql/18/bin/postgres --version; \
|
||||
echo "=== PostGIS Libraries ==="; \
|
||||
ls -la /usr/lib/postgresql/16/lib/postgis*.so; \
|
||||
ls -la /usr/lib/postgresql/18/lib/postgis*.so; \
|
||||
echo "=== pg_upgrade Available ==="; \
|
||||
/usr/lib/postgresql/18/bin/pg_upgrade --version; \
|
||||
echo "=== Shared Libraries ==="; \
|
||||
echo "GEOS: $(geos-config --version)"; \
|
||||
echo "GDAL: $(gdal-config --version)"; \
|
||||
id postgres
|
||||
|
||||
USER postgres
|
||||
|
||||
EXPOSE 5432
|
||||
184
build/postgresql-postgis/Migration_Plan.md
Normal file
184
build/postgresql-postgis/Migration_Plan.md
Normal file
@@ -0,0 +1,184 @@
|
||||
# PostgreSQL 18 + PostGIS 3.6 for CloudNativePG (ARM64 Source Build)
|
||||
|
||||
## Overview
|
||||
|
||||
Upgrade from PostgreSQL 16 to PostgreSQL 18 with PostGIS 3.6 for ARM64 CloudNativePG deployment.
|
||||
|
||||
**Why build from source?**
|
||||
- The official `postgis/postgis:18-3.6` image only supports AMD64, not ARM64
|
||||
- `imresamu/postgis` hasn't released PG18 ARM64 images yet
|
||||
- Building from source ensures ARM64 compatibility for your cluster
|
||||
|
||||
**Current Setup:**
|
||||
- Image: `registry.keyboardvagabond.com/library/cnpg-postgis:16.6-3.4-v2`
|
||||
- Base: `imresamu/postgis:16-3.4`
|
||||
- PostgreSQL: 16.6
|
||||
- PostGIS: 3.4
|
||||
|
||||
**Target Setup:**
|
||||
- Image: `registry.keyboardvagabond.com/library/cnpg-postgis:18-3.6`
|
||||
- Base: `postgres:18-bookworm` (official, ARM64 supported)
|
||||
- PostgreSQL: 18.1
|
||||
- PostGIS: 3.6.1 (compiled from source)
|
||||
- GEOS: 3.13.0
|
||||
- PROJ: 9.4.1
|
||||
- GDAL: 3.10.1
|
||||
|
||||
## Extensions Included
|
||||
|
||||
| Extension | Description | Status |
|
||||
|-----------|-------------|--------|
|
||||
| postgis | Core GIS functionality | ✓ Compiled |
|
||||
| postgis_topology | Topology support | ✓ Compiled |
|
||||
| postgis_raster | Raster support | ✓ Compiled |
|
||||
| fuzzystrmatch | Fuzzy string matching | ✓ Compiled |
|
||||
| postgis_tiger_geocoder | US Census TIGER geocoder | ✓ Compiled |
|
||||
|
||||
## Build Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ Stage 1: Builder │
|
||||
│ - Base: postgres:18-bookworm (ARM64) │
|
||||
│ - Compile GEOS 3.13.0 │
|
||||
│ - Compile PROJ 9.5.1 │
|
||||
│ - Compile GDAL 3.10.1 │
|
||||
│ - Compile PostGIS 3.6.1 │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Stage 2: CNPG Tools │
|
||||
│ - ghcr.io/cloudnative-pg/postgresql:18 │
|
||||
│ - Extract barman-cloud tools for backup/restore │
|
||||
├─────────────────────────────────────────────────────────────────┤
|
||||
│ Stage 3: Final Image (minimal) │
|
||||
│ - Base: postgres:18-bookworm (ARM64) │
|
||||
│ - Copy compiled libs from Stage 1 │
|
||||
│ - Copy barman tools from Stage 2 │
|
||||
│ - Fix postgres UID to 26 (CNPG requirement) │
|
||||
│ - Runtime dependencies only │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## ⚠️ Important: PG18 Data Directory Change
|
||||
|
||||
PostgreSQL 18 changed the default data directory path:
|
||||
|
||||
| Version | Data Directory |
|
||||
|---------|----------------|
|
||||
| PG 13-17 | `/var/lib/postgresql/data` |
|
||||
| PG 18+ | `/var/lib/postgresql` |
|
||||
|
||||
This affects volume mounts in docker-compose and may require CNPG configuration changes.
|
||||
|
||||
## Migration Steps
|
||||
|
||||
### Phase 1: Build and Test Locally
|
||||
|
||||
1. **Build the image (takes 15-30 minutes):**
|
||||
```bash
|
||||
cd build/postgresql-postgis
|
||||
chmod +x build.sh initdb-postgis.sh update-postgis.sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
2. **Test with docker-compose:**
|
||||
```bash
|
||||
docker-compose -f docker-compose.test.yaml up -d
|
||||
docker-compose -f docker-compose.test.yaml exec postgres psql -U postgres
|
||||
|
||||
# In psql, verify:
|
||||
SELECT postgis_full_version();
|
||||
SELECT ST_AsText(ST_Point(0, 0));
|
||||
\dx -- list extensions
|
||||
|
||||
# Cleanup
|
||||
docker-compose -f docker-compose.test.yaml down -v
|
||||
```
|
||||
|
||||
3. **Interactive testing:**
|
||||
```bash
|
||||
docker run -it --rm -e POSTGRES_PASSWORD=test cnpg-postgis:18-3.6 bash
|
||||
```
|
||||
|
||||
### Phase 2: Push to Registry
|
||||
|
||||
```bash
|
||||
docker push registry.keyboardvagabond.com/library/cnpg-postgis:18-3.6
|
||||
```
|
||||
|
||||
### Phase 3: CNPG Upgrade
|
||||
|
||||
**Option A: In-place upgrade (for testing)**
|
||||
|
||||
1. Update `manifests/infrastructure/postgresql/cluster-shared.yaml`:
|
||||
```yaml
|
||||
spec:
|
||||
imageName: registry.keyboardvagabond.com/library/cnpg-postgis:18-3.6
|
||||
```
|
||||
|
||||
2. CNPG will handle the rolling upgrade automatically.
|
||||
|
||||
**Option B: Create new cluster and migrate (safer for production)**
|
||||
|
||||
1. Create a new cluster with PG18 image
|
||||
2. Use pg_dump/pg_restore or CNPG backup/restore
|
||||
3. Switch applications to new cluster
|
||||
4. Decommission old cluster
|
||||
|
||||
## CNPG Operator Compatibility
|
||||
|
||||
- Current operator: `>=0.20.0` (Helm chart)
|
||||
- PostgreSQL 18 support: Requires CNPG operator 1.24+
|
||||
- Check current version:
|
||||
```bash
|
||||
kubectl get deployment -n postgresql-system -l app.kubernetes.io/name=cloudnative-pg \
|
||||
-o jsonpath='{.items[0].spec.template.spec.containers[0].image}'
|
||||
```
|
||||
|
||||
If upgrade needed, update `manifests/infrastructure/postgresql/operator.yaml`:
|
||||
```yaml
|
||||
spec:
|
||||
chart:
|
||||
spec:
|
||||
version: ">=0.23.0" # or specific version with PG18 support
|
||||
```
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If issues occur:
|
||||
1. Change imageName back to `registry.keyboardvagabond.com/library/cnpg-postgis:16.6-3.4-v2`
|
||||
2. CNPG will roll back to previous version
|
||||
3. Restore from backup if data issues
|
||||
|
||||
## Verification Checklist
|
||||
|
||||
- [ ] Image builds successfully on M1 Mac (~15-30 min)
|
||||
- [ ] postgres user has UID 26
|
||||
- [ ] GEOS, PROJ, GDAL compiled correctly
|
||||
- [ ] PostGIS extensions install correctly
|
||||
- [ ] barman-cloud tools are present
|
||||
- [ ] Local docker-compose test passes
|
||||
- [ ] Spatial queries work (`ST_Point`, `ST_AsText`, etc.)
|
||||
- [ ] Image pushed to Harbor registry
|
||||
- [ ] CNPG operator compatible with PG18
|
||||
- [ ] Test cluster upgrade in staging (if available)
|
||||
- [ ] Production cluster upgrade successful
|
||||
- [ ] All fediverse apps functioning correctly
|
||||
|
||||
## Build Dependencies (compiled from source)
|
||||
|
||||
| Library | Version | Purpose |
|
||||
|---------|---------|---------|
|
||||
| GEOS | 3.13.0 | Geometry operations |
|
||||
| PROJ | 9.4.1 | Coordinate transformations |
|
||||
| GDAL | 3.10.1 | Raster/vector data access |
|
||||
| PostGIS | 3.6.1 | PostgreSQL spatial extension |
|
||||
|
||||
## References
|
||||
|
||||
- [PostgreSQL 18 Release Notes](https://www.postgresql.org/docs/18/release-18.html)
|
||||
- [PostGIS 3.6 Release Notes](https://postgis.net/documentation/getting_started/)
|
||||
- [docker-postgis GitHub](https://github.com/postgis/docker-postgis)
|
||||
- [CloudNativePG Documentation](https://cloudnative-pg.io/documentation/)
|
||||
- [GEOS Downloads](https://download.osgeo.org/geos/)
|
||||
- [PROJ Downloads](https://download.osgeo.org/proj/)
|
||||
- [GDAL Downloads](https://github.com/OSGeo/gdal/releases)
|
||||
140
build/postgresql-postgis/build-upgrade-image.sh
Executable file
140
build/postgresql-postgis/build-upgrade-image.sh
Executable file
@@ -0,0 +1,140 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# =============================================================================
|
||||
# Build script for PostgreSQL 16→18 Upgrade Image with PostGIS
|
||||
# This image is used ONLY for the pg_upgrade process via CloudNativePG
|
||||
# =============================================================================
|
||||
|
||||
# Configuration
|
||||
REGISTRY="registry.keyboardvagabond.com/library"
|
||||
IMAGE_NAME="cnpg-postgis"
|
||||
TAG="upgrade-16-to-18"
|
||||
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
|
||||
LOCAL_IMAGE="${IMAGE_NAME}:${TAG}"
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }
|
||||
log_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
echo ""
|
||||
echo "========================================================"
|
||||
echo " PostgreSQL 16→18 Upgrade Image Build (ARM64)"
|
||||
echo "========================================================"
|
||||
echo ""
|
||||
log_info "This builds a special image with BOTH PG16 and PG18 binaries"
|
||||
log_info "Required for CloudNativePG declarative pg_upgrade"
|
||||
log_warn "Build time: ~30-45 minutes (builds PostGIS twice)"
|
||||
log_info "Target: ${FULL_IMAGE}"
|
||||
echo ""
|
||||
|
||||
# =============================================================================
|
||||
# Build the upgrade image
|
||||
# =============================================================================
|
||||
log_step "Starting Docker build with Dockerfile.upgrade..."
|
||||
|
||||
BUILD_START=$(date +%s)
|
||||
|
||||
docker build \
|
||||
--platform linux/arm64 \
|
||||
--progress=plain \
|
||||
-f Dockerfile.upgrade \
|
||||
-t "${FULL_IMAGE}" \
|
||||
-t "${LOCAL_IMAGE}" \
|
||||
.
|
||||
|
||||
BUILD_END=$(date +%s)
|
||||
BUILD_TIME=$((BUILD_END - BUILD_START))
|
||||
BUILD_MINS=$((BUILD_TIME / 60))
|
||||
BUILD_SECS=$((BUILD_TIME % 60))
|
||||
|
||||
log_info "Build completed in ${BUILD_MINS}m ${BUILD_SECS}s"
|
||||
|
||||
# =============================================================================
|
||||
# Test the upgrade image
|
||||
# =============================================================================
|
||||
echo ""
|
||||
log_step "Running verification tests..."
|
||||
|
||||
# Test 1: Both PostgreSQL versions present
|
||||
log_info "Test 1: Checking PostgreSQL versions..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
echo " PG16: $(/usr/lib/postgresql/16/bin/postgres --version)"
|
||||
echo " PG18: $(/usr/lib/postgresql/18/bin/postgres --version)"
|
||||
'
|
||||
|
||||
# Test 2: pg_upgrade available
|
||||
log_info "Test 2: Checking pg_upgrade..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
/usr/lib/postgresql/18/bin/pg_upgrade --version && echo " ✓ pg_upgrade available"
|
||||
'
|
||||
|
||||
# Test 3: User ID check
|
||||
log_info "Test 3: Checking postgres user ID (should be 26)..."
|
||||
POSTGRES_UID=$(docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" id -u postgres)
|
||||
if [ "$POSTGRES_UID" = "26" ]; then
|
||||
echo " ✓ postgres UID is 26 (CNPG compatible)"
|
||||
else
|
||||
log_error "postgres UID is ${POSTGRES_UID}, expected 26"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 4: PostGIS for both versions
|
||||
log_info "Test 4: Checking PostGIS libraries..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
echo " PG16 PostGIS:"
|
||||
ls /usr/lib/postgresql/16/lib/postgis*.so 2>/dev/null | xargs -I{} basename {} | sed "s/^/ /"
|
||||
echo " PG18 PostGIS:"
|
||||
ls /usr/lib/postgresql/18/lib/postgis*.so 2>/dev/null | xargs -I{} basename {} | sed "s/^/ /"
|
||||
'
|
||||
|
||||
# Test 5: Shared libraries
|
||||
log_info "Test 5: Checking shared libraries..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
echo " GEOS: $(geos-config --version 2>/dev/null || echo "not found")"
|
||||
echo " GDAL: $(gdal-config --version 2>/dev/null || echo "not found")"
|
||||
echo " PROJ: $(projinfo 2>&1 | head -1 || echo "installed")"
|
||||
'
|
||||
|
||||
# Test 6: Barman tools
|
||||
log_info "Test 6: Checking barman-cloud tools..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" \
|
||||
bash -c 'ls /usr/local/bin/barman* >/dev/null 2>&1 && echo " ✓ barman-cloud tools available" || echo " ✗ barman-cloud tools not found"'
|
||||
|
||||
# =============================================================================
|
||||
# Summary
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "========================================================"
|
||||
log_info "Upgrade image build completed!"
|
||||
echo "========================================================"
|
||||
echo ""
|
||||
echo "Images built:"
|
||||
echo " Local: ${LOCAL_IMAGE}"
|
||||
echo " Harbor: ${FULL_IMAGE}"
|
||||
echo ""
|
||||
echo "Build time: ${BUILD_MINS}m ${BUILD_SECS}s"
|
||||
echo ""
|
||||
echo "To push to Harbor registry:"
|
||||
echo " docker push ${FULL_IMAGE}"
|
||||
echo ""
|
||||
echo "IMPORTANT: This image is for pg_upgrade ONLY!"
|
||||
echo "After upgrade completes, switch to: ${REGISTRY}/${IMAGE_NAME}:18-3.6"
|
||||
echo ""
|
||||
log_warn "Next steps:"
|
||||
echo " 1. Push image: docker push ${FULL_IMAGE}"
|
||||
echo " 2. Take Longhorn snapshot of postgres-shared volumes"
|
||||
echo " 3. Update cluster-shared.yaml imageName to: ${FULL_IMAGE}"
|
||||
echo " 4. Apply and monitor the upgrade"
|
||||
echo " 5. After success, switch to regular 18-3.6 image"
|
||||
echo ""
|
||||
@@ -1,41 +1,173 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
set -euo pipefail
|
||||
|
||||
# Build script for ARM64 PostGIS image compatible with CloudNativePG
|
||||
# =============================================================================
|
||||
# Build script for ARM64 PostgreSQL 18 + PostGIS 3.6 image for CloudNativePG
|
||||
# This builds PostGIS from source since ARM64 packages aren't available yet
|
||||
# =============================================================================
|
||||
|
||||
REGISTRY="<YOUR_REGISTRY_URL>/library"
|
||||
# Configuration
|
||||
REGISTRY="registry.keyboardvagabond.com/library"
|
||||
IMAGE_NAME="cnpg-postgis"
|
||||
TAG="16.6-3.4-v2"
|
||||
PG_VERSION="18"
|
||||
POSTGIS_VERSION="3.6"
|
||||
TAG="${PG_VERSION}-${POSTGIS_VERSION}"
|
||||
FULL_IMAGE="${REGISTRY}/${IMAGE_NAME}:${TAG}"
|
||||
LOCAL_IMAGE="${IMAGE_NAME}:${TAG}"
|
||||
|
||||
echo "Building ARM64 PostGIS image: ${FULL_IMAGE}"
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
log_info() {
|
||||
echo -e "${GREEN}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
log_warn() {
|
||||
echo -e "${YELLOW}[WARN]${NC} $1"
|
||||
}
|
||||
|
||||
log_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
log_step() {
|
||||
echo -e "${BLUE}[STEP]${NC} $1"
|
||||
}
|
||||
|
||||
# Change to script directory
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
echo " PostgreSQL ${PG_VERSION} + PostGIS ${POSTGIS_VERSION} ARM64 Build"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
log_info "Building from source (this will take 15-30 minutes)"
|
||||
log_info "Target: ${FULL_IMAGE}"
|
||||
echo ""
|
||||
|
||||
# =============================================================================
|
||||
# Build the image
|
||||
# =============================================================================
|
||||
log_step "Starting Docker build..."
|
||||
|
||||
BUILD_START=$(date +%s)
|
||||
|
||||
docker build \
|
||||
--platform linux/arm64 \
|
||||
--progress=plain \
|
||||
-t "${FULL_IMAGE}" \
|
||||
-t "${LOCAL_IMAGE}" \
|
||||
.
|
||||
|
||||
echo "Image built successfully: ${FULL_IMAGE}"
|
||||
BUILD_END=$(date +%s)
|
||||
BUILD_TIME=$((BUILD_END - BUILD_START))
|
||||
BUILD_MINS=$((BUILD_TIME / 60))
|
||||
BUILD_SECS=$((BUILD_TIME % 60))
|
||||
|
||||
# Test the image by running a container and checking PostGIS availability
|
||||
echo "Testing PostGIS installation..."
|
||||
docker run --rm --platform linux/arm64 "${FULL_IMAGE}" \
|
||||
postgres --version
|
||||
|
||||
echo "Tagging image for local testing..."
|
||||
docker tag "${FULL_IMAGE}" "${LOCAL_IMAGE}"
|
||||
|
||||
echo "Image built and tagged as:"
|
||||
echo " Harbor registry: ${FULL_IMAGE}"
|
||||
echo " Local testing: ${LOCAL_IMAGE}"
|
||||
log_info "Build completed in ${BUILD_MINS}m ${BUILD_SECS}s"
|
||||
|
||||
# =============================================================================
|
||||
# Test the image
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "To push to Harbor registry (when ready for deployment):"
|
||||
log_step "Running tests..."
|
||||
|
||||
# Test 1: PostgreSQL version
|
||||
log_info "Test 1: Checking PostgreSQL version..."
|
||||
PG_VER=$(docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" postgres --version)
|
||||
echo " ${PG_VER}"
|
||||
|
||||
# Test 2: User ID check (CNPG requires UID 26)
|
||||
log_info "Test 2: Checking postgres user ID (should be 26)..."
|
||||
POSTGRES_UID=$(docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" id -u postgres)
|
||||
if [ "$POSTGRES_UID" = "26" ]; then
|
||||
echo " ✓ postgres UID is 26 (CNPG compatible)"
|
||||
else
|
||||
log_error "postgres UID is ${POSTGRES_UID}, expected 26"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test 3: Library check
|
||||
log_info "Test 3: Checking compiled libraries..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
echo " GEOS: $(geos-config --version 2>/dev/null || echo "not found")"
|
||||
echo " GDAL: $(gdal-config --version 2>/dev/null || echo "not found")"
|
||||
echo " PROJ: $(projinfo 2>&1 | head -1 || echo "installed")"
|
||||
'
|
||||
|
||||
# Test 4: PostGIS extension files
|
||||
log_info "Test 4: Checking PostGIS extension files..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" bash -c '
|
||||
ls /usr/lib/postgresql/18/lib/postgis*.so 2>/dev/null && echo " ✓ PostGIS shared libraries present" || echo " ✗ PostGIS libraries missing"
|
||||
ls /usr/share/postgresql/18/extension/postgis*.control 2>/dev/null && echo " ✓ PostGIS extension control files present" || echo " ✗ Extension control files missing"
|
||||
'
|
||||
|
||||
# Test 5: Full PostGIS functionality test
|
||||
log_info "Test 5: Testing PostGIS functionality..."
|
||||
docker run --rm --platform linux/arm64 \
|
||||
-e POSTGRES_PASSWORD=testpassword \
|
||||
"${LOCAL_IMAGE}" \
|
||||
bash -c '
|
||||
set -e
|
||||
# Initialize database
|
||||
initdb -D /tmp/pgdata -U postgres >/dev/null 2>&1
|
||||
|
||||
# Start PostgreSQL
|
||||
pg_ctl -D /tmp/pgdata -o "-c listen_addresses='\'\''" start -w >/dev/null 2>&1
|
||||
|
||||
# Create extensions
|
||||
psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS postgis;" >/dev/null 2>&1
|
||||
psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS postgis_topology;" >/dev/null 2>&1
|
||||
psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;" >/dev/null 2>&1
|
||||
psql -U postgres -c "CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder;" >/dev/null 2>&1
|
||||
|
||||
# Get version
|
||||
POSTGIS_VER=$(psql -U postgres -t -c "SELECT postgis_full_version();" 2>/dev/null | head -1 | xargs)
|
||||
echo " PostGIS: ${POSTGIS_VER:0:80}..."
|
||||
|
||||
# Test spatial query
|
||||
psql -U postgres -c "SELECT ST_AsText(ST_Point(0,0));" >/dev/null 2>&1
|
||||
echo " ✓ Spatial queries working"
|
||||
|
||||
# Stop PostgreSQL
|
||||
pg_ctl -D /tmp/pgdata stop >/dev/null 2>&1
|
||||
' && echo " ✓ All PostGIS extensions functional" || log_warn "PostGIS test had issues (check manually)"
|
||||
|
||||
# Test 6: Barman tools
|
||||
log_info "Test 6: Checking barman-cloud tools..."
|
||||
docker run --rm --platform linux/arm64 "${LOCAL_IMAGE}" \
|
||||
bash -c 'ls /usr/local/bin/barman* >/dev/null 2>&1 && echo " ✓ barman-cloud tools available" || echo " ✗ barman-cloud tools not found"'
|
||||
|
||||
# =============================================================================
|
||||
# Summary
|
||||
# =============================================================================
|
||||
echo ""
|
||||
echo "=============================================="
|
||||
log_info "Build and tests completed!"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo "Images built:"
|
||||
echo " Local: ${LOCAL_IMAGE}"
|
||||
echo " Harbor: ${FULL_IMAGE}"
|
||||
echo ""
|
||||
echo "Build time: ${BUILD_MINS}m ${BUILD_SECS}s"
|
||||
echo ""
|
||||
echo "To test interactively:"
|
||||
echo " docker run -it --rm -e POSTGRES_PASSWORD=test ${LOCAL_IMAGE} bash"
|
||||
echo ""
|
||||
echo "To test with docker-compose:"
|
||||
echo " docker-compose -f docker-compose.test.yaml up -d"
|
||||
echo " docker-compose -f docker-compose.test.yaml exec postgres psql -U postgres"
|
||||
echo ""
|
||||
echo "To push to Harbor registry:"
|
||||
echo " docker push ${FULL_IMAGE}"
|
||||
|
||||
echo ""
|
||||
echo "Build completed successfully!"
|
||||
echo "Local testing image: ${LOCAL_IMAGE}"
|
||||
echo "Harbor registry image: ${FULL_IMAGE}"
|
||||
echo "To update CNPG cluster, change imageName in cluster-shared.yaml to:"
|
||||
echo " imageName: ${FULL_IMAGE}"
|
||||
echo ""
|
||||
log_warn "NOTE: PG18 uses /var/lib/postgresql as data dir (not /var/lib/postgresql/data)"
|
||||
36
build/postgresql-postgis/docker-compose.test.yaml
Normal file
36
build/postgresql-postgis/docker-compose.test.yaml
Normal file
@@ -0,0 +1,36 @@
|
||||
# Docker Compose for local testing of PostgreSQL 18 + PostGIS image
|
||||
#
|
||||
# Usage:
|
||||
# docker-compose -f docker-compose.test.yaml up -d
|
||||
# docker-compose -f docker-compose.test.yaml exec postgres psql -U postgres
|
||||
# docker-compose -f docker-compose.test.yaml down -v
|
||||
#
|
||||
# NOTE: PostgreSQL 18 changed the data directory path!
|
||||
# PG 13-17: /var/lib/postgresql/data
|
||||
# PG 18+: /var/lib/postgresql
|
||||
#
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: cnpg-postgis:18-3.6
|
||||
platform: linux/arm64
|
||||
container_name: postgis-test
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: testpassword
|
||||
POSTGRES_DB: testdb
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
# NOTE: PG18 uses /var/lib/postgresql (not /var/lib/postgresql/data)
|
||||
- postgres_data:/var/lib/postgresql
|
||||
- ./init-extensions.sql:/docker-entrypoint-initdb.d/20-extensions.sql:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U postgres"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
postgres_data:
|
||||
21
build/postgresql-postgis/init-extensions.sql
Normal file
21
build/postgresql-postgis/init-extensions.sql
Normal file
@@ -0,0 +1,21 @@
|
||||
-- Initialize PostGIS extensions for testing
|
||||
-- This mirrors what CNPG does in postInitTemplateSQL
|
||||
|
||||
-- Core PostGIS
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
|
||||
-- Topology support
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_topology;
|
||||
|
||||
-- Fuzzy string matching (required for tiger geocoder)
|
||||
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
|
||||
|
||||
-- US Census TIGER geocoder
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder;
|
||||
|
||||
-- Verify installations
|
||||
SELECT 'PostgreSQL version: ' || version();
|
||||
SELECT 'PostGIS version: ' || postgis_full_version();
|
||||
|
||||
-- List all installed extensions
|
||||
SELECT extname, extversion FROM pg_extension ORDER BY extname;
|
||||
22
build/postgresql-postgis/initdb-postgis.sh
Executable file
22
build/postgresql-postgis/initdb-postgis.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Perform all actions as $POSTGRES_USER
|
||||
export PGUSER="$POSTGRES_USER"
|
||||
|
||||
# Create the 'template_postgis' template db
|
||||
psql --dbname="$POSTGRES_DB" <<- 'EOSQL'
|
||||
CREATE DATABASE template_postgis IS_TEMPLATE true;
|
||||
EOSQL
|
||||
|
||||
# Load PostGIS into both template_database and $POSTGRES_DB
|
||||
for DB in template_postgis "$POSTGRES_DB"; do
|
||||
echo "Loading PostGIS extensions into $DB"
|
||||
psql --dbname="$DB" <<-'EOSQL'
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_topology;
|
||||
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder;
|
||||
EOSQL
|
||||
done
|
||||
28
build/postgresql-postgis/update-postgis.sh
Executable file
28
build/postgresql-postgis/update-postgis.sh
Executable file
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
# Perform all actions as $POSTGRES_USER
|
||||
export PGUSER="$POSTGRES_USER"
|
||||
|
||||
POSTGIS_VERSION="${POSTGIS_VERSION%%+*}"
|
||||
|
||||
# Load PostGIS into both template_database and $POSTGRES_DB
|
||||
for DB in template_postgis "$POSTGRES_DB" "${@}"; do
|
||||
echo "Updating PostGIS extensions '$DB' to $POSTGIS_VERSION"
|
||||
psql --dbname="$DB" -c "
|
||||
-- Upgrade PostGIS (includes raster)
|
||||
CREATE EXTENSION IF NOT EXISTS postgis VERSION '$POSTGIS_VERSION';
|
||||
ALTER EXTENSION postgis UPDATE TO '$POSTGIS_VERSION';
|
||||
|
||||
-- Upgrade Topology
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_topology VERSION '$POSTGIS_VERSION';
|
||||
ALTER EXTENSION postgis_topology UPDATE TO '$POSTGIS_VERSION';
|
||||
|
||||
-- Install Tiger dependencies in case not already installed
|
||||
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch;
|
||||
-- Upgrade US Tiger Geocoder
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder VERSION '$POSTGIS_VERSION';
|
||||
ALTER EXTENSION postgis_tiger_geocoder UPDATE TO '$POSTGIS_VERSION';
|
||||
"
|
||||
done
|
||||
Reference in New Issue
Block a user