├── .github └── workflows │ └── main.yml ├── Dockerfile ├── LICENSE.txt ├── README.md └── install_pg_extensions.sh /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: build container 2 | on: 3 | # triggered by user action only 4 | workflow_dispatch: 5 | inputs: 6 | PG_VERSION: 7 | description: 'Postgres version' 8 | required: true 9 | default: '15.3' 10 | EXTENSIONS: 11 | description: 'Postgres extensions to install' 12 | required: true 13 | default: 'cron timescaledb' 14 | TIMESCALEDB_VERSION: 15 | description: 'TimescaleDB version' 16 | required: true 17 | default: '2.11.0' 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: docker/setup-buildx-action@v2 24 | - uses: docker/login-action@v2 25 | # authenticate ghcr.io 26 | with: 27 | registry: ghcr.io 28 | username: ${{ github.actor }} 29 | password: ${{ secrets.GITHUB_TOKEN }} 30 | - name: calculate image tag 31 | id: vars 32 | run: | 33 | # step 1: order extensions alphabetically 34 | export EXTENSIONS=$(echo "${{ github.event.inputs.EXTENSIONS }}" | tr ' ' '\n' | sort | tr '\n' ' ') 35 | 36 | # this is good but it leaves a trailing space. Fix it: 37 | export EXTENSIONS=$(echo "${EXTENSIONS}" | sed 's/ $//g') 38 | 39 | # step 2: if exists, replace extension timescaledb with its versioned equivalent; replace spaces with dashes 40 | export EXTENSIONS=$(echo "${{ github.event.inputs.EXTENSIONS }}" | sed 's/timescaledb/timescaledb-${{ github.event.inputs.TIMESCALEDB_VERSION }}/g;s/ /-/g') 41 | 42 | # step 3: output variable to github action 43 | echo "IMAGE_TAG=${{ github.event.inputs.PG_VERSION }}-${EXTENSIONS}" >> $GITHUB_OUTPUT 44 | - uses: docker/build-push-action@v3 45 | with: 46 | context: . 47 | file: ./Dockerfile 48 | push: true 49 | tags: ghcr.io/${{ github.repository_owner }}/postgresql:${{ steps.vars.outputs.IMAGE_TAG }} 50 | build-args: | 51 | POSTGRESQL_VERSION=${{ github.event.inputs.PG_VERSION }} 52 | EXTENSIONS=${{ github.event.inputs.EXTENSIONS }} 53 | TIMESCALEDB_VERSION=${{ github.event.inputs.TIMESCALEDB_VERSION }} 54 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # add extensions to cnpg postgresql image: timescaledb, pg_cron 2 | ARG POSTGRESQL_VERSION=15.3 3 | ARG EXTENSIONS="timescaledb cron" 4 | ARG TIMESCALEDB_VERSION=2.11.0 5 | 6 | 7 | FROM ghcr.io/cloudnative-pg/postgresql:${POSTGRESQL_VERSION} 8 | ARG EXTENSIONS 9 | ENV EXTENSIONS=${EXTENSIONS} 10 | ARG TIMESCALEDB_VERSION 11 | ENV TIMESCALEDB_VERSION=${TIMESCALEDB_VERSION} 12 | 13 | COPY ./install_pg_extensions.sh / 14 | # switch to root user to install extensions 15 | USER root 16 | RUN \ 17 | apt-get update && \ 18 | /install_pg_extensions.sh ${EXTENSIONS} && \ 19 | # cleanup 20 | apt-get clean && \ 21 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /install_pg_extensions.sh 22 | # switch back to the postgres user 23 | USER postgres -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the “Software”), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostgreSQL container images extender 2 | 3 | This repository contains the dockerfiles and scripts as well as the github actions 4 | to extend the postgresql container images from [ghcr.io/cloudnative-pg/postgresql](https://github.com/cloudnative-pg/postgres-containers/). 5 | 6 | ## Building locally 7 | 8 | To build an image locally using docker, check out the repository and run the following command: 9 | 10 | ```shell 11 | git clone 12 | ``` 13 | 14 | Then you can build the image using the following command: 15 | 16 | ```shell 17 | docker build -t postgresql . 18 | ``` 19 | 20 | By default the image extends version 15.3 of the cloudnative-pg operand image. 21 | You can change this by providing a different version as build argument: 22 | 23 | ```shell 24 | docker build -t postgresql --build-arg POSTGRESQL_VERSION=15.2 . 25 | ``` 26 | 27 | By default this image extends the base image with the timescaledb and cron extensions. 28 | To change this, you can provide a different list of extensions as build argument: 29 | 30 | ```shell 31 | docker build -t postgresql --build-arg EXTENSIONS="timescaledb cron" . 32 | ``` 33 | 34 | The supported extensions are found in the official debian apt repositories 35 | under the package names `postgresql--`. Timescaledb is 36 | handled separately as it is not available in the official debian apt repositories. 37 | 38 | For the Timescaledb version you can also provide a different version as build argument: 39 | 40 | ```shell 41 | docker build -t postgresql --build-arg TIMESCALEDB_VERSION=2.11.0 . 42 | ``` 43 | 44 | # Building with GitHub Actions 45 | 46 | This repository contains a GitHub Actions workflow that builds the image and pushes it to the 47 | `ghcr.io//postgresql` repository. You can clone this repository 48 | to generate your own custom images directly in GitHub. The workflow is triggered 49 | manually and accepts the same build arguments as the local build. 50 | 51 | The tags for the images are generated from the postgresql version and the extension list. 52 | The timescaledb extension is versioned. For example, the image for postgresql 15.3 with 53 | timescaledb 2.11.0 and cron extension would be tagged as `15.3-cron-timescaledb-2.11.0`. 54 | -------------------------------------------------------------------------------- /install_pg_extensions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | # calling syntax: install_pg_extensions.sh [extension1] [extension2] ... 5 | 6 | # install extensions 7 | EXTENSIONS="$@" 8 | # cycle through extensions list 9 | for EXTENSION in ${EXTENSIONS}; do 10 | # special case: timescaledb 11 | if [ "$EXTENSION" == "timescaledb" ]; then 12 | # dependencies 13 | apt-get install apt-transport-https lsb-release wget -y 14 | 15 | # repository 16 | echo "deb https://packagecloud.io/timescale/timescaledb/debian/" \ 17 | "$(lsb_release -c -s) main" \ 18 | > /etc/apt/sources.list.d/timescaledb.list 19 | 20 | # key 21 | wget --quiet -O - https://packagecloud.io/timescale/timescaledb/gpgkey \ 22 | | gpg --dearmor > /etc/apt/trusted.gpg.d/timescaledb.gpg 23 | 24 | apt-get update 25 | apt-get install --yes \ 26 | timescaledb-tools \ 27 | timescaledb-toolkit-postgresql-${PG_MAJOR} \ 28 | timescaledb-2-loader-postgresql-${PG_MAJOR} \ 29 | timescaledb-2-${TIMESCALEDB_VERSION}-postgresql-${PG_MAJOR} 30 | 31 | # cleanup 32 | apt-get remove apt-transport-https lsb-release wget --auto-remove -y 33 | 34 | continue 35 | fi 36 | 37 | # is it an extension found in apt? 38 | if apt-cache show "postgresql-${PG_MAJOR}-${EXTENSION}" &> /dev/null; then 39 | # install the extension 40 | apt-get install -y "postgresql-${PG_MAJOR}-${EXTENSION}" 41 | continue 42 | fi 43 | 44 | # extension not found/supported 45 | echo "Extension '${EXTENSION}' not found/supported" 46 | exit 1 47 | done 48 | --------------------------------------------------------------------------------