From f0d5f4870eb31802a4589c7053ee49b0015a0011 Mon Sep 17 00:00:00 2001 From: Maxime Killinger Date: Thu, 25 Dec 2025 16:46:34 +0100 Subject: [PATCH] fix(docker): resolve permission denied error for PG18+ volume mounts PostgreSQL 18+ Docker images changed the data directory structure to use versioned subdirectories (e.g., /var/lib/postgresql/18/main) instead of the traditional /var/lib/postgresql/data path. Changes: - Dockerfile: Add mkdir and chown to ensure /var/lib/postgresql has correct permissions for the postgres user before volume mount - README.md: Update Quick Start with volume mount example - README.md: Add 'Data Persistence' section explaining PG18+ requirements This fixes the 'mkdir: cannot create directory: Permission denied' error that occurred when mounting volumes at /var/lib/postgresql. See: https://github.com/docker-library/postgres/pull/1259 --- .gitea/workflows/docker-build.yml | 12 ++++++------ Dockerfile | 9 ++++++--- README.md | 7 +++++++ docker-entrypoint-wrapper.sh | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 docker-entrypoint-wrapper.sh diff --git a/.gitea/workflows/docker-build.yml b/.gitea/workflows/docker-build.yml index 5003fd3..3d6b8c0 100644 --- a/.gitea/workflows/docker-build.yml +++ b/.gitea/workflows/docker-build.yml @@ -13,20 +13,20 @@ jobs: pg_version: [15, 16, 17, 18] steps: - name: 📥 Checkout code - uses: actions/checkout@v4 + uses: https://github.com/actions/checkout@v4 - name: 🛠️ Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: https://github.com/docker/setup-buildx-action@v3 - name: 🔐 Login to Gitea Registry - uses: docker/login-action@v3 + uses: https://github.com/docker/login-action@v3 with: registry: gitea.killinger.fr username: maxime.killinger password: ${{ secrets.DOCKER_TOKEN }} - name: 📦 Build Docker image - uses: docker/build-push-action@v5 + uses: https://github.com/docker/build-push-action@v5 with: context: . load: true @@ -74,7 +74,7 @@ jobs: run: docker rm -f test-pg${{ matrix.pg_version }} || true - name: 🚀 Push Docker image - uses: docker/build-push-action@v5 + uses: https://github.com/docker/build-push-action@v5 with: context: . push: true @@ -85,7 +85,7 @@ jobs: - name: 🏷️ Tag latest (PG18 only) if: matrix.pg_version == 18 - uses: docker/build-push-action@v5 + uses: https://github.com/docker/build-push-action@v5 with: context: . push: true diff --git a/Dockerfile b/Dockerfile index c4b55f0..dee429f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,11 +46,14 @@ COPY --from=builder /tmp/timescaledb/usr/share/postgresql/ /usr/share/postgresql COPY init-extensions.sh /docker-entrypoint-initdb.d/ RUN chmod +x /docker-entrypoint-initdb.d/init-extensions.sh +# Add entrypoint wrapper to fix volume permissions at runtime +COPY docker-entrypoint-wrapper.sh /usr/local/bin/ +RUN chmod +x /usr/local/bin/docker-entrypoint-wrapper.sh + # Healthcheck HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \ CMD pg_isready -U postgres || exit 1 -USER postgres - -# Preload required libraries +# Run as root initially, wrapper will fix permissions then switch to postgres +ENTRYPOINT ["docker-entrypoint-wrapper.sh"] CMD ["postgres", "-c", "shared_preload_libraries=timescaledb,vchord"] diff --git a/README.md b/README.md index a59f6bb..0326fcc 100644 --- a/README.md +++ b/README.md @@ -23,12 +23,19 @@ Docker image combining **PostgreSQL** with three powerful extensions: docker run -d \ --name my-postgres \ -e POSTGRES_PASSWORD=mysecretpassword \ + -v postgres_data:/var/lib/postgresql \ -p 5432:5432 \ gitea.killinger.fr/maxime.killinger/postgres-ts-vectors:latest ``` All extensions are **automatically created** on first startup. +## Data Persistence + +> [!IMPORTANT] +> Starting with PostgreSQL 18, mount volumes at `/var/lib/postgresql` (not `/var/lib/postgresql/data`). +> Data will be stored in a versioned subdirectory (e.g., `/var/lib/postgresql/18/main`), which facilitates future upgrades with `pg_upgrade`. + ## Environment Variables | Variable | Description | Default | diff --git a/docker-entrypoint-wrapper.sh b/docker-entrypoint-wrapper.sh new file mode 100644 index 0000000..50f8c76 --- /dev/null +++ b/docker-entrypoint-wrapper.sh @@ -0,0 +1,14 @@ +#!/bin/bash +set -e + +# Fix permissions for mounted volumes (PG18+ requirement) +# This runs as root before switching to postgres user +if [ "$(id -u)" = '0' ]; then + # Ensure data directory exists with correct permissions + mkdir -p /var/lib/postgresql + chown -R postgres:postgres /var/lib/postgresql + chmod 700 /var/lib/postgresql +fi + +# Execute the original entrypoint +exec docker-entrypoint.sh "$@"