├── .dockerignore ├── .github ├── stale.yml └── workflows │ └── build.yml ├── Changelog.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── VERSION ├── docker-compose.yml ├── entrypoint.sh ├── runtime ├── env-defaults └── functions └── scripts └── release-notes.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | /.git/ 2 | /.github/ 3 | LICENSE 4 | VERSION 5 | README.md 6 | Changelog.md 7 | Makefile 8 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | tags: 8 | - '*' 9 | pull_request: 10 | branches: 11 | - master 12 | workflow_dispatch: 13 | branches: 14 | - master 15 | 16 | 17 | jobs: 18 | build-and-push-docker-image: 19 | name: Build and Push Docker Image 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Checkout code 24 | uses: actions/checkout@v3 25 | 26 | - name: Docker meta 27 | id: meta 28 | uses: docker/metadata-action@v3 29 | with: 30 | images: | 31 | sameersbn/postgresql 32 | quay.io/sameersbn/postgresql 33 | ghcr.io/sameersbn/postgresql 34 | tags: | 35 | type=match,pattern=\d+ 36 | type=match,pattern=(.*) 37 | latest 38 | 39 | - name: Set up Docker Buildx 40 | id: buildx 41 | uses: docker/setup-buildx-action@v2 42 | 43 | - name: Login to DockerHub 44 | if: github.event_name != 'pull_request' 45 | uses: docker/login-action@v2 46 | with: 47 | username: ${{ secrets.DOCKERHUB_USERNAME }} 48 | password: ${{ secrets.DOCKERHUB_TOKEN }} 49 | 50 | - name: Login to Github Packages 51 | if: github.event_name != 'pull_request' 52 | uses: docker/login-action@v2 53 | with: 54 | registry: ghcr.io 55 | username: ${{ github.actor }} 56 | password: ${{ secrets.GITHUB_TOKEN }} 57 | 58 | - name: Login to Quay.io 59 | if: github.event_name != 'pull_request' 60 | uses: docker/login-action@v2 61 | with: 62 | registry: quay.io 63 | username: ${{ secrets.QUAY_USERNAME }} 64 | password: ${{ secrets.QUAY_TOKEN }} 65 | 66 | - name: Build image and push to container registries 67 | uses: docker/build-push-action@v4 68 | with: 69 | context: . 70 | push: ${{ github.event_name != 'pull_request' }} 71 | tags: ${{ steps.meta.outputs.tags }} 72 | labels: ${{ steps.meta.outputs.labels }} 73 | 74 | - name: Image digest 75 | run: echo ${{ steps.docker_build.outputs.digest }} 76 | -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | **9.6** 4 | - postgresql: upgrade to 9.6 5 | - upgrade baseimage to sameersbn/ubuntu:14.04.20170110 6 | 7 | **9.5** 8 | - postgresql: upgrade to 9.5 9 | 10 | **9.4-17** 11 | - added `DB_EXTENSION` configuration parameter 12 | 13 | **9.4-12** 14 | - removed use of single-user mode 15 | - added `DB_TEMPLATE` variable to specify the database template 16 | 17 | **9.4-11** 18 | - added `PG_PASSWORD` variable to specify password for `postgres` user 19 | 20 | **9.4-9** 21 | - complete rewrite 22 | - `PSQL_TRUST_LOCALNET` config parameter renamed to `PG_TRUST_LOCALNET` 23 | - `PSQL_MODE` config parameter renamed to `REPLICATION_MODE` 24 | - `PSQL_SSLMODE` config parameter renamed to `REPLICATION_SSLMODE` 25 | - defined `/etc/postgresql/certs` as the mountpoint to install SSL key and certificate 26 | - added `PG_SSL` parameter to enable/disable SSL support 27 | - `DB_LOCALE` config parameter renamed to `PG_LOCALE` 28 | - complete rewrite of the README 29 | - add support for creating backups using `pg_basebackup` 30 | - removed `PG_LOCALE` option (doesn't work!) 31 | - added `DEBUG` option to enable bash debugging 32 | 33 | **9.4-2** 34 | - added replication options 35 | 36 | **9.4-1** 37 | - start: removed `pwfile` logic 38 | - init: added `USERMAP_*` configuration options 39 | - base image update to fix SSL vulnerability 40 | 41 | **9.4** 42 | - postgresql: upgrade to 9.4 43 | 44 | **9.1-2** 45 | - use the official postgresql apt repo 46 | - feature: automatic data migration on upgrade 47 | 48 | **9.1-1** 49 | - upgrade to sameersbn/ubuntu:20141001, fixes shellshock 50 | - support creation of users and databases at launch (`docker run`) 51 | - mount volume at `/var/run/postgresql` allowing the postgresql unix socket to be exposed 52 | 53 | **9.1** 54 | - optimized image size by removing `/var/lib/apt/lists/*`. 55 | - update to the sameersbn/ubuntu:12.04.20140818 baseimage 56 | - removed use of supervisord 57 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy-20230605 AS add-apt-repositories 2 | 3 | RUN apt-get update \ 4 | && DEBIAN_FRONTEND=noninteractive apt-get install -y wget gnupg \ 5 | && wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ 6 | && echo 'deb http://apt.postgresql.org/pub/repos/apt/ jammy-pgdg main' >> /etc/apt/sources.list 7 | 8 | FROM ubuntu:jammy-20230605 9 | 10 | LABEL maintainer="sameer@damagehead.com" 11 | 12 | ENV PG_APP_HOME="/etc/docker-postgresql" \ 13 | PG_VERSION=15 \ 14 | PG_USER=postgres \ 15 | PG_HOME=/var/lib/postgresql \ 16 | PG_RUNDIR=/run/postgresql \ 17 | PG_LOGDIR=/var/log/postgresql \ 18 | PG_CERTDIR=/etc/postgresql/certs 19 | 20 | ENV PG_BINDIR=/usr/lib/postgresql/${PG_VERSION}/bin \ 21 | PG_DATADIR=${PG_HOME}/${PG_VERSION}/main 22 | 23 | COPY --from=add-apt-repositories /etc/apt/trusted.gpg /etc/apt/trusted.gpg 24 | 25 | COPY --from=add-apt-repositories /etc/apt/sources.list /etc/apt/sources.list 26 | 27 | RUN apt-get update \ 28 | && DEBIAN_FRONTEND=noninteractive apt-get install -y acl sudo locales \ 29 | postgresql-${PG_VERSION} postgresql-client-${PG_VERSION} postgresql-contrib-${PG_VERSION} \ 30 | && update-locale LANG=C.UTF-8 LC_MESSAGES=POSIX \ 31 | && locale-gen en_US.UTF-8 \ 32 | && DEBIAN_FRONTEND=noninteractive dpkg-reconfigure locales \ 33 | && ln -sf ${PG_DATADIR}/postgresql.conf /etc/postgresql/${PG_VERSION}/main/postgresql.conf \ 34 | && ln -sf ${PG_DATADIR}/pg_hba.conf /etc/postgresql/${PG_VERSION}/main/pg_hba.conf \ 35 | && ln -sf ${PG_DATADIR}/pg_ident.conf /etc/postgresql/${PG_VERSION}/main/pg_ident.conf \ 36 | && rm -rf ${PG_HOME} \ 37 | && rm -rf /var/lib/apt/lists/* 38 | 39 | COPY runtime/ ${PG_APP_HOME}/ 40 | 41 | COPY entrypoint.sh /sbin/entrypoint.sh 42 | 43 | RUN chmod 755 /sbin/entrypoint.sh 44 | 45 | EXPOSE 5432/tcp 46 | 47 | WORKDIR ${PG_HOME} 48 | 49 | ENTRYPOINT ["/sbin/entrypoint.sh"] 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Sameer Naik 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | build: 4 | @docker build --tag=sameersbn/postgresql . 5 | 6 | release: build 7 | @docker build --tag=sameersbn/postgresql:$(shell cat VERSION) . 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sameersbn/postgresql:15-20230628 2 | 3 | - [Introduction](#introduction) 4 | - [Contributing](#contributing) 5 | - [Issues](#issues) 6 | - [Getting started](#getting-started) 7 | - [Installation](#installation) 8 | - [Quickstart](#quickstart) 9 | - [Persistence](#persistence) 10 | - [Trusting local connections](#trusting-local-connections) 11 | - [Setting `postgres` user password](#setting-postgres-user-password) 12 | - [Creating database user](#creating-database-user) 13 | - [Creating databases](#creating-databases) 14 | - [Granting user access to a database](#granting-user-access-to-a-database) 15 | - [Enabling extensions](#enabling-extensions) 16 | - [Creating replication user](#creating-replication-user) 17 | - [Setting up a replication cluster](#setting-up-a-replication-cluster) 18 | - [Creating a snapshot](#creating-a-snapshot) 19 | - [Creating a backup](#creating-a-backup) 20 | - [Command-line arguments](#command-line-arguments) 21 | - [Logs](#logs) 22 | - [UID/GID mapping](#uidgid-mapping) 23 | - [Maintenance](#maintenance) 24 | - [Upgrading](#upgrading) 25 | - [Shell Access](#shell-access) 26 | 27 | # Introduction 28 | 29 | `Dockerfile` to create a [Docker](https://www.docker.com/) container image for [PostgreSQL](http://postgresql.org/). 30 | 31 | PostgreSQL is an object-relational database management system (ORDBMS) with an emphasis on extensibility and standards-compliance [[source](https://en.wikipedia.org/wiki/PostgreSQL)]. 32 | 33 | ## Contributing 34 | 35 | If you find this image useful here's how you can help: 36 | 37 | - Send a pull request with your awesome features and bug fixes 38 | - Help users resolve their [issues](../../issues?q=is%3Aopen+is%3Aissue). 39 | - Support the development of this image with a [donation](http://www.damagehead.com/donate/) 40 | 41 | ## Issues 42 | 43 | Before reporting your issue please try updating Docker to the latest version and check if it resolves the issue. Refer to the Docker [installation guide](https://docs.docker.com/installation) for instructions. 44 | 45 | SELinux users should try disabling SELinux using the command `setenforce 0` to see if it resolves the issue. 46 | 47 | If the above recommendations do not help then [report your issue](../../issues/new) along with the following information: 48 | 49 | - Output of the `docker vers6` and `docker info` commands 50 | - The `docker run` command or `docker-compose.yml` used to start the image. Mask out the sensitive bits. 51 | - Please state if you are using [Boot2Docker](http://www.boot2docker.io), [VirtualBox](https://www.virtualbox.org), etc. 52 | 53 | # Getting started 54 | 55 | ## Installation 56 | 57 | Automated builds of the image are available on [Dockerhub](https://hub.docker.com/r/sameersbn/postgresql) and is the recommended method of installation. 58 | 59 | > **Note**: Builds are also available on [Quay.io](https://quay.io/repository/sameersbn/postgresql) 60 | 61 | ```bash 62 | docker pull sameersbn/postgresql:15-20230628 63 | ``` 64 | 65 | Alternatively you can build the image yourself. 66 | 67 | ```bash 68 | docker build -t sameersbn/postgresql github.com/sameersbn/docker-postgresql 69 | ``` 70 | 71 | ## Quickstart 72 | 73 | Start PostgreSQL using: 74 | 75 | ```bash 76 | docker run --name postgresql -itd --restart always \ 77 | --publish 5432:5432 \ 78 | --volume postgresql:/var/lib/postgresql \ 79 | sameersbn/postgresql:15-20230628 80 | ``` 81 | 82 | Login to the PostgreSQL server using: 83 | 84 | ```bash 85 | docker exec -it postgresql sudo -u postgres psql 86 | ``` 87 | 88 | *Alternatively, you can use the sample [docker-compose.yml](docker-compose.yml) file to start the container using [Docker Compose](https://docs.docker.com/compose/)* 89 | 90 | ## Persistence 91 | 92 | For PostgreSQL to preserve its state across container shutdown and startup you should mount a volume at `/var/lib/postgresql`. If you don't like the default volume destination then you can change it 93 | 94 | > *The [Quickstart](#quickstart) command already mounts a volume for persistence.* 95 | 96 | SELinux users should update the security context of the host mountpoint so that it plays nicely with Docker: 97 | 98 | ```bash 99 | mkdir -p /srv/docker/postgresql 100 | chcon -Rt svirt_sandbox_file_t /srv/docker/postgresql 101 | ``` 102 | 103 | ## Trusting local connections 104 | 105 | By default connections to the PostgreSQL server need to authenticated using a password. If desired you can trust connections from the local network using the `PG_TRUST_LOCALNET` variable. 106 | 107 | ```bash 108 | docker run --name postgresql -itd --restart always \ 109 | --env 'PG_TRUST_LOCALNET=true' \ 110 | sameersbn/postgresql:15-20230628 111 | ``` 112 | 113 | > **Note** 114 | > 115 | > The local network here is network to which the container is attached. This has different meanings depending on the `--net` parameter specified while starting the container. In the default configuration, this parameter would trust connections from other containers on the `docker0` bridge. 116 | 117 | ## Setting `postgres` user password 118 | 119 | By default the `postgres` user is not assigned a password and as a result you can only login to the PostgreSQL server locally. If you wish to login remotely to the PostgreSQL server as the `postgres` user, you will need to assign a password for the user using the `PG_PASSWORD` variable. 120 | 121 | ```bash 122 | docker run --name postgresql -itd --restart always \ 123 | --env 'PG_PASSWORD=passw0rd' \ 124 | sameersbn/postgresql:15-20230628 125 | ``` 126 | 127 | 128 | > **Note** 129 | > 130 | > - When [persistence](#persistence) is in use, `PG_PASSWORD` is effective on the first run. 131 | > - This feature is only available in the `latest` and versions > `9.4-10` 132 | 133 | ## Creating database user 134 | 135 | A new PostgreSQL database user can be created by specifying the `DB_USER` and `DB_PASS` variables while starting the container. 136 | 137 | ```bash 138 | docker run --name postgresql -itd --restart always \ 139 | --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' \ 140 | sameersbn/postgresql:15-20230628 141 | ``` 142 | 143 | > **Notes** 144 | > 145 | > - The created user can login remotely 146 | > - The container will error out if a password is not specified for the user 147 | > - No changes will be made if the user already exists 148 | > - Only a single user can be created at each launch 149 | 150 | ## Creating databases 151 | 152 | A new PostgreSQL database can be created by specifying the `DB_NAME` variable while starting the container. 153 | 154 | ```bash 155 | docker run --name postgresql -itd --restart always \ 156 | --env 'DB_NAME=dbname' \ 157 | sameersbn/postgresql:15-20230628 158 | ``` 159 | 160 | By default databases are created by copying the standard system database named `template1`. You can specify a different template for your database using the `DB_TEMPLATE` parameter. Refer to [Template Databases](http://www.postgresql.org/docs/9.4/static/manage-ag-templatedbs.html) for further information. 161 | 162 | Additionally, more than one database can be created by specifying a comma separated list of database names in `DB_NAME`. For example, the following command creates two new databases named `dbname1` and `dbname2`. 163 | 164 | *This feature is only available in releases greater than `9.1-1`* 165 | 166 | ```bash 167 | docker run --name postgresql -itd --restart always \ 168 | --env 'DB_NAME=dbname1,dbname2' \ 169 | sameersbn/postgresql:15-20230628 170 | ``` 171 | 172 | ## Granting user access to a database 173 | 174 | If the `DB_USER` and `DB_PASS` variables are specified along with the `DB_NAME` variable, then the user specified in `DB_USER` will be granted access to all the databases listed in `DB_NAME`. Note that if the user and/or databases do not exist, they will be created. 175 | 176 | ```bash 177 | docker run --name postgresql -itd --restart always \ 178 | --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' \ 179 | --env 'DB_NAME=dbname1,dbname2' \ 180 | sameersbn/postgresql:15-20230628 181 | ``` 182 | 183 | In the above example `dbuser` with be granted access to both the `dbname1` and `dbname2` databases. 184 | 185 | # Enabling extensions 186 | 187 | The image also packages the [postgres contrib module](http://www.postgresql.org/docs/9.4/static/contrib.html). A comma separated list of modules can be specified using the `DB_EXTENSION` parameter. 188 | 189 | ```bash 190 | docker run --name postgresql -itd \ 191 | --env 'DB_NAME=db1,db2' --env 'DB_EXTENSION=unaccent,pg_trgm' \ 192 | sameersbn/postgresql:15-20230628 193 | ``` 194 | 195 | The above command enables the `unaccent` and `pg_trgm` modules on the databases listed in `DB_NAME`, namely `db1` and `db2`. 196 | 197 | > **NOTE**: 198 | > 199 | > This option deprecates the `DB_UNACCENT` parameter. 200 | 201 | ## Creating replication user 202 | 203 | Similar to the creation of a database user, a new PostgreSQL replication user can be created by specifying the `REPLICATION_USER` and `REPLICATION_PASS` variables while starting the container. 204 | 205 | ```bash 206 | docker run --name postgresql -itd --restart always \ 207 | --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \ 208 | sameersbn/postgresql:15-20230628 209 | ``` 210 | 211 | > **Notes** 212 | > 213 | > - The created user can login remotely 214 | > - The container will error out if a password is not specified for the user 215 | > - No changes will be made if the user already exists 216 | > - Only a single user can be created at each launch 217 | 218 | *It is a good idea to create a replication user even if you are not going to use it as it will allow you to setup slave nodes and/or generate snapshots and backups when the need arises.* 219 | 220 | ## Setting up a replication cluster 221 | 222 | When the container is started, it is by default configured to act as a master node in a replication cluster. This means that you can scale your PostgreSQL database backend when the need arises without incurring any downtime. However do note that a replication user must exist on the master node for this to work. 223 | 224 | Begin by creating the master node of our cluster: 225 | 226 | ```bash 227 | docker run --name postgresql-master -itd --restart always \ 228 | --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' --env 'DB_NAME=dbname' \ 229 | --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \ 230 | sameersbn/postgresql:15-20230628 231 | ``` 232 | 233 | Notice that no additional arguments are specified while starting the master node of the cluster. 234 | 235 | To create a replication slave the `REPLICATION_MODE` variable should be set to `slave` and additionally the `REPLICATION_HOST`, `REPLICATION_PORT`, `REPLICATION_SSLMODE`, `REPLICATION_USER` and `REPLICATION_PASS` variables should be specified. 236 | 237 | Create a slave node: 238 | 239 | ```bash 240 | docker run --name postgresql-slave01 -itd --restart always \ 241 | --link postgresql-master:master \ 242 | --env 'REPLICATION_MODE=slave' --env 'REPLICATION_SSLMODE=prefer' \ 243 | --env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \ 244 | --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \ 245 | sameersbn/postgresql:15-20230628 246 | ``` 247 | 248 | *In the above command, we used docker links so that we can address the master node using the `master` alias in `REPLICATION_HOST`.* 249 | 250 | > **Note** 251 | > 252 | > - The default value of `REPLICATION_PORT` is `5432` 253 | > - The default value of `REPLICATION_SSLMODE` is `prefer` 254 | > - The value of `REPLICATION_USER` and `REPLICATION_PASS` should be the same as the ones specified on the master node. 255 | > - With [persistence](#persistence) in use, if the container is stopped and started, for the container continue to function as a slave you need to ensure that `REPLICATION_MODE=slave` is defined in the containers environment. In the absense of which the slave configuration will be turned off and the node will allow writing to it while having the last synced data from the master. 256 | 257 | And just like that with minimal effort you have a PostgreSQL replication cluster setup. You can create additional slaves to scale the cluster horizontally. 258 | 259 | Here are some important notes about a PostgreSQL replication cluster: 260 | 261 | - Writes can only occur on the master 262 | - Slaves are read-only 263 | - For best performance, limit the reads to the slave nodes 264 | 265 | ## Creating a snapshot 266 | 267 | Similar to a creating replication slave node, you can create a snapshot of the master by specifying `REPLICATION_MODE=snapshot`. 268 | 269 | Once the master node is created as specified in [Setting up a replication cluster](#setting-up-a-replication-cluster), you can create a snapshot using: 270 | 271 | ```bash 272 | docker run --name postgresql-snapshot -itd --restart always \ 273 | --link postgresql-master:master \ 274 | --env 'REPLICATION_MODE=snapshot' --env 'REPLICATION_SSLMODE=prefer' \ 275 | --env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \ 276 | --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \ 277 | sameersbn/postgresql:15-20230628 278 | ``` 279 | 280 | The difference between a slave and a snapshot is that a slave is read-only and updated whenever the master data is updated (streaming replication), while a snapshot is read-write and is not updated after the initial snapshot of the data from the master. 281 | 282 | This is useful for developers to quickly snapshot the current state of a live database and use it for development/debugging purposes without altering the database on the live instance. 283 | 284 | ## Creating a backup 285 | 286 | Just as the case of setting up a slave node or generating a snapshot, you can also create a backup of the data on the master by specifying `REPLICATION_MODE=backup`. 287 | 288 | > The backups are generated with [pg_basebackup](http://www.postgresql.org/docs/9.4/static/app-pgbasebackup.html) using the replication protocol. 289 | 290 | Once the master node is created as specified in [Setting up a replication cluster](#setting-up-a-replication-cluster), you can create a point-in-time backup using: 291 | 292 | ```bash 293 | docker run --name postgresql-backup -it --rm \ 294 | --link postgresql-master:master \ 295 | --env 'REPLICATION_MODE=backup' --env 'REPLICATION_SSLMODE=prefer' \ 296 | --env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \ 297 | --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \ 298 | --volume /srv/docker/backups/postgresql.$(date +%Y%m%d%H%M%S):/var/lib/postgresql \ 299 | sameersbn/postgresql:15-20230628 300 | ``` 301 | 302 | Once the backup is generated, the container will exit and the backup of the master data will be available at `/srv/docker/backups/postgresql.XXXXXXXXXXXX/`. Restoring the backup involves starting a container with the data in `/srv/docker/backups/postgresql.XXXXXXXXXXXX`. 303 | 304 | ## Command-line arguments 305 | 306 | You can customize the launch command of PostgreSQL server by specifying arguments for `postgres` on the `docker run` command. For example the following command enables connection logging: 307 | 308 | ```bash 309 | docker run --name postgresql -itd --restart always \ 310 | sameersbn/postgresql:15-20230628 -c log_connections=on 311 | ``` 312 | 313 | Please refer to the documentation of [postgres](http://www.postgresql.org/docs/9.4/static/app-postgres.html) for the complete list of available options. 314 | 315 | ## Logs 316 | 317 | By default the PostgreSQL server logs are sent to the standard output. Using the [Command-line arguments](#command-line-arguments) feature you can configure the PostgreSQL server to send the log output to a file using the `-c logging_collector=on` argument: 318 | 319 | ```bash 320 | docker run --name postgresql -itd --restart always \ 321 | sameersbn/postgresql:15-20230628 -c logging_collector=on 322 | ``` 323 | 324 | To access the PostgreSQL logs you can use `docker exec`. For example: 325 | 326 | ```bash 327 | docker exec -it postgresql tail -f /var/log/postgresql/postgresql-9.4-main.log 328 | ``` 329 | 330 | # UID/GID mapping 331 | 332 | The files and processes created by the container are owned by the `postgres` user that is internal to the container. In the absense of user namespace in docker the UID and GID of the containers `postgres` user may have different meaning on the host. 333 | 334 | For example, a user on the host with the same UID and/or GID as the `postgres` user of the container will be able to access the data in the persistent volumes mounted from the host as well as be able to KILL the `postgres` server process started by the container. 335 | 336 | To circumvent this issue you can specify the UID and GID for the `postgres` user of the container using the `USERMAP_UID` and `USERMAP_GID` variables respectively. 337 | 338 | For example, if you want to assign the `postgres` user of the container the UID and GID `999`: 339 | 340 | ```bash 341 | docker run --name postgresql -itd --restart always \ 342 | --env 'USERMAP_UID=999' --env 'USERMAP_GID=999' \ 343 | sameersbn/postgresql:15-20230628 344 | ``` 345 | 346 | # Maintenance 347 | 348 | ## Upgrading 349 | 350 | To upgrade to newer releases: 351 | 352 | 1. Download the updated Docker image: 353 | 354 | ```bash 355 | docker pull sameersbn/postgresql:15-20230628 356 | ``` 357 | 358 | 2. Stop the currently running image: 359 | 360 | ```bash 361 | docker stop postgresql 362 | ``` 363 | 364 | 3. Remove the stopped container 365 | 366 | ```bash 367 | docker rm -v postgresql 368 | ``` 369 | 370 | 4. Start the updated image 371 | 372 | ```bash 373 | docker run --name postgresql -itd \ 374 | [OPTIONS] \ 375 | sameersbn/postgresql:15-20230628 376 | ``` 377 | 378 | ## Shell Access 379 | 380 | For debugging and maintenance purposes you may want access the containers shell. If you are using Docker version `1.3.0` or higher you can access a running containers shell by starting `bash` using `docker exec`: 381 | 382 | ```bash 383 | docker exec -it postgresql bash 384 | ``` 385 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 15-20230628 2 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | PostgreSQL: 2 | restart: always 3 | image: sameersbn/postgresql:15-20230628 4 | ports: 5 | - "5432:5432" 6 | environment: 7 | - DEBUG=false 8 | 9 | - DB_USER= 10 | - DB_PASS= 11 | - DB_NAME= 12 | - DB_TEMPLATE= 13 | 14 | - DB_EXTENSION= 15 | 16 | - REPLICATION_MODE= 17 | - REPLICATION_USER= 18 | - REPLICATION_PASS= 19 | - REPLICATION_SSLMODE= 20 | command: "--wal_keep_segments=32 --logging_collector=off" 21 | volumes: 22 | - postgresql:/var/lib/postgresql 23 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | # shellcheck source=runtime/functions 5 | source "${PG_APP_HOME}/functions" 6 | 7 | [[ ${DEBUG} == true ]] && set -x 8 | 9 | # allow arguments to be passed to postgres 10 | if [[ ${1:0:1} = '-' ]]; then 11 | EXTRA_ARGS="$@" 12 | set -- 13 | elif [[ ${1} == postgres || ${1} == $(command -v postgres) ]]; then 14 | EXTRA_ARGS="${@:2}" 15 | set -- 16 | fi 17 | 18 | # default behaviour is to launch postgres 19 | if [[ -z ${1} ]]; then 20 | map_uidgid 21 | 22 | create_datadir 23 | create_certdir 24 | create_logdir 25 | create_rundir 26 | 27 | set_resolvconf_perms 28 | 29 | configure_postgresql 30 | 31 | echo "Starting PostgreSQL ${PG_VERSION}..." 32 | exec start-stop-daemon --start --chuid "${PG_USER}:${PG_USER}" \ 33 | --exec "${PG_BINDIR}/postgres" -- -D "${PG_DATADIR}" ${EXTRA_ARGS} 34 | else 35 | exec "$@" 36 | fi 37 | 38 | -------------------------------------------------------------------------------- /runtime/env-defaults: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PG_SSL=${PG_SSL:-} 4 | 5 | PG_TRUST_LOCALNET=${PG_TRUST_LOCALNET:-$PSQL_TRUST_LOCALNET} # backward compatibility 6 | PG_TRUST_LOCALNET=${PG_TRUST_LOCALNET:-false} 7 | 8 | REPLICATION_MODE=${REPLICATION_MODE:-$PSQL_MODE} # backward compatibility 9 | REPLICATION_MODE=${REPLICATION_MODE:-} 10 | REPLICATION_USER=${REPLICATION_USER:-} 11 | REPLICATION_PASS=${REPLICATION_PASS:-} 12 | REPLICATION_HOST=${REPLICATION_HOST:-} 13 | REPLICATION_PORT=${REPLICATION_PORT:-5432} 14 | REPLICATION_SSLMODE=${REPLICATION_SSLMODE:-prefer} 15 | 16 | DB_NAME=${DB_NAME:-} 17 | DB_USER=${DB_USER:-} 18 | DB_PASS=${DB_PASS:-} 19 | DB_TEMPLATE=${DB_TEMPLATE:-template1} 20 | 21 | DB_EXTENSION=${DB_EXTENSION:-} 22 | -------------------------------------------------------------------------------- /runtime/functions: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | shopt -s extglob 4 | source ${PG_APP_HOME}/env-defaults 5 | 6 | PG_CONF=${PG_DATADIR}/postgresql.conf 7 | PG_HBA_CONF=${PG_DATADIR}/pg_hba.conf 8 | PG_IDENT_CONF=${PG_DATADIR}/pg_ident.conf 9 | PG_RECOVERY_CONF=${PG_DATADIR}/recovery.conf 10 | 11 | ## Execute command as PG_USER 12 | exec_as_postgres() { 13 | sudo -HEu ${PG_USER} "$@" 14 | } 15 | 16 | map_uidgid() { 17 | USERMAP_ORIG_UID=$(id -u ${PG_USER}) 18 | USERMAP_ORIG_GID=$(id -g ${PG_USER}) 19 | USERMAP_GID=${USERMAP_GID:-${USERMAP_UID:-$USERMAP_ORIG_GID}} 20 | USERMAP_UID=${USERMAP_UID:-$USERMAP_ORIG_UID} 21 | if [[ ${USERMAP_UID} != ${USERMAP_ORIG_UID} ]] || [[ ${USERMAP_GID} != ${USERMAP_ORIG_GID} ]]; then 22 | echo "Adapting uid and gid for ${PG_USER}:${PG_USER} to $USERMAP_UID:$USERMAP_GID" 23 | groupmod -o -g ${USERMAP_GID} ${PG_USER} 24 | sed -i -e "s|:${USERMAP_ORIG_UID}:${USERMAP_GID}:|:${USERMAP_UID}:${USERMAP_GID}:|" /etc/passwd 25 | fi 26 | } 27 | 28 | create_datadir() { 29 | echo "Initializing datadir..." 30 | mkdir -p ${PG_HOME} 31 | if [[ -d ${PG_DATADIR} ]]; then 32 | find ${PG_DATADIR} -type f | xargs chmod 0600 33 | find ${PG_DATADIR} -type d | xargs chmod 0700 34 | fi 35 | chown -R ${PG_USER}:${PG_USER} ${PG_HOME} 36 | } 37 | 38 | create_certdir() { 39 | echo "Initializing certdir..." 40 | mkdir -p ${PG_CERTDIR} 41 | [[ -f ${PG_CERTDIR}/server.crt ]] && chmod 0644 ${PG_CERTDIR}/server.crt 42 | [[ -f ${PG_CERTDIR}/server.key ]] && chmod 0640 ${PG_CERTDIR}/server.key 43 | chmod 0755 ${PG_CERTDIR} 44 | chown -R root:${PG_USER} ${PG_CERTDIR} 45 | } 46 | 47 | create_logdir() { 48 | echo "Initializing logdir..." 49 | mkdir -p ${PG_LOGDIR} 50 | chmod -R 1775 ${PG_LOGDIR} 51 | chown -R root:${PG_USER} ${PG_LOGDIR} 52 | } 53 | 54 | create_rundir() { 55 | echo "Initializing rundir..." 56 | mkdir -p ${PG_RUNDIR} ${PG_RUNDIR}/${PG_VERSION}-main.pg_stat_tmp 57 | chmod -R 0755 ${PG_RUNDIR} 58 | chmod g+s ${PG_RUNDIR} 59 | chown -R ${PG_USER}:${PG_USER} ${PG_RUNDIR} 60 | } 61 | 62 | set_postgresql_param() { 63 | local key=${1} 64 | local value=${2} 65 | local verbosity=${3:-verbose} 66 | 67 | if [[ -n ${value} ]]; then 68 | local current=$(exec_as_postgres sed -n -e "s/^\(${key} = '\)\([^ ']*\)\(.*\)$/\2/p" ${PG_CONF}) 69 | if [[ "${current}" != "${value}" ]]; then 70 | if [[ ${verbosity} == verbose ]]; then 71 | echo "‣ Setting postgresql.conf parameter: ${key} = '${value}'" 72 | fi 73 | value="$(echo "${value}" | sed 's|[&]|\\&|g')" 74 | exec_as_postgres sed -i "s|^[#]*[ ]*${key} = .*|${key} = '${value}'|" ${PG_CONF} 75 | fi 76 | fi 77 | } 78 | 79 | set_recovery_param() { 80 | local key=${1} 81 | local value=${2} 82 | local hide=${3} 83 | if [[ -n ${value} ]]; then 84 | local current=$(exec_as_postgres sed -n -e "s/^\(.*\)\(${key}=\)\([^ ']*\)\(.*\)$/\3/p" ${PG_RECOVERY_CONF}) 85 | if [[ "${current}" != "${value}" ]]; then 86 | case ${hide} in 87 | true) echo "‣ Setting primary_conninfo parameter: ${key}" ;; 88 | *) echo "‣ Setting primary_conninfo parameter: ${key} = '${value}'" ;; 89 | esac 90 | exec_as_postgres sed -i "s|${key}=[^ ']*|${key}=${value}|" ${PG_RECOVERY_CONF} 91 | fi 92 | fi 93 | } 94 | 95 | set_hba_param() { 96 | local value=${1} 97 | if ! grep -q "$(sed "s| | \\\+|g" <<< ${value})" ${PG_HBA_CONF}; then 98 | echo "${value}" >> ${PG_HBA_CONF} 99 | fi 100 | } 101 | 102 | configure_ssl() { 103 | ## NOT SURE IF THIS IS A GOOD ALTERNATIVE TO ENABLE SSL SUPPORT BY DEFAULT ## 104 | ## BECAUSE USERS WHO PULL A PREBUILT IMAGE WILL HAVE THE SAME CERTIFICATES ## 105 | # if [[ ! -f ${PG_CERTDIR}/server.crt && ! -f ${PG_CERTDIR}/server.key ]]; then 106 | # if [[ -f /etc/ssl/certs/ssl-cert-snakeoil.pem && -f /etc/ssl/private/ssl-cert-snakeoil.key ]]; then 107 | # ln -sf /etc/ssl/certs/ssl-cert-snakeoil.pem ${PG_CERTDIR}/server.crt 108 | # ln -sf /etc/ssl/private/ssl-cert-snakeoil.key ${PG_CERTDIR}/server.key 109 | # fi 110 | # fi 111 | 112 | if [[ -f ${PG_CERTDIR}/server.crt && -f ${PG_CERTDIR}/server.key ]]; then 113 | PG_SSL=${PG_SSL:-on} 114 | set_postgresql_param "ssl_cert_file" "${PG_CERTDIR}/server.crt" 115 | set_postgresql_param "ssl_key_file" "${PG_CERTDIR}/server.key" 116 | fi 117 | PG_SSL=${PG_SSL:-off} 118 | set_postgresql_param "ssl" "${PG_SSL}" 119 | } 120 | 121 | configure_hot_standby() { 122 | case ${REPLICATION_MODE} in 123 | slave|snapshot|backup) ;; 124 | *) 125 | echo "Configuring hot standby..." 126 | set_postgresql_param "wal_level" "hot_standby" 127 | set_postgresql_param "max_wal_senders" "16" 128 | set_postgresql_param "checkpoint_segments" "8" 129 | set_postgresql_param "wal_keep_segments" "32" 130 | set_postgresql_param "hot_standby" "on" 131 | ;; 132 | esac 133 | } 134 | 135 | initialize_database() { 136 | if [[ ! -f ${PG_DATADIR}/PG_VERSION ]]; then 137 | case ${REPLICATION_MODE} in 138 | slave|snapshot|backup) 139 | if [[ -z $REPLICATION_HOST ]]; then 140 | echo "ERROR! Cannot continue without the REPLICATION_HOST. Exiting..." 141 | exit 1 142 | fi 143 | 144 | if [[ -z $REPLICATION_USER ]]; then 145 | echo "ERROR! Cannot continue without the REPLICATION_USER. Exiting..." 146 | exit 1 147 | fi 148 | 149 | if [[ -z $REPLICATION_PASS ]]; then 150 | echo "ERROR! Cannot continue without the REPLICATION_PASS. Exiting..." 151 | exit 1 152 | fi 153 | 154 | echo -n "Waiting for $REPLICATION_HOST to accept connections (60s timeout)" 155 | timeout=60 156 | while ! ${PG_BINDIR}/pg_isready -h $REPLICATION_HOST -p $REPLICATION_PORT -t 1 >/dev/null 2>&1 157 | do 158 | timeout=$(expr $timeout - 1) 159 | if [[ $timeout -eq 0 ]]; then 160 | echo "Timeout! Exiting..." 161 | exit 1 162 | fi 163 | echo -n "." 164 | sleep 1 165 | done 166 | echo 167 | 168 | case ${REPLICATION_MODE} in 169 | slave) 170 | echo "Replicating initial data from $REPLICATION_HOST..." 171 | exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ 172 | -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X stream -w >/dev/null 173 | ;; 174 | snapshot) 175 | echo "Generating a snapshot data on $REPLICATION_HOST..." 176 | exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ 177 | -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null 178 | ;; 179 | backup) 180 | echo "Backing up data on $REPLICATION_HOST..." 181 | exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ 182 | -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null 183 | exit 0 184 | ;; 185 | esac 186 | ;; 187 | *) 188 | echo "Initializing database..." 189 | PG_OLD_VERSION=$(find ${PG_HOME}/+([0-9])?(.[0-9])/main -maxdepth 1 -name PG_VERSION 2>/dev/null | grep -v $PG_VERSION | sort -r | head -n1 | cut -d'/' -f5) 190 | if [[ -n ${PG_OLD_VERSION} ]]; then 191 | echo "‣ Migrating PostgreSQL ${PG_OLD_VERSION} data to ${PG_VERSION}..." 192 | 193 | # protect the existing data from being altered by apt-get 194 | mv ${PG_HOME}/${PG_OLD_VERSION} ${PG_HOME}/${PG_OLD_VERSION}.migrating 195 | 196 | echo "‣ Installing PostgreSQL ${PG_OLD_VERSION}..." 197 | if ! ( apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-${PG_OLD_VERSION} postgresql-client-${PG_OLD_VERSION} ) >/dev/null; then 198 | echo "ERROR! Failed to install PostgreSQL ${PG_OLD_VERSION}. Exiting..." 199 | # first move the old data back 200 | rm -rf ${PG_HOME}/${PG_OLD_VERSION} 201 | mv ${PG_HOME}/${PG_OLD_VERSION}.migrating ${PG_HOME}/${PG_OLD_VERSION} 202 | exit 1 203 | fi 204 | rm -rf /var/lib/apt/lists/* 205 | 206 | # we're ready to migrate, move back the old data and remove the trap 207 | rm -rf ${PG_HOME}/${PG_OLD_VERSION} 208 | mv ${PG_HOME}/${PG_OLD_VERSION}.migrating ${PG_HOME}/${PG_OLD_VERSION} 209 | fi 210 | 211 | if [[ -n $PG_PASSWORD ]]; then 212 | echo "${PG_PASSWORD}" > /tmp/pwfile 213 | fi 214 | 215 | exec_as_postgres ${PG_BINDIR}/initdb --pgdata=${PG_DATADIR} \ 216 | --username=${PG_USER} --encoding=unicode --auth=trust ${PG_PASSWORD:+--pwfile=/tmp/pwfile} >/dev/null 217 | 218 | if [[ -n ${PG_OLD_VERSION} ]]; then 219 | PG_OLD_BINDIR=/usr/lib/postgresql/${PG_OLD_VERSION}/bin 220 | PG_OLD_DATADIR=${PG_HOME}/${PG_OLD_VERSION}/main 221 | PG_OLD_CONF=${PG_OLD_DATADIR}/postgresql.conf 222 | PG_OLD_HBA_CONF=${PG_OLD_DATADIR}/pg_hba.conf 223 | PG_OLD_IDENT_CONF=${PG_OLD_DATADIR}/pg_ident.conf 224 | 225 | echo -n "‣ Migration in progress. Please be patient..." 226 | exec_as_postgres ${PG_BINDIR}/pg_upgrade \ 227 | -b ${PG_OLD_BINDIR} -B ${PG_BINDIR} \ 228 | -d ${PG_OLD_DATADIR} -D ${PG_DATADIR} \ 229 | -o "-c config_file=${PG_OLD_CONF} --hba_file=${PG_OLD_HBA_CONF} --ident_file=${PG_OLD_IDENT_CONF}" \ 230 | -O "-c config_file=${PG_CONF} --hba_file=${PG_HBA_CONF} --ident_file=${PG_IDENT_CONF}" 231 | echo 232 | fi 233 | ;; 234 | esac 235 | 236 | configure_hot_standby 237 | 238 | # Change DSM from `posix' to `sysv' if we are inside an lx-brand container 239 | if [[ $(uname -v) == "BrandZ virtual linux" ]]; then 240 | set_postgresql_param "dynamic_shared_memory_type" "sysv" 241 | fi 242 | fi 243 | 244 | # configure path to data_directory 245 | set_postgresql_param "data_directory" "${PG_DATADIR}" 246 | 247 | # configure logging 248 | set_postgresql_param "log_directory" "${PG_LOGDIR}" 249 | set_postgresql_param "log_filename" "postgresql-${PG_VERSION}-main.log" 250 | 251 | # trust connections from local network 252 | if [[ ${PG_TRUST_LOCALNET} == true ]]; then 253 | echo "Trusting connections from the local network..." 254 | set_hba_param "host all all samenet trust" 255 | fi 256 | 257 | # allow remote connections to postgresql database 258 | set_hba_param "host all all 0.0.0.0/0 md5" 259 | } 260 | 261 | set_resolvconf_perms() { 262 | echo "Setting resolv.conf ACLs..." 263 | setfacl -m user:${PG_USER}:r /etc/resolv.conf || true 264 | } 265 | 266 | configure_recovery() { 267 | if [[ ${REPLICATION_MODE} == slave ]]; then 268 | echo "Configuring recovery..." 269 | if [[ ! -f ${PG_RECOVERY_CONF} ]]; then 270 | # initialize recovery.conf on the firstrun (slave only) 271 | exec_as_postgres touch ${PG_RECOVERY_CONF} 272 | ( echo "standby_mode = 'on'"; 273 | echo "primary_conninfo = 'host=${REPLICATION_HOST} port=${REPLICATION_PORT} user=${REPLICATION_USER} password=${REPLICATION_PASS} sslmode=${REPLICATION_SSLMODE}'"; 274 | ) > ${PG_RECOVERY_CONF} 275 | else 276 | set_recovery_param "host" "${REPLICATION_HOST}" 277 | set_recovery_param "port" "${REPLICATION_PORT}" 278 | set_recovery_param "user" "${REPLICATION_USER}" 279 | set_recovery_param "password" "${REPLICATION_PASS}" "true" 280 | set_recovery_param "sslmode" "${REPLICATION_SSLMODE}" 281 | fi 282 | else 283 | # recovery.conf can only exist on a slave node, its existence otherwise causes problems 284 | rm -rf ${PG_RECOVERY_CONF} 285 | fi 286 | } 287 | 288 | create_user() { 289 | if [[ -n ${DB_USER} ]]; then 290 | case $REPLICATION_MODE in 291 | slave|snapshot|backup) 292 | echo "INFO! Database user cannot be created on a $REPLICATION_MODE node. Skipping..." 293 | ;; 294 | *) 295 | if [[ -z ${DB_PASS} ]]; then 296 | echo "ERROR! Please specify a password for DB_USER in DB_PASS. Exiting..." 297 | exit 1 298 | fi 299 | echo "Creating database user: ${DB_USER}" 300 | if [[ -z $(psql -U ${PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_user WHERE usename = '${DB_USER}'";) ]]; then 301 | psql -U ${PG_USER} -c "CREATE ROLE \"${DB_USER}\" with LOGIN CREATEDB PASSWORD '${DB_PASS}';" >/dev/null 302 | fi 303 | ;; 304 | esac 305 | fi 306 | } 307 | 308 | load_extensions() { 309 | local database=${1?missing argument} 310 | 311 | if [[ ${DB_UNACCENT} == true ]]; then 312 | echo 313 | echo "WARNING: " 314 | echo " The DB_UNACCENT option will be deprecated in favour of DB_EXTENSION soon." 315 | echo " Please migrate to using DB_EXTENSION" 316 | echo 317 | echo "‣ Loading unaccent extension..." 318 | psql -U ${PG_USER} -d ${database} -c "CREATE EXTENSION IF NOT EXISTS unaccent;" >/dev/null 2>&1 319 | fi 320 | 321 | for extension in $(awk -F',' '{for (i = 1 ; i <= NF ; i++) print $i}' <<< "${DB_EXTENSION}"); do 322 | echo "‣ Loading ${extension} extension..." 323 | psql -U ${PG_USER} -d ${database} -c "CREATE EXTENSION IF NOT EXISTS ${extension};" >/dev/null 2>&1 324 | done 325 | } 326 | 327 | create_database() { 328 | if [[ -n ${DB_NAME} ]]; then 329 | case $REPLICATION_MODE in 330 | slave|snapshot|backup) 331 | echo "INFO! Database cannot be created on a $REPLICATION_MODE node. Skipping..." 332 | ;; 333 | *) 334 | for database in $(awk -F',' '{for (i = 1 ; i <= NF ; i++) print $i}' <<< "${DB_NAME}"); do 335 | echo "Creating database: ${database}..." 336 | if [[ -z $(psql -U ${PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_database WHERE datname = '${database}'";) ]]; then 337 | psql -U ${PG_USER} -c "CREATE DATABASE \"${database}\" WITH TEMPLATE = \"${DB_TEMPLATE}\";" >/dev/null 338 | fi 339 | 340 | load_extensions ${database} 341 | 342 | if [[ -n ${DB_USER} ]]; then 343 | echo "‣ Granting access to ${DB_USER} user..." 344 | psql -U ${PG_USER} -c "GRANT ALL PRIVILEGES ON DATABASE \"${database}\" to \"${DB_USER}\";" >/dev/null 345 | fi 346 | done 347 | ;; 348 | esac 349 | fi 350 | } 351 | 352 | create_replication_user() { 353 | if [[ -n ${REPLICATION_USER} ]]; then 354 | case $REPLICATION_MODE in 355 | slave|snapshot|backup) ;; # replication user can only be created on the master 356 | *) 357 | if [[ -z ${REPLICATION_PASS} ]]; then 358 | echo "ERROR! Please specify a password for REPLICATION_USER in REPLICATION_PASS. Exiting..." 359 | exit 1 360 | fi 361 | 362 | echo "Creating replication user: ${REPLICATION_USER}" 363 | if [[ -z $(psql -U ${PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_user WHERE usename = '${REPLICATION_USER}'";) ]]; then 364 | psql -U ${PG_USER} -c "CREATE ROLE \"${REPLICATION_USER}\" WITH REPLICATION LOGIN ENCRYPTED PASSWORD '${REPLICATION_PASS}';" >/dev/null 365 | fi 366 | 367 | set_hba_param "host replication ${REPLICATION_USER} 0.0.0.0/0 md5" 368 | ;; 369 | esac 370 | fi 371 | } 372 | 373 | configure_postgresql() { 374 | initialize_database 375 | configure_recovery 376 | configure_ssl 377 | 378 | # start postgres server internally for the creation of users and databases 379 | rm -rf ${PG_DATADIR}/postmaster.pid 380 | set_postgresql_param "listen_addresses" "127.0.0.1" quiet 381 | exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w start >/dev/null 382 | 383 | create_user 384 | create_database 385 | create_replication_user 386 | 387 | # stop the postgres server 388 | exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w stop >/dev/null 389 | 390 | # listen on all interfaces 391 | set_postgresql_param "listen_addresses" "*" quiet 392 | } 393 | -------------------------------------------------------------------------------- /scripts/release-notes.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | RELEASE=${GIT_TAG:-$1} 4 | 5 | if [ -z "${RELEASE}" ]; then 6 | echo "Usage:" 7 | echo "./scripts/release-notes.sh v0.1.0" 8 | exit 1 9 | fi 10 | 11 | if ! git rev-list ${RELEASE} >/dev/null 2>&1; then 12 | echo "${RELEASE} does not exist" 13 | exit 14 | fi 15 | 16 | PREV_RELEASE=${PREV_RELEASE:-$(git describe --tags --abbrev=0 ${RELEASE}^)} 17 | PREV_RELEASE=${PREV_RELEASE:-$(git rev-list --max-parents=0 ${RELEASE}^)} 18 | NOTABLE_CHANGES=$(git cat-file -p ${RELEASE} | sed '/-----BEGIN PGP SIGNATURE-----/,//d' | tail -n +6) 19 | CHANGELOG=$(git log --no-merges --pretty=format:'- [%h] %s (%aN)' ${PREV_RELEASE}..${RELEASE}) 20 | if [ $? -ne 0 ]; then 21 | echo "Error creating changelog" 22 | exit 1 23 | fi 24 | 25 | cat <