├── .gitattributes ├── .gitignore ├── Dockerfile ├── README.md ├── backup ├── docker-compose.yml ├── entrypoint.sh ├── fix-acl.sh └── setup-wale.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | text eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM postgres:9.4.9 2 | 3 | MAINTAINER Luke Smith 4 | 5 | RUN apt-get update && apt-get install -y python3-pip python3.4 lzop pv daemontools && \ 6 | pip3 install wal-e[aws] && \ 7 | apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 8 | 9 | # Change the entrypoint so wale will always be setup, even if the data dir already exists 10 | COPY entrypoint.sh / 11 | ENTRYPOINT ["/entrypoint.sh"] 12 | 13 | COPY setup-wale.sh fix-acl.sh /docker-entrypoint-initdb.d/ 14 | COPY backup / 15 | 16 | CMD ["postgres"] 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Postgres docker container with wale 2 | 3 | Based on https://github.com/docker-library/postgres with [WAL-E](https://github.com/wal-e/wal-e) installed. 4 | 5 | Environment variables to pass to the container for WAL-E, all of these must be present or WAL-E is not configured. 6 | 7 | ``` 8 | WALE_AWS_ACCESS_KEY_ID` 9 | WALE_AWS_SECRET_ACCESS_KEY` 10 | WALE_S3_PREFIX="s3:///" 11 | WALE_AWS_REGION=eu-west-1 12 | ``` 13 | 14 | ## Running 15 | 16 | The master 17 | 18 | ``` 19 | docker run -it \ 20 | --env "WALE_AWS_ACCESS_KEY_ID=****" \ 21 | --env "WALE_AWS_SECRET_ACCESS_KEY=****" \ 22 | --env "WALE_AWS_REGION=eu-west-1" \ 23 | --env "WALE_S3_PREFIX=s3://my-bucket" \ 24 | --env "POSTGRES_AUTHORITY=master" \ 25 | -v ./data/master:/var/lib/postgresql/data \ 26 | docker-postgres-wale 27 | ``` 28 | 29 | The slave will run in `standby_mode`. 30 | 31 | ``` 32 | docker run -it \ 33 | --env "WALE_AWS_ACCESS_KEY_ID=****" \ 34 | --env "WALE_AWS_SECRET_ACCESS_KEY=****" \ 35 | --env "WALE_AWS_REGION=eu-west-1" \ 36 | --env "WALE_S3_PREFIX=s3://my-bucket" \ 37 | --env "POSTGRES_AUTHORITY=slave" \ 38 | -v ./data/slave:/var/lib/postgresql/data \ 39 | docker-postgres-wale 40 | ``` 41 | 42 | When bringing online `rm ./data/recovery.conf` and start the container with `POSTGRES_AUTHORITY=master`. 43 | -------------------------------------------------------------------------------- /backup: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | su - postgres -c "/usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-push /var/lib/postgresql/data" 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | master: 4 | build: . 5 | environment: 6 | - WALE_AWS_ACCESS_KEY_ID= 7 | - WALE_AWS_SECRET_ACCESS_KEY= 8 | - WALE_AWS_REGION=eu-west-1 9 | - WALE_S3_PREFIX=s3://docker-postgres-wale 10 | volumes: 11 | - ./data/master:/var/lib/postgresql/data 12 | slave: 13 | build: . 14 | environment: 15 | - WALE_AWS_ACCESS_KEY_ID= 16 | - WALE_AWS_SECRET_ACCESS_KEY= 17 | - WALE_AWS_REGION=eu-west-1 18 | - WALE_S3_PREFIX=s3://docker-postgres-wale 19 | - POSTGRES_AUTHORITY=slave 20 | volumes: 21 | - ./data/slave:/var/lib/postgresql/data 22 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | if [ "$1" = 'postgres' ]; then 6 | 7 | if [ ! -s "$PGDATA/PG_VERSION" ]; then 8 | echo $PGDATA/PG_VERSION does not exist 9 | else 10 | echo $PGDATA/PG_VERSION exist, ensuring wal-e is set to run 11 | . ./docker-entrypoint-initdb.d/setup-wale.sh 12 | fi 13 | 14 | . ./docker-entrypoint.sh $1 15 | fi 16 | 17 | exec "$@" 18 | -------------------------------------------------------------------------------- /fix-acl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat > /var/lib/postgresql/data/pg_hba.conf < /etc/wal-e.d/env/AWS_SECRET_ACCESS_KEY 8 | echo "$WALE_AWS_ACCESS_KEY_ID" > /etc/wal-e.d/env/AWS_ACCESS_KEY_ID 9 | echo "$WALE_S3_PREFIX" > /etc/wal-e.d/env/WALE_S3_PREFIX 10 | echo "$WALE_AWS_REGION" > /etc/wal-e.d/env/AWS_REGION 11 | chown -R root:postgres /etc/wal-e.d 12 | 13 | if [ "$POSTGRES_AUTHORITY" = "slave" ] 14 | then 15 | echo "Authority: Slave - Fetching latest backups"; 16 | 17 | if grep -q "/etc/wal-e.d/env" "/var/lib/postgresql/data/recovery.conf"; then 18 | echo "wal-e already configured in /var/lib/postgresql/data/recovery.conf" 19 | else 20 | gosu postgres pg_ctl -D "$PGDATA" -w stop 21 | # $PGDATA cannot be removed so use temporary dir 22 | # If you don't stop the server first, you'll waste 5hrs debugging why your WALs aren't pulled 23 | su - postgres -c "envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-fetch /tmp/pg-data LATEST" 24 | su - postgres -c "cp -rf /tmp/pg-data/* $PGDATA" 25 | su - postgres -c "rm -rf /tmp/pg-data" 26 | 27 | # Create recovery.conf 28 | echo "standby_mode = 'yes'" >> $PGDATA/recovery.conf 29 | echo "restore_command = 'envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-fetch "%f" "%p"'" >> $PGDATA/recovery.conf 30 | echo "trigger_file = '$PGDATA/trigger'" >> $PGDATA/recovery.conf 31 | 32 | chown -R postgres "$PGDATA" 33 | 34 | # Starting server again to satisfy init script 35 | gosu postgres pg_ctl -D "$PGDATA" -o "-c listen_addresses=''" -w start 36 | fi 37 | else 38 | echo "Authority: Master - Scheduling WAL backups"; 39 | 40 | if grep -q "/etc/wal-e.d/env" "/var/lib/postgresql/data/postgresql.conf"; then 41 | echo "wal-e already configured in /var/lib/postgresql/data/postgresql.conf" 42 | else 43 | echo "wal_level = archive" >> /var/lib/postgresql/data/postgresql.conf 44 | echo "archive_mode = on" >> /var/lib/postgresql/data/postgresql.conf 45 | echo "archive_command = 'envdir /etc/wal-e.d/env /usr/local/bin/wal-e wal-push %p'" >> /var/lib/postgresql/data/postgresql.conf 46 | echo "archive_timeout = 60" >> /var/lib/postgresql/data/postgresql.conf 47 | fi 48 | 49 | su - postgres -c "crontab -l | { cat; echo \"0 3 * * * /usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e backup-push /var/lib/postgresql/data\"; } | crontab -" 50 | su - postgres -c "crontab -l | { cat; echo \"0 4 * * * /usr/bin/envdir /etc/wal-e.d/env /usr/local/bin/wal-e delete --confirm retain 7\"; } | crontab -" 51 | fi 52 | --------------------------------------------------------------------------------