46 Commits

Author SHA1 Message Date
Sameer Naik 197d53e0a1 release 9.4-11 2015-12-13 14:55:54 +05:30
Sameer Naik 88208071b0 dockerfile: upgrade to sameersbn/ubuntu:14.04.20151213 2015-12-13 14:55:20 +05:30
Sameer Naik 38dc995884 added PG_PASSWORD variable to specify password for postgres user
Refer #43
2015-12-11 15:33:59 +05:30
Sameer Naik 116b158c1a release 9.4-10 2015-12-09 22:34:11 +05:30
Sameer Naik 60a249dd7d ensure required defaults are set at every start 2015-12-09 22:33:39 +05:30
Sameer Naik 490f33c05c release 9.4-9 2015-12-05 10:09:23 +05:30
Sameer Naik c1cce0328c disable trigger_file option from recovery.conf
Triggering of a slave to stop replication and enable writing works.
However if a second slave (with data persistence) is reconfigured to
use the first slave (triggered) as the master, the second slave cannot
replicate the data.

At the moment the only way to convert a slave to a master is to stop it
and start it as a master in which case the above issue is not seen.

To avoid users from trying to trigger a slave, we removed the config
altogether until the issue can be resolved.
2015-11-30 11:57:44 +05:30
Sameer Naik ba9d02ecb3 escape & characters in set_postgresql_param 2015-11-29 19:06:10 +05:30
Sameer Naik ee497d68d0 sed variable expansion works by default when double quotes are used 2015-11-29 19:05:08 +05:30
Sameer Naik 8572e6bc77 readme: fixed typo 2015-11-29 11:52:47 +05:30
Sameer Naik cdad6abd5a print value being set in recovery.conf 2015-11-29 11:46:03 +05:30
Sameer Naik d0904a4ca1 set default values of REPLICATION_PORT and REPLICATION_SSLMODE in env-defaults 2015-11-29 11:43:44 +05:30
Sameer Naik 3a838eaa69 readme: fixed typo 2015-11-28 22:23:29 +05:30
Sameer Naik ce64f22779 readme: slave can be restarted to continue as a regular read/write instance 2015-11-28 22:21:17 +05:30
Sameer Naik d92102d951 added DEBUG option to enable bash debugging 2015-11-28 21:19:42 +05:30
Sameer Naik a1ca18b780 recovery.conf can exist only on a slave node
It's existence otherwise cause issues while replication users, as such
the `configure_recovery` function is promoted higher in the
initialization sequence.
2015-11-28 21:18:16 +05:30
Sameer Naik 22c969c88c removed launch sequence from functions import 2015-11-28 14:51:18 +05:30
Sameer Naik 8458c2a3ca user and database can only be created on the master node 2015-11-28 14:22:46 +05:30
Sameer Naik e6dff6ef93 readme: --env consistency 2015-11-28 13:48:23 +05:30
Sameer Naik edee0f1ce7 removed locale setting entry from TOC 2015-11-28 13:15:55 +05:30
Sameer Naik 1f87e4aa1b removed PG_LOCALE option (doesn't work!) 2015-11-28 13:13:44 +05:30
Sameer Naik a6a2a78585 readme: add imagelayers.io badge 2015-11-28 11:45:54 +05:30
Sameer Naik 2668b06886 readme: fixes 2015-11-27 19:36:13 +05:30
Sameer Naik 27ffe14e79 readme: moved Command-line arguments section before Logs 2015-11-27 18:01:36 +05:30
Sameer Naik 6c7706c8f1 readme: moved logs section towards the end 2015-11-27 18:00:01 +05:30
Sameer Naik 710299161a readme: fixed typo 2015-11-27 16:49:13 +05:30
Sameer Naik 22dba65610 add support for creating backups using pg_basebackup 2015-11-27 16:48:24 +05:30
Sameer Naik 73be444cea added missing ;; to case 2015-11-27 16:24:07 +05:30
Sameer Naik c7bae0d677 Merge branch 'complete-rewrite-and-reorg' 2015-11-27 15:44:26 +05:30
Sameer Naik c5522c9fda complete rewrite of the README 2015-11-27 15:39:10 +05:30
Sameer Naik ce2caf3937 DB_LOCALE config parameter renamed to PG_LOCALE 2015-11-27 15:02:50 +05:30
Sameer Naik 5e09110558 configure logging options on first run 2015-11-27 11:04:52 +05:30
Sameer Naik afe467bec7 added sample docker-compose.yml 2015-11-27 10:07:56 +05:30
Sameer Naik 7f1e051f1a remove extra whitespace 2015-11-26 22:29:20 +05:30
Sameer Naik 978c70a78a moved default script variables to env-defaults 2015-11-26 21:06:13 +05:30
Sameer Naik faaa87cc64 separated out entrypoint.sh functions to a functions bash module 2015-11-26 21:04:17 +05:30
Sameer Naik 6418c9e044 added PG_SSL parameter to enable/disable SSL support
`PG_SSL` is automatically set to `on` if `server.crt` and `server.key`
can be found at `/etc/postgresql/certs`

Closes #32
2015-11-26 21:03:51 +05:30
Sameer Naik 5f6024062f defined /etc/postgresql/certs as the mountpoint to install SSL key and certificate 2015-11-26 21:03:51 +05:30
Sameer Naik 7eeda81f1e set default value of REPLICATION_SSLMODE to prefer 2015-11-26 21:03:51 +05:30
Sameer Naik 761ec9645c PSQL_SSLMODE config parameter renamed to REPLICATION_SSLMODE 2015-11-26 21:03:51 +05:30
Sameer Naik b6f0cba6a7 PSQL_MODE config parameter renamed to REPLICATION_MODE 2015-11-26 21:03:51 +05:30
Sameer Naik de5295ffa7 PSQL_TRUST_LOCALNET config parameter renamed to PG_TRUST_LOCALNET 2015-11-26 21:03:51 +05:30
Sameer Naik c8e9dec549 complete rewrite of existing feature set
Closes #40
2015-11-26 21:03:49 +05:30
Sameer Naik a68b58aefe fix: set ssl config to off or on 2015-11-23 22:25:23 +05:30
Sameer Naik f3b18c1f1b avoid duplicate entries in configuration files. Refer #40 2015-11-23 20:46:11 +05:30
Sameer Naik b4a5810e13 readme: docker build one liner 2015-11-19 22:32:41 +05:30
8 changed files with 707 additions and 389 deletions
+16
View File
@@ -1,5 +1,21 @@
# Changelog # Changelog
**9.4-11**
- added `PG_PASSWORD` variable to specify password for `postgres` user
**9.4-9**
- complete rewrite
- `PSQL_TRUST_LOCALNET` config parameter renamed to `PG_TRUST_LOCALNET`
- `PSQL_MODE` config parameter renamed to `REPLICATION_MODE`
- `PSQL_SSLMODE` config parameter renamed to `REPLICATION_SSLMODE`
- defined `/etc/postgresql/certs` as the mountpoint to install SSL key and certificate
- added `PG_SSL` parameter to enable/disable SSL support
- `DB_LOCALE` config parameter renamed to `PG_LOCALE`
- complete rewrite of the README
- add support for creating backups using `pg_basebackup`
- removed `PG_LOCALE` option (doesn't work!)
- added `DEBUG` option to enable bash debugging
**9.4-2** **9.4-2**
- added replication options - added replication options
+13 -7
View File
@@ -1,26 +1,32 @@
FROM sameersbn/ubuntu:14.04.20151117 FROM sameersbn/ubuntu:14.04.20151213
MAINTAINER sameer@damagehead.com MAINTAINER sameer@damagehead.com
ENV PG_VERSION=9.4 \ ENV PG_APP_HOME="/etc/docker-postgresql"\
PG_VERSION=9.4 \
PG_USER=postgres \ PG_USER=postgres \
PG_HOME=/var/lib/postgresql \ PG_HOME=/var/lib/postgresql \
PG_RUNDIR=/run/postgresql \ PG_RUNDIR=/run/postgresql \
PG_LOGDIR=/var/log/postgresql PG_LOGDIR=/var/log/postgresql \
PG_CERTDIR=/etc/postgresql/certs
ENV PG_BINDIR="/usr/lib/postgresql/${PG_VERSION}/bin" \ ENV PG_BINDIR=/usr/lib/postgresql/${PG_VERSION}/bin \
PG_CONFDIR="${PG_HOME}/${PG_VERSION}/main" \ PG_DATADIR=${PG_HOME}/${PG_VERSION}/main
PG_DATADIR="${PG_HOME}/${PG_VERSION}/main"
RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \
&& echo 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' > /etc/apt/sources.list.d/pgdg.list \ && echo 'deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main' > /etc/apt/sources.list.d/pgdg.list \
&& apt-get update \ && apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-${PG_VERSION} postgresql-client-${PG_VERSION} postgresql-contrib-${PG_VERSION} \ && DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-${PG_VERSION} postgresql-client-${PG_VERSION} postgresql-contrib-${PG_VERSION} \
&& ln -sf ${PG_DATADIR}/postgresql.conf /etc/postgresql/${PG_VERSION}/main/postgresql.conf \
&& ln -sf ${PG_DATADIR}/pg_hba.conf /etc/postgresql/${PG_VERSION}/main/pg_hba.conf \
&& ln -sf ${PG_DATADIR}/pg_ident.conf /etc/postgresql/${PG_VERSION}/main/pg_ident.conf \
&& rm -rf ${PG_HOME} \ && rm -rf ${PG_HOME} \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
COPY runtime/ ${PG_APP_HOME}/
COPY entrypoint.sh /sbin/entrypoint.sh COPY entrypoint.sh /sbin/entrypoint.sh
RUN chmod 755 /sbin/entrypoint.sh RUN chmod 755 /sbin/entrypoint.sh
EXPOSE 5432/tcp EXPOSE 5432/tcp
VOLUME ["${PG_HOME}", "${PG_RUNDIR}"] VOLUME ["${PG_HOME}", "${PG_RUNDIR}"]
CMD ["/sbin/entrypoint.sh"] WORKDIR ${PG_HOME}
ENTRYPOINT ["/sbin/entrypoint.sh"]
+264 -151
View File
@@ -1,269 +1,382 @@
[![Circle CI](https://circleci.com/gh/sameersbn/docker-postgresql.svg?style=svg)](https://circleci.com/gh/sameersbn/docker-postgresql) [![Docker Repository on Quay.io](https://quay.io/repository/sameersbn/postgresql/status "Docker Repository on Quay.io")](https://quay.io/repository/sameersbn/postgresql) [![Circle CI](https://circleci.com/gh/sameersbn/docker-postgresql.svg?style=shield)](https://circleci.com/gh/sameersbn/docker-postgresql) [![Docker Repository on Quay.io](https://quay.io/repository/sameersbn/postgresql/status "Docker Repository on Quay.io")](https://quay.io/repository/sameersbn/postgresql) [![](https://badge.imagelayers.io/sameersbn/postgresql.svg)](https://imagelayers.io/?images=sameersbn/postgresql:latest 'Get your own badge on imagelayers.io')
# Table of Contents # sameersbn/postgresql:9.4-11
- [Introduction](#introduction) - [Introduction](#introduction)
- [Changelog](Changelog.md) - [Contributing](#contributing)
- [Contributing](#contributing) - [Issues](#issues)
- [Reporting Issues](#reporting-issues) - [Getting started](#getting-started)
- [Installation](#installation) - [Installation](#installation)
- [Quick Start](#quick-start) - [Quickstart](#quickstart)
- [Persistence](#persistence) - [Persistence](#persistence)
- [Creating User and Database at Launch](#creating-user-and-database-at-launch) - [Trusting local connections](#trusting-local-connections)
- [Creating a Snapshot or Slave Database](#creating-a-snapshot-or-slave-database) - [Setting `postgres` user password](#setting-postgres-user-password)
- [Host UID / GID Mapping](#host-uid--gid-mapping) - [Creating database user](#creating-database-user)
- [Upgrading](#upgrading) - [Creating databases](#creating-databases)
- [Shell Access](#shell-access) - [Enabling unaccent extension](#enabling-unaccent-extension)
- [Granting user access to a database](#granting-user-access-to-a-database)
- [Creating replication user](#creating-replication-user)
- [Setting up a replication cluster](#setting-up-a-replication-cluster)
- [Creating a snapshot](#creating-a-snapshot)
- [Creating a backup](#creating-a-backup)
- [Command-line arguments](#command-line-arguments)
- [Logs](#logs)
- [UID/GID mapping](#uid-gid-mapping)
- [Maintenance](#maintenance)
- [Upgrading](#upgrading)
- [Shell Access](#shell-access)
# Introduction # Introduction
Dockerfile to build a PostgreSQL container image which can be linked to other containers. `Dockerfile` to create a [Docker](https://www.docker.com/) container image for [PostgreSQL](http://postgresql.org/).
# Contributing PostgreSQL is an object-relational database management system (ORDBMS) with an emphasis on extensibility and standards-compliance [[source](https://en.wikipedia.org/wiki/PostgreSQL)].
## Contributing
If you find this image useful here's how you can help: If you find this image useful here's how you can help:
- Send a Pull Request with your awesome new features and bug fixes - Send a pull request with your awesome features and bug fixes
- Help new users with [Issues](https://github.com/sameersbn/docker-postgresql/issues) they may encounter - Help users resolve their [issues](../../issues?q=is%3Aopen+is%3Aissue).
- Support the development of this image with a [donation](http://www.damagehead.com/donate/) - Support the development of this image with a [donation](http://www.damagehead.com/donate/)
# Reporting Issues ## Issues
Docker is a relatively new project and is being actively developed and tested by a thriving community of developers and testers and every release of Docker features many enhancements and bugfixes. 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.
Given the nature of the development and release cycle it is very important that you have the latest version of docker installed because any issue that you encounter might have already been fixed with a newer docker release. SELinux users should try disabling SELinux using the command `setenforce 0` to see if it resolves the issue.
For ubuntu users I suggest [installing docker](https://docs.docker.com/installation/ubuntulinux/) using docker's own package repository since the version of docker packaged in the ubuntu repositories are a little dated. If the above recommendations do not help then [report your issue](../../issues/new) along with the following information:
Here is the shortform of the installation of an updated version of docker on ubuntu. - Output of the `docker version` and `docker info` commands
- The `docker run` command or `docker-compose.yml` used to start the image. Mask out the sensitive bits.
- Please state if you are using [Boot2Docker](http://www.boot2docker.io), [VirtualBox](https://www.virtualbox.org), etc.
```bash # Getting started
sudo apt-get purge docker.io
curl -s https://get.docker.io/ubuntu/ | sudo sh
sudo apt-get update
sudo apt-get install lxc-docker
```
Fedora and RHEL/CentOS users should try disabling selinux with `setenforce 0` and check if resolves the issue. If it does than there is not much that I can help you with. You can either stick with selinux disabled (not recommended by redhat) or switch to using ubuntu. ## Installation
If using the latest docker version and/or disabling selinux does not fix the issue then please file a issue request on the [issues](https://github.com/sameersbn/docker-postgresql/issues) page.
In your issue report please make sure you provide the following information:
- The host distribution and release version.
- Output of the `docker version` command
- Output of the `docker info` command
- The `docker run` command you used to run the image (mask out the sensitive bits).
# Installation
Automated builds of the image are available on [Dockerhub](https://hub.docker.com/r/sameersbn/postgresql) and is the recommended method of installation. Automated builds of the image are available on [Dockerhub](https://hub.docker.com/r/sameersbn/postgresql) and is the recommended method of installation.
> **Note**: Builds are also available on [Quay.io](https://quay.io/repository/sameersbn/postgresql) > **Note**: Builds are also available on [Quay.io](https://quay.io/repository/sameersbn/postgresql)
```bash ```bash
docker pull sameersbn/postgresql:9.4-8 docker pull sameersbn/postgresql:9.4-11
``` ```
Alternately you can build the image yourself. Alternatively you can build the image yourself.
```bash ```bash
git clone https://github.com/sameersbn/docker-postgresql.git docker build -t sameersbn/postgresql github.com/sameersbn/docker-postgresql
cd docker-postgresql
docker build -t="$USER/postgresql" .
``` ```
# Quick Start ## Quickstart
Run the postgresql image Start PostgreSQL using:
```bash ```bash
docker run --name postgresql -d sameersbn/postgresql:9.4-8 docker run --name postgresql -itd --restart always \
--publish 5432:5432 \
--volume /srv/docker/postgresql:/var/lib/postgresql \
sameersbn/postgresql:9.4-11
``` ```
The simplest way to login to the postgresql container as the administrative `postgres` user is to use the `docker exec` command to attach a new process to the running container and connect to the postgresql server over the unix socket. Login to the PostgreSQL server using:
```bash ```bash
docker exec -it postgresql sudo -u postgres psql docker exec -it postgresql sudo -u postgres psql
``` ```
# Persistence *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/)*
For data persistence a volume should be mounted at `/var/lib/postgresql`. ## Persistence
SELinux users are also required to change the security context of the mount point so that it plays nicely with selinux. For PostgreSQL to preserve its state across container shutdown and startup you should mount a volume at `/var/lib/postgresql`.
> *The [Quickstart](#quickstart) command already mounts a volume for persistence.*
SELinux users should update the security context of the host mountpoint so that it plays nicely with Docker:
```bash ```bash
mkdir -p /opt/postgresql/data mkdir -p /srv/docker/postgresql
sudo chcon -Rt svirt_sandbox_file_t /opt/postgresql/data chcon -Rt svirt_sandbox_file_t /srv/docker/postgresql
``` ```
The updated run command looks like this. ## Trusting local connections
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.
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd --restart always \
-v /opt/postgresql/data:/var/lib/postgresql sameersbn/postgresql:9.4-8 --env 'PG_TRUST_LOCALNET=true' \
sameersbn/postgresql:9.4-11
``` ```
This will make sure that the data stored in the database is not lost when the image is stopped and started again. > **Note**
>
> 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.
# Creating User and Database at Launch ## Setting `postgres` user password
The image allows you to create a user and database at launch time. 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.
To create a new user you should specify the `DB_USER` and `DB_PASS` variables. The following command will create a new user *dbuser* with the password *dbpass*.
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd --restart always \
-e 'DB_USER=dbuser' -e 'DB_PASS=dbpass' \ --env 'PG_PASSWORD=passw0rd' \
sameersbn/postgresql:9.4-8 sameersbn/postgresql:9.4-11
``` ```
**NOTE**
- If the password is not specified the user will not be created
- If the user user already exists no changes will be made
Similarly, you can also create a new database by specifying the database name in the `DB_NAME` variable. > **Note**
>
> - When [persistence](#persistence) is in use, `PG_PASSWORD` is effective on the first run.
> - This feature is only available in the `latest` and versions > `9.4-10`
## Creating database user
A new PostgreSQL database user can be created by specifying the `DB_USER` and `DB_PASS` variables while starting the container.
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd --restart always \
-e 'DB_NAME=dbname' sameersbn/postgresql:9.4-8 --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' \
sameersbn/postgresql:9.4-11
``` ```
You may also specify a comma separated list of database names in the `DB_NAME` variable. The following command creates two new databases named *dbname1* and *dbname2* (p.s. this feature is only available in releases greater than 9.1-1). > **Notes**
>
> - The created user can login remotely
> - The container will error out if a password is not specified for the user
> - No changes will be made if the user already exists
> - Only a single user can be created at each launch
## Creating databases
A new PostgreSQL database can be created by specifying the `DB_NAME` variable while starting the container.
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd --restart always \
-e 'DB_NAME=dbname1,dbname2' \ --env 'DB_NAME=dbname' \
sameersbn/postgresql:9.4-8 sameersbn/postgresql:9.4-11
``` ```
If the `DB_USER` and `DB_PASS` variables are also specified while creating the database, then the user is granted access to the database(s). 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`.
For example, *This feature is only available in releases greater than `9.1-1`*
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd --restart always \
-e 'DB_USER=dbuser' -e 'DB_PASS=dbpass' -e 'DB_NAME=dbname' \ --env 'DB_NAME=dbname1,dbname2' \
sameersbn/postgresql:9.4-8 sameersbn/postgresql:9.4-11
``` ```
will create a user *dbuser* with the password *dbpass*. It will also create a database named *dbname* and the *dbuser* user will have full access to the *dbname* database. # Enabling unaccent extension
The `DB_LOCALE` environment variable can be used to configure the locale used for database creation. Its default value is set to C. Unaccent is a text search dictionary that removes accents (diacritic signs) from lexemes. It's a filtering dictionary, which means its output is always passed to the next dictionary (if any), unlike the normal behavior of dictionaries. This allows accent-insensitive processing for full text search [[source](http://www.postgresql.org/docs/9.4/static/unaccent.html)].
The `PSQL_TRUST_LOCALNET` environment variable can be used to configure postgres to trust connections on the same network. This is handy for other containers to connect without authentication. To enable this behavior, set `PSQL_TRUST_LOCALNET` to `true`. You can enable the unaccent extension on database(s) by specifying `DB_UNACCENT=true`. For example, the following command enables the unaccent extension for the `dbname` database.
For example,
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql -itd \
-e 'PSQL_TRUST_LOCALNET=true' \ --env 'DB_NAME=dbname' --env 'DB_UNACCENT=true' \
sameersbn/postgresql:9.4-8 sameersbn/postgresql:9.4-11
``` ```
This has the effect of adding the following to the `pg_hba.conf` file: *By default the unaccent extension is disabled*
``` ## Granting user access to a database
host all all samenet trust
```
# Creating a Snapshot or Slave Database 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.
You may use the `PSQL_MODE` variable along with `REPLICATION_HOST`, `REPLICATION_PORT`, `REPLICATION_USER` and `REPLICATION_PASS` to create a snapshot of an existing database and enable stream replication.
Your master database must support replication or super-user access for the credentials you specify. The `PSQL_MODE` variable should be set to `master`, for replication on your master node and `slave` or `snapshot` respectively for streaming replication or a point-in-time snapshot of a running instance.
Create a master instance
```bash ```bash
docker run --name='psql-master' -it --rm \ docker run --name postgresql -itd --restart always \
-e 'PSQL_MODE=master' -e 'PSQL_TRUST_LOCALNET=true' \ --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' \
-e 'REPLICATION_USER=replicator' -e 'REPLICATION_PASS=replicatorpass' \ --env 'DB_NAME=dbname1,dbname2' \
-e 'DB_NAME=dbname' -e 'DB_USER=dbuser' -e 'DB_PASS=dbpass' \ sameersbn/postgresql:9.4-11
sameersbn/postgresql:9.4-8
``` ```
Create a streaming replication instance In the above example `dbuser` with be granted access to both the `dbname1` and `dbname2` databases.
## Creating replication user
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.
```bash ```bash
docker run --name='psql-slave' -it --rm \ docker run --name postgresql -itd --restart always \
--link psql-master:psql-master \ --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \
-e 'PSQL_MODE=slave' -e 'PSQL_TRUST_LOCALNET=true' \ sameersbn/postgresql:9.4-11
-e 'REPLICATION_HOST=psql-master' -e 'REPLICATION_PORT=5432' \
-e 'REPLICATION_USER=replicator' -e 'REPLICATION_PASS=replicatorpass' \
sameersbn/postgresql:9.4-8
``` ```
# Enable Unaccent (Search plain text with accent) > **Notes**
>
> - The created user can login remotely
> - The container will error out if a password is not specified for the user
> - No changes will be made if the user already exists
> - Only a single user can be created at each launch
Unaccent is a text search dictionary that removes accents (diacritic signs) from lexemes. It's a filtering dictionary, which means its output is always passed to the next dictionary (if any), unlike the normal behavior of dictionaries. This allows accent-insensitive processing for full text search. *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.*
By default unaccent is configure to `false` ## Setting up a replication cluster
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.
Begin by creating the master node of our cluster:
```bash ```bash
docker run --name postgresql -d \ docker run --name postgresql-master -itd --restart always \
-e 'DB_UNACCENT=true' \ --env 'DB_USER=dbuser' --env 'DB_PASS=dbuserpass' --env 'DB_NAME=dbname' \
sameersbn/postgresql:9.4-8 --env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \
sameersbn/postgresql:9.4-11
``` ```
# Host UID / GID Mapping Notice that no additional arguments are specified while starting the master node of the cluster.
Per default the container is configured to run postgres as user and group `postgres` with some unknown `uid` and `gid`. The host possibly uses these ids for different purposes leading to unfavorable effects. From the host it appears as if the mounted data volumes are owned by the host's user/group `[whatever id postgres has in the image]`. 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.
Also the container processes seem to be executed as the host's user/group `[whatever id postgres has in the image]`. The container can be configured to map the `uid` and `gid` of `postgres` to different ids on host by passing the environment variables `USERMAP_UID` and `USERMAP_GID`. The following command maps the ids to user and group `postgres` on the host. Create a slave node:
```bash ```bash
docker run --name=postgresql -it --rm [options] \ docker run --name postgresql-slave01 -itd --restart always \
--env="USERMAP_UID=$(id -u postgres)" --env="USERMAP_GID=$(id -g postgres)" \ --link postgresql-master:master \
sameersbn/postgresql:9.4-8 --env 'REPLICATION_MODE=slave' --env 'REPLICATION_SSLMODE=prefer' \
--env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \
--env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \
sameersbn/postgresql:9.4-11
``` ```
*In the above command, we used docker links so that we can address the master node using the `master` alias in `REPLICATION_HOST`.*
# Upgrading > **Note**
>
> - The default value of `REPLICATION_PORT` is `5432`
> - The default value of `REPLICATION_SSLMODE` is `prefer`
> - The value of `REPLICATION_USER` and `REPLICATION_PASS` should be the same as the ones specified on the master node.
> - 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.
To upgrade to newer releases, simply follow this 3 step upgrade procedure. And just like that with minimal effort you have a PostgreSQL replication cluster setup. You can create additional slaves to scale the cluster horizontally.
- **Step 1**: Stop the currently running image Here are some important notes about a PostgreSQL replication cluster:
- Writes can only occur on the master
- Slaves are read-only
- For best performance, limit the reads to the slave nodes
## Creating a snapshot
Similar to a creating replication slave node, you can create a snapshot of the master by specifying `REPLICATION_MODE=snapshot`.
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:
```bash ```bash
docker stop postgresql docker run --name postgresql-snapshot -itd --restart always \
--link postgresql-master:master \
--env 'REPLICATION_MODE=snapshot' --env 'REPLICATION_SSLMODE=prefer' \
--env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \
--env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \
sameersbn/postgresql:9.4-11
``` ```
- **Step 2**: Update the docker image. 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.
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.
## Creating a backup
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`.
> The backups are generated with [pg_basebackup](http://www.postgresql.org/docs/9.4/static/app-pgbasebackup.html) using the replication protocol.
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:
```bash ```bash
docker pull sameersbn/postgresql:9.4-8 docker run --name postgresql-backup -it --rm \
--link postgresql-master:master \
--env 'REPLICATION_MODE=backup' --env 'REPLICATION_SSLMODE=prefer' \
--env 'REPLICATION_HOST=master' --env 'REPLICATION_PORT=5432' \
--env 'REPLICATION_USER=repluser' --env 'REPLICATION_PASS=repluserpass' \
--volume /srv/docker/backups/postgresql.$(date +%Y%m%d%H$M%S):/var/lib/postgresql \
sameersbn/postgresql:9.4-11
``` ```
- **Step 3**: Start the image 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`.
## Command-line arguments
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:
```bash ```bash
docker run --name postgresql -d [OPTIONS] sameersbn/postgresql:9.4-8 docker run --name postgresql -itd --restart always \
sameersbn/postgresql:9.4-11 -c log_connections=on
``` ```
# Shell Access 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.
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 using `docker exec` command. ## Logs
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:
```bash
docker run --name postgresql -itd --restart always \
sameersbn/postgresql:9.4-11 -c logging_collector=on
```
To access the PostgreSQL logs you can use `docker exec`. For example:
```bash
docker exec -it postgresql tail -f /var/log/postgresql/postgresql-9.4-main.log
```
# UID/GID mapping
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.
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.
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.
For example, if you want to assign the `postgres` user of the container the UID and GID `999`:
```bash
docker run --name postgresql -itd --restart always \
--env 'USERMAP_UID=999' --env 'USERMAP_GID=999' \
sameersbn/postgresql:9.4-11
```
# Maintenance
## Upgrading
To upgrade to newer releases:
1. Download the updated Docker image:
```bash
docker pull sameersbn/postgresql:9.4-11
```
2. Stop the currently running image:
```bash
docker stop postgresql
```
3. Remove the stopped container
```bash
docker rm -v postgresql
```
4. Start the updated image
```bash
docker run --name postgresql -itd \
[OPTIONS] \
sameersbn/postgresql:9.4-11
```
## Shell Access
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`:
```bash ```bash
docker exec -it postgresql bash docker exec -it postgresql bash
``` ```
If you are using an older version of docker, you can use the [nsenter](http://man7.org/linux/man-pages/man1/nsenter.1.html) linux tool (part of the util-linux package) to access the container shell.
Some linux distros (e.g. ubuntu) use older versions of the util-linux which do not include the `nsenter` tool. To get around this @jpetazzo has created a nice docker image that allows you to install the `nsenter` utility and a helper script named `docker-enter` on these distros.
To install `nsenter` execute the following command on your host,
```bash
docker run --rm -v /usr/local/bin:/target jpetazzo/nsenter
```
Now you can access the container shell using the command
```bash
sudo docker-enter postgresql
```
For more information refer https://github.com/jpetazzo/nsenter
+1 -1
View File
@@ -1 +1 @@
9.4-8 9.4-11
+16
View File
@@ -0,0 +1,16 @@
PostgreSQL:
restart: always
image: sameersbn/postgresql:9.4-11
ports:
- "5432:5432"
environment:
- DEBUG=false
- DB_USER=
- DB_PASS=
- DB_NAME=
- REPLICATION_MODE=
- REPLICATION_USER=
- REPLICATION_PASS=
- REPLICATION_SSLMODE=
volumes:
- /srv/docker/postgresql:/var/lib/postgresql
+29 -230
View File
@@ -1,241 +1,40 @@
#!/bin/bash #!/bin/bash
set -e set -e
source ${PG_APP_HOME}/functions
# set this env variable to true to enable a line in the [[ ${DEBUG} == true ]] && set -x
# pg_hba.conf file to trust samenet. this can be used to connect
# from other containers on the same host without authentication
PSQL_TRUST_LOCALNET=${PSQL_TRUST_LOCALNET:-false}
DB_NAME=${DB_NAME:-} # allow arguments to be passed to postgres
DB_USER=${DB_USER:-} if [[ ${1:0:1} = '-' ]]; then
DB_PASS=${DB_PASS:-} EXTRA_ARGS="$@"
DB_LOCALE=${DB_LOCALE:-C} set --
DB_UNACCENT=${DB_UNACCENT:false} elif [[ ${1} == postgres || ${1} == $(which postgres) ]]; then
EXTRA_ARGS="${@:2}"
# by default postgresql will start up as a standalone instance. set --
# set this environment variable to master, slave or snapshot to use replication features.
# "snapshot" will create a point in time backup of a master instance.
PSQL_MODE=${PSQL_MODE:-standalone}
REPLICATION_USER=${REPLICATION_USER:-}
REPLICATION_PASS=${REPLICATION_PASS:-}
REPLICATION_HOST=${REPLICATION_HOST:-}
REPLICATION_PORT=${REPLICATION_PORT:-5432}
# set this env variable to "require" to enable encryption and "verify-full" for verification.
PSQL_SSLMODE=${PSQL_SSLMODE:-disable}
map_postgres_uid() {
USERMAP_ORIG_UID=$(id -u ${PG_USER})
USERMAP_ORIG_GID=$(id -g ${PG_USER})
USERMAP_GID=${USERMAP_GID:-${USERMAP_UID:-$USERMAP_ORIG_GID}}
USERMAP_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
if [[ ${USERMAP_UID} != ${USERMAP_ORIG_UID} ]] || [[ ${USERMAP_GID} != ${USERMAP_ORIG_GID} ]]; then
echo "Adapting uid and gid for ${PG_USER}:${PG_USER} to $USERMAP_UID:$USERMAP_GID"
groupmod -g ${USERMAP_GID} ${PG_USER}
sed -i -e "s/:${USERMAP_ORIG_UID}:${USERMAP_GID}:/:${USERMAP_UID}:${USERMAP_GID}:/" /etc/passwd
fi
}
create_data_dir() {
mkdir -p ${PG_HOME}
chmod -R 0700 ${PG_HOME}
chown -R ${PG_USER}:${PG_USER} ${PG_HOME}
}
create_log_dir() {
mkdir -p ${PG_LOGDIR}
chmod -R 1775 ${PG_LOGDIR}
chown -R root:${PG_USER} ${PG_LOGDIR}
}
create_run_dir() {
mkdir -p ${PG_RUNDIR} ${PG_RUNDIR}/${PG_VERSION}-main.pg_stat_tmp
chmod -R 0755 ${PG_RUNDIR}
chmod g+s ${PG_RUNDIR}
chown -R ${PG_USER}:${PG_USER} ${PG_RUNDIR}
}
map_postgres_uid
create_data_dir
create_log_dir
create_run_dir
cd ${PG_HOME}
# initialize PostgreSQL data directory
if [[ ! -d ${PG_DATADIR} ]]; then
if [[ ${PSQL_MODE} == slave || ${PSQL_MODE} == snapshot ]]; then
echo "Replicating database..."
if [[ ${PSQL_MODE} == snapshot ]]; then
sudo -Hu ${PG_USER} \
PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \
-h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -w -x -v -P
elif [[ ${PSQL_MODE} == slave ]]; then
# Setup streaming replication.
sudo -Hu ${PG_USER} \
PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \
-h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X stream -w -v -P
echo "Setting up hot standby configuration..."
cat >> ${PG_CONFDIR}/postgresql.conf <<EOF
hot_standby = on
EOF
sudo -Hu ${PG_USER} touch ${PG_DATADIR}/recovery.conf
cat >> ${PG_DATADIR}/recovery.conf <<EOF
standby_mode = 'on'
primary_conninfo = 'host=${REPLICATION_HOST} port=${REPLICATION_PORT} user=${REPLICATION_USER} password=${REPLICATION_PASS} sslmode=${PSQL_SSLMODE}'
trigger_file = '/tmp/postgresql.trigger'
EOF
fi
else
# check if we need to perform data migration
PG_OLD_VERSION=$(find ${PG_HOME}/[0-9].[0-9]/main -maxdepth 1 -name PG_VERSION 2>/dev/null | sort -r | head -n1 | cut -d'/' -f5)
if [[ $DB_LOCALE != C ]]; then
echo "Generating required locale \"${DB_LOCALE}\"..."
locale-gen ${DB_LOCALE} >/dev/null
fi
echo "Initializing database..."
sudo -Hu ${PG_USER} ${PG_BINDIR}/initdb --pgdata=${PG_DATADIR} \
--username=${PG_USER} --encoding=unicode --locale=${DB_LOCALE} --auth=trust >/dev/null
fi
fi fi
if [[ -n ${PG_OLD_VERSION} ]]; then # default behaviour is to launch postgres
echo "Migrating postgresql ${PG_OLD_VERSION} data..." if [[ -z ${1} ]]; then
PG_OLD_CONFDIR="${PG_HOME}/${PG_OLD_VERSION}/main" map_uidgid
PG_OLD_BINDIR="/usr/lib/postgresql/${PG_OLD_VERSION}/bin"
PG_OLD_DATADIR="${PG_HOME}/${PG_OLD_VERSION}/main"
# backup ${PG_OLD_DATADIR} to avoid data loss create_datadir
PG_BKP_SUFFIX=$(date +%Y%m%d%H%M%S) create_certdir
echo "Backing up ${PG_OLD_DATADIR} to ${PG_OLD_DATADIR}.${PG_BKP_SUFFIX}..." create_logdir
cp -a ${PG_OLD_DATADIR} ${PG_OLD_DATADIR}.${PG_BKP_SUFFIX} create_rundir
echo "Installing postgresql-${PG_OLD_VERSION}..." initialize_database
apt-get update configure_recovery
DEBIAN_FRONTEND=noninteractive apt-get install postgresql-${PG_OLD_VERSION} postgresql-client-${PG_OLD_VERSION} configure_ssl
rm -rf /var/lib/apt/lists/* trust_localnet
# migrate ${PG_OLD_VERSION} data create_user
echo "Migration in progress. This could take a while, please be patient..." create_database
sudo -Hu ${PG_USER} ${PG_BINDIR}/pg_upgrade \ create_replication_user
-b ${PG_OLD_BINDIR} -B ${PG_BINDIR} \
-d ${PG_OLD_DATADIR} -D ${PG_DATADIR} \ echo "Starting PostgreSQL ${PG_VERSION}..."
-o "-c config_file=${PG_OLD_CONFDIR}/postgresql.conf --hba_file=${PG_OLD_CONFDIR}/pg_hba.conf --ident_file=${PG_OLD_CONFDIR}/pg_ident.conf" \ exec start-stop-daemon --start --chuid ${PG_USER}:${PG_USER} \
-O "-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf" >/dev/null --exec ${PG_BINDIR}/postgres -- -D ${PG_DATADIR} ${EXTRA_ARGS}
else
exec "$@"
fi fi
if [[ ${PSQL_SSLMODE} == disable ]]; then
sed 's/ssl = true/#ssl = true/' -i ${PG_CONFDIR}/postgresql.conf
fi
# Change DSM from `posix' to `sysv' if we are inside an lx-brand container
if [[ $(uname -v) == "BrandZ virtual linux" ]]; then
sed 's/\(dynamic_shared_memory_type = \)posix/\1sysv/' \
-i ${PG_CONFDIR}/postgresql.conf
fi
# listen on all interfaces
cat >> ${PG_CONFDIR}/postgresql.conf <<EOF
listen_addresses = '*'
EOF
if [[ ${PSQL_TRUST_LOCALNET} == true ]]; then
echo "Enabling trust samenet in pg_hba.conf..."
cat >> ${PG_CONFDIR}/pg_hba.conf <<EOF
host all all samenet trust
EOF
fi
# allow remote connections to postgresql database
cat >> ${PG_CONFDIR}/pg_hba.conf <<EOF
host all all 0.0.0.0/0 md5
EOF
# allow replication connections to the database
if [[ -n ${REPLICATION_USER} ]]; then
if [[ ${PSQL_SSLMODE} == disable ]]; then
cat >> ${PG_CONFDIR}/pg_hba.conf <<EOF
host replication $REPLICATION_USER 0.0.0.0/0 md5
EOF
else
cat >> ${PG_CONFDIR}/pg_hba.conf <<EOF
hostssl replication $REPLICATION_USER 0.0.0.0/0 md5
EOF
fi
fi
if [[ ${PSQL_MODE} == master ]]; then
if [[ -n ${REPLICATION_USER} ]]; then
echo "Supporting hot standby..."
cat >> ${PG_CONFDIR}/postgresql.conf <<EOF
wal_level = hot_standby
max_wal_senders = 3
checkpoint_segments = 8
wal_keep_segments = 8
EOF
fi
fi
# Hot standby (slave and snapshot) servers can ignore the following code.
if [[ ${PSQL_MODE} == standalone || ${PSQL_MODE} == master ]]; then
if [[ -n ${REPLICATION_USER} ]]; then
if [[ -z ${REPLICATION_PASS} ]]; then
echo ""
echo "WARNING: "
echo " Please specify a password for replication user \"${REPLICATION_USER}\". Skipping user creation..."
echo ""
DB_USER=
else
echo "Creating user \"${REPLICATION_USER}\"..."
echo "CREATE ROLE \"${REPLICATION_USER}\" WITH REPLICATION LOGIN ENCRYPTED PASSWORD '${REPLICATION_PASS}';" |
sudo -Hu ${PG_USER} ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf >/dev/null
fi
fi
if [[ -n ${DB_USER} ]]; then
if [[ -z ${DB_PASS} ]]; then
echo ""
echo "WARNING: "
echo " Please specify a password for \"${DB_USER}\". Skipping user creation..."
echo ""
DB_USER=
else
echo "Creating user \"${DB_USER}\"..."
echo "CREATE ROLE \"${DB_USER}\" with LOGIN CREATEDB PASSWORD '${DB_PASS}';" |
sudo -Hu ${PG_USER} ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf >/dev/null
fi
fi
if [[ -n ${DB_NAME} ]]; then
for db in $(awk -F',' '{for (i = 1 ; i <= NF ; i++) print $i}' <<< "${DB_NAME}"); do
echo "Creating database \"${db}\"..."
echo "CREATE DATABASE \"${db}\";" | \
sudo -Hu ${PG_USER} ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf >/dev/null
if [[ ${DB_UNACCENT} == true ]]; then
echo "Installing unaccent extension..."
echo "CREATE EXTENSION IF NOT EXISTS unaccent;" | \
sudo -Hu ${PG_USER} ${PG_BINDIR}/postgres --single ${db} -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf >/dev/null
fi
if [[ -n ${DB_USER} ]]; then
echo "Granting access to database \"${db}\" for user \"${DB_USER}\"..."
echo "GRANT ALL PRIVILEGES ON DATABASE \"${db}\" to \"${DB_USER}\";" |
sudo -Hu ${PG_USER} ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf >/dev/null
fi
done
fi
fi
echo "Starting PostgreSQL server..."
exec start-stop-daemon --start --chuid ${PG_USER}:${PG_USER} --exec ${PG_BINDIR}/postgres -- -D ${PG_DATADIR} \
-c config_file=${PG_CONFDIR}/postgresql.conf --hba_file=${PG_CONFDIR}/pg_hba.conf --ident_file=${PG_CONFDIR}/pg_ident.conf
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
PG_SSL=${PG_SSL:-}
PG_TRUST_LOCALNET=${PG_TRUST_LOCALNET:-$PSQL_TRUST_LOCALNET} # backward compatibility
PG_TRUST_LOCALNET=${PG_TRUST_LOCALNET:-false}
REPLICATION_MODE=${REPLICATION_MODE:-$PSQL_MODE} # backward compatibility
REPLICATION_MODE=${REPLICATION_MODE:-}
REPLICATION_USER=${REPLICATION_USER:-}
REPLICATION_PASS=${REPLICATION_PASS:-}
REPLICATION_HOST=${REPLICATION_HOST:-}
REPLICATION_PORT=${REPLICATION_PORT:-5432}
REPLICATION_SSLMODE=${REPLICATION_SSLMODE:-prefer}
DB_NAME=${DB_NAME:-}
DB_USER=${DB_USER:-}
DB_PASS=${DB_PASS:-}
DB_UNACCENT=${DB_UNACCENT:-false}
+348
View File
@@ -0,0 +1,348 @@
#!/bin/bash
set -e
source ${PG_APP_HOME}/env-defaults
PG_CONF=${PG_DATADIR}/postgresql.conf
PG_HBA_CONF=${PG_DATADIR}/pg_hba.conf
PG_IDENT_CONF=${PG_DATADIR}/pg_ident.conf
PG_RECOVERY_CONF=${PG_DATADIR}/recovery.conf
## Execute command as PG_USER
exec_as_postgres() {
sudo -HEu ${PG_USER} "$@"
}
map_uidgid() {
USERMAP_ORIG_UID=$(id -u ${PG_USER})
USERMAP_ORIG_GID=$(id -g ${PG_USER})
USERMAP_GID=${USERMAP_GID:-${USERMAP_UID:-$USERMAP_ORIG_GID}}
USERMAP_UID=${USERMAP_UID:-$USERMAP_ORIG_UID}
if [[ ${USERMAP_UID} != ${USERMAP_ORIG_UID} ]] || [[ ${USERMAP_GID} != ${USERMAP_ORIG_GID} ]]; then
echo "Adapting uid and gid for ${PG_USER}:${PG_USER} to $USERMAP_UID:$USERMAP_GID"
groupmod -g ${USERMAP_GID} ${PG_USER}
sed -i -e "s|:${USERMAP_ORIG_UID}:${USERMAP_GID}:|:${USERMAP_UID}:${USERMAP_GID}:|" /etc/passwd
fi
}
create_datadir() {
echo "Initializing datadir..."
mkdir -p ${PG_HOME}
if [[ -d ${PG_DATADIR} ]]; then
find ${PG_DATADIR} -type f -exec chmod 0600 {} \;
find ${PG_DATADIR} -type d -exec chmod 0700 {} \;
fi
chown -R ${PG_USER}:${PG_USER} ${PG_HOME}
}
create_certdir() {
echo "Initializing certdir..."
mkdir -p ${PG_CERTDIR}
[[ -f ${PG_CERTDIR}/server.crt ]] && chmod 0644 ${PG_CERTDIR}/server.crt
[[ -f ${PG_CERTDIR}/server.key ]] && chmod 0640 ${PG_CERTDIR}/server.key
chmod 0755 ${PG_CERTDIR}
chown -R root:${PG_USER} ${PG_CERTDIR}
}
create_logdir() {
echo "Initializing logdir..."
mkdir -p ${PG_LOGDIR}
chmod -R 1775 ${PG_LOGDIR}
chown -R root:${PG_USER} ${PG_LOGDIR}
}
create_rundir() {
echo "Initializing rundir..."
mkdir -p ${PG_RUNDIR} ${PG_RUNDIR}/${PG_VERSION}-main.pg_stat_tmp
chmod -R 0755 ${PG_RUNDIR}
chmod g+s ${PG_RUNDIR}
chown -R ${PG_USER}:${PG_USER} ${PG_RUNDIR}
}
set_postgresql_param() {
local key=${1}
local value=${2}
if [[ -n ${value} ]]; then
local current=$(exec_as_postgres sed -n -e "s/^\("${key}" = '\)\([^ ']*\)\(.*\)$/\2/p" ${PG_CONF})
if [[ "${current}" != "${value}" ]]; then
echo "‣ Setting postgresql.conf parameter: ${key} = '${value}'"
value="$(echo "${value}" | sed 's|[&]|\\&|g')"
exec_as_postgres sed -i "s|^[#]*[ ]*${key} = .*|${key} = '${value}'|" ${PG_CONF}
fi
fi
}
set_recovery_param() {
local key=${1}
local value=${2}
local hide=${3}
if [[ -n ${value} ]]; then
local current=$(exec_as_postgres sed -n -e "s/^\(.*\)\("${key}"=\)\([^ ']*\)\(.*\)$/\3/p" ${PG_RECOVERY_CONF})
if [[ "${current}" != "${value}" ]]; then
case ${hide} in
true) echo "‣ Setting primary_conninfo parameter: ${key}" ;;
*) echo "‣ Setting primary_conninfo parameter: ${key} = '${value}'" ;;
esac
exec_as_postgres sed -i "s|${key}=[^ ']*|${key}=${value}|" ${PG_RECOVERY_CONF}
fi
fi
}
set_hba_param() {
local value=${1}
if ! grep -q "$(sed "s| | \\\+|g" <<< ${value})" ${PG_HBA_CONF}; then
echo "${value}" >> ${PG_HBA_CONF}
fi
}
configure_ssl() {
## NOT SURE IF THIS IS A GOOD ALTERNATIVE TO ENABLE SSL SUPPORT BY DEFAULT ##
## BECAUSE USERS WHO PULL A PREBUILT IMAGE WILL HAVE THE SAME CERTIFICATES ##
# if [[ ! -f ${PG_CERTDIR}/server.crt && ! -f ${PG_CERTDIR}/server.key ]]; then
# if [[ -f /etc/ssl/certs/ssl-cert-snakeoil.pem && -f /etc/ssl/private/ssl-cert-snakeoil.key ]]; then
# ln -sf /etc/ssl/certs/ssl-cert-snakeoil.pem ${PG_CERTDIR}/server.crt
# ln -sf /etc/ssl/private/ssl-cert-snakeoil.key ${PG_CERTDIR}/server.key
# fi
# fi
if [[ -f ${PG_CERTDIR}/server.crt && -f ${PG_CERTDIR}/server.key ]]; then
PG_SSL=${PG_SSL:-on}
set_postgresql_param "ssl_cert_file" "${PG_CERTDIR}/server.crt"
set_postgresql_param "ssl_key_file" "${PG_CERTDIR}/server.key"
fi
PG_SSL=${PG_SSL:-off}
set_postgresql_param "ssl" "${PG_SSL}"
}
configure_hot_standby() {
case ${REPLICATION_MODE} in
slave|snapshot|backup) ;;
*)
echo "Configuring hot standby..."
set_postgresql_param "wal_level" "hot_standby"
set_postgresql_param "max_wal_senders" "16"
set_postgresql_param "checkpoint_segments" "8"
set_postgresql_param "wal_keep_segments" "32"
set_postgresql_param "hot_standby" "on"
;;
esac
}
initialize_database() {
if [[ ! -f ${PG_DATADIR}/PG_VERSION ]]; then
case ${REPLICATION_MODE} in
slave|snapshot|backup)
if [[ -z $REPLICATION_HOST ]]; then
echo "ERROR! Cannot continue without the REPLICATION_HOST. Exiting..."
exit 1
fi
if [[ -z $REPLICATION_USER ]]; then
echo "ERROR! Cannot continue without the REPLICATION_USER. Exiting..."
exit 1
fi
if [[ -z $REPLICATION_PASS ]]; then
echo "ERROR! Cannot continue without the REPLICATION_PASS. Exiting..."
exit 1
fi
echo -n "Waiting for $REPLICATION_HOST to accept connections (60s timeout)"
timeout=60
while ! ${PG_BINDIR}/pg_isready -h $REPLICATION_HOST -p $REPLICATION_PORT -t 1 >/dev/null 2>&1
do
timeout=$(expr $timeout - 1)
if [[ $timeout -eq 0 ]]; then
echo "Timeout! Exiting..."
exit 1
fi
echo -n "."
sleep 1
done
echo
case ${REPLICATION_MODE} in
slave)
echo "Replicating initial data from $REPLICATION_HOST..."
exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \
-h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X stream -w >/dev/null
;;
snapshot)
echo "Generating a snapshot data on $REPLICATION_HOST..."
exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \
-h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null
;;
backup)
echo "Backing up data on $REPLICATION_HOST..."
exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \
-h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null
exit 0
;;
esac
;;
*)
echo "Initializing database..."
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)
if [[ -n ${PG_OLD_VERSION} ]]; then
echo "‣ Migrating PostgreSQL ${PG_OLD_VERSION} data to ${PG_VERSION}..."
# protect the existing data from being altered by apt-get
mv ${PG_HOME}/${PG_OLD_VERSION} ${PG_HOME}/${PG_OLD_VERSION}.migrating
echo "‣ Installing PostgreSQL ${PG_OLD_VERSION}..."
if ! ( apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y postgresql-${PG_OLD_VERSION} postgresql-client-${PG_OLD_VERSION} ) >/dev/null; then
echo "ERROR! Failed to install PostgreSQL ${PG_OLD_VERSION}. Exiting..."
# first move the old data back
rm -rf ${PG_HOME}/${PG_OLD_VERSION}
mv ${PG_HOME}/${PG_OLD_VERSION}.migrating ${PG_HOME}/${PG_OLD_VERSION}
exit 1
fi
rm -rf /var/lib/apt/lists/*
# we're ready to migrate, move back the old data and remove the trap
rm -rf ${PG_HOME}/${PG_OLD_VERSION}
mv ${PG_HOME}/${PG_OLD_VERSION}.migrating ${PG_HOME}/${PG_OLD_VERSION}
fi
if [[ -n $PG_PASSWORD ]]; then
echo "${PG_PASSWORD}" > /tmp/pwfile
fi
exec_as_postgres ${PG_BINDIR}/initdb --pgdata=${PG_DATADIR} \
--username=${PG_USER} --encoding=unicode --auth=trust ${PG_PASSWORD:+--pwfile=/tmp/pwfile} >/dev/null
if [[ -n ${PG_OLD_VERSION} ]]; then
PG_OLD_BINDIR=/usr/lib/postgresql/${PG_OLD_VERSION}/bin
PG_OLD_DATADIR=${PG_HOME}/${PG_OLD_VERSION}/main
PG_OLD_CONF=${PG_OLD_DATADIR}/postgresql.conf
PG_OLD_HBA_CONF=${PG_OLD_DATADIR}/pg_hba.conf
PG_OLD_IDENT_CONF=${PG_OLD_DATADIR}/pg_ident.conf
echo -n "‣ Migration in progress. Please be patient..."
exec_as_postgres ${PG_BINDIR}/pg_upgrade \
-b ${PG_OLD_BINDIR} -B ${PG_BINDIR} \
-d ${PG_OLD_DATADIR} -D ${PG_DATADIR} \
-o "-c config_file=${PG_OLD_CONF} --hba_file=${PG_OLD_HBA_CONF} --ident_file=${PG_OLD_IDENT_CONF}" \
-O "-c config_file=${PG_CONF} --hba_file=${PG_HBA_CONF} --ident_file=${PG_IDENT_CONF}" >/dev/null
echo
fi
;;
esac
configure_hot_standby
# Change DSM from `posix' to `sysv' if we are inside an lx-brand container
if [[ $(uname -v) == "BrandZ virtual linux" ]]; then
set_postgresql_param "dynamic_shared_memory_type" "sysv"
fi
fi
# configure path to data_directory
set_postgresql_param "data_directory" "${PG_DATADIR}"
# configure logging
set_postgresql_param "log_directory" "${PG_LOGDIR}"
set_postgresql_param "log_filename" "postgresql-${PG_VERSION}-main.log"
# listen on all interfaces
set_postgresql_param "listen_addresses" "*"
# allow remote connections to postgresql database
set_hba_param "host all all 0.0.0.0/0 md5"
}
trust_localnet() {
if [[ ${PG_TRUST_LOCALNET} == true ]]; then
echo "Trusting connections from the local network..."
set_hba_param "host all all samenet trust"
fi
}
configure_recovery() {
if [[ ${REPLICATION_MODE} == slave ]]; then
echo "Configuring recovery..."
if [[ ! -f ${PG_RECOVERY_CONF} ]]; then
# initialize recovery.conf on the firstrun (slave only)
exec_as_postgres touch ${PG_RECOVERY_CONF}
( echo "standby_mode = 'on'";
echo "primary_conninfo = 'host=${REPLICATION_HOST} port=${REPLICATION_PORT} user=${REPLICATION_USER} password=${REPLICATION_PASS} sslmode=${REPLICATION_SSLMODE}'";
) > ${PG_RECOVERY_CONF}
else
set_recovery_param "host" "${REPLICATION_HOST}"
set_recovery_param "port" "${REPLICATION_PORT}"
set_recovery_param "user" "${REPLICATION_USER}"
set_recovery_param "password" "${REPLICATION_PASS}" "true"
set_recovery_param "sslmode" "${REPLICATION_SSLMODE}"
fi
else
# recovery.conf can only exist on a slave node, its existence otherwise causes problems
rm -rf ${PG_RECOVERY_CONF}
fi
}
create_user() {
if [[ -n ${DB_USER} ]]; then
case $REPLICATION_MODE in
slave|snapshot|backup)
echo "INFO! Database user cannot be created on a $REPLICATION_MODE node. Skipping..."
;;
*)
if [[ -z ${DB_PASS} ]]; then
echo "ERROR! Please specify a password for DB_USER in DB_PASS. Exiting..."
exit 1
fi
echo "Creating database user: ${DB_USER}"
echo "CREATE ROLE \"${DB_USER}\" with LOGIN CREATEDB PASSWORD '${DB_PASS}';" | \
exec_as_postgres ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} >/dev/null 2>&1
;;
esac
fi
}
create_database() {
if [[ -n ${DB_NAME} ]]; then
case $REPLICATION_MODE in
slave|snapshot|backup)
echo "INFO! Database cannot be created on a $REPLICATION_MODE node. Skipping..."
;;
*)
echo -n "Creating database(s): "
for database in $(awk -F',' '{for (i = 1 ; i <= NF ; i++) print $i}' <<< "${DB_NAME}"); do
echo -n "${database} "
echo "CREATE DATABASE \"${database}\";" | \
exec_as_postgres ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} >/dev/null 2>&1
if [[ ${DB_UNACCENT} == true ]]; then
echo "CREATE EXTENSION IF NOT EXISTS unaccent;" | \
exec_as_postgres ${PG_BINDIR}/postgres --single ${database} -D ${PG_DATADIR} >/dev/null 2>&1
fi
if [[ -n ${DB_USER} ]]; then
echo "GRANT ALL PRIVILEGES ON DATABASE \"${database}\" to \"${DB_USER}\";" | \
exec_as_postgres ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} >/dev/null 2>&1
fi
done
echo
;;
esac
fi
}
create_replication_user() {
if [[ -n ${REPLICATION_USER} ]]; then
case $REPLICATION_MODE in
slave|snapshot|backup) ;; # replication user can only be created on the master
*)
if [[ -z ${REPLICATION_PASS} ]]; then
echo "ERROR! Please specify a password for REPLICATION_USER in REPLICATION_PASS. Exiting..."
exit 1
fi
echo "Creating replication user: ${REPLICATION_USER}"
echo "CREATE ROLE \"${REPLICATION_USER}\" WITH REPLICATION LOGIN ENCRYPTED PASSWORD '${REPLICATION_PASS}';" | \
exec_as_postgres ${PG_BINDIR}/postgres --single -D ${PG_DATADIR} >/dev/null 2>&1
set_hba_param "host replication ${REPLICATION_USER} 0.0.0.0/0 md5"
;;
esac
fi
}