Skip to content

Commit 26e615a

Browse files
authored
feat: support mounting a persistent data directory (#11)
* feat: support mounting a persistent data directory * fix: use host uid/gid
1 parent a5a3181 commit 26e615a

File tree

9 files changed

+92
-31
lines changed

9 files changed

+92
-31
lines changed

.env.example.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,10 @@ export POSTGRES_EXTENSIONS="ltree postgis"
99

1010
export EPHEMERAL_POSTGRES_AUTO_UPDATE="1"
1111
export EPHEMERAL_POSTGRES_FORCE_BUILD="0"
12+
13+
# Set to empty string to use a tmpfs / ram disk instead
14+
export EPHEMERAL_POSTGRES_DATA_DIR="./data"
15+
16+
# Defaults to uid:gid of current user, set to empty to use upstream default user
17+
EPHEMERAL_POSTGRES_LINUX_USER=$(id -u)
18+
export EPHEMERAL_POSTGRES_LINUX_USER

.github/workflows/cd.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ jobs:
4141

4242
- name: Test ephemeral-postgres ${{ matrix.postgres-version }}
4343
run: ./bin/test-image.sh "${{ matrix.postgres-version }}"
44+
timeout-minutes: 2
4445

4546
- name: Push ephemeral-postgres ${{ matrix.postgres-version }}
4647
if: github.ref_name == 'main'

README.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33

44
A bash script that starts an ephemeral postgres locally in docker for **development purposes**.
55

6-
**Data is destroyed** between runs, on Linux the data is stored on a `tmpfs` / ramdisk
6+
By default, **Data is destroyed** between runs, and on Linux the data is stored on a `tmpfs` (ramdisk)
77
for faster startup.
88

9+
For persistent data, configure `EPHEMERAL_POSTGRES_DATA_DIR` to be a path you wish to
10+
store the data on your host machine.
11+
912
The container loads a `ClientAuthentication` hook `ensure_role_and_database_exists` that
1013
automatically creates roles & databases that don't exist when connections are made.
1114

@@ -23,6 +26,12 @@ Prebuild images are pulled from dockerhub automatically for recent postgres vers
2326
- Clone the repo
2427
- (Optionally) add the repo to your `$PATH`
2528

29+
```shell
30+
git clone git@github.com:mnahkies/ephemeral-postgres.git ~/.local/share/ephemeral-postgres
31+
ln -s ~/.local/share/ephemeral-postgres/start-ephemeral-postgres.sh ~/.local/bin/start-postgres
32+
ln -s ~/.local/share/ephemeral-postgres/connect-ephemeral-postgres.sh ~/.local/bin/connect-postgres
33+
```
34+
2635
## Usage
2736

2837
Start the `postgres` server:
@@ -40,8 +49,11 @@ start-ephemeral-postgres.sh
4049
- `POSTGRES_EXTENSIONS=` - could be `postgis ltree` / etc
4150
- `EPHEMERAL_POSTGRES_FORCE_BUILD=0` - force building the docker image locally instead of pulling a prebuilt image
4251
- `EPHEMERAL_POSTGRES_AUTO_UPDATE=1` - whether to automatically check for updates to `ephemeral-postgres`
52+
- `EPHEMERAL_POSTGRES_DATA_DIR=` - when empty, use a tmpfs / ram disk, otherwise a path to bind mount to the postgres data directory
53+
- `EPHEMERAL_POSTGRES_LINUX_USER=$(id -u)` - linux `uid` / `gid` to run postgres as, defaulting to current users
54+
- `EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS` - used internally, but you can pass arbitrary flags for `docker run` here, eg: `--network=foo`
4355

44-
You can also create a `.env.sh` file and this will be automatically loaded by `start-postgres.sh
56+
You can also create a `.env.sh` file and this will be automatically loaded by `start-ephemeral-postgres.sh`
4557

4658
Connect using `psql`:
4759

bin/build-image.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
set -xeo pipefail
44

5-
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6-
5+
__dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
76
pushd "$__dir"
87
trap popd EXIT
98

bin/push-image.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
set -xeo pipefail
44

5-
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6-
5+
__dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
76
pushd "$__dir"
87
trap popd EXIT
98

bin/test-image.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
set -xeo pipefail
44

5-
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6-
5+
__dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
76
pushd "$__dir"
87
trap popd EXIT
98

connect-ephemeral-postgres.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@
22

33
set -eo pipefail
44

5+
__dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
6+
pushd "$__dir"
7+
trap popd EXIT
8+
9+
source ./ephemeral-postgres-config.sh
10+
511
docker exec -it postgres psql -U postgres

ephemeral-postgres-config.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#!/usr/bin/env bash
2+
3+
set -eo pipefail
4+
5+
: "${POSTGRES_VERSION:=17}"
6+
: "${POSTGRES_USER:=postgres}"
7+
: "${POSTGRES_PASSWORD:=postgres}"
8+
: "${POSTGRES_HOST_AUTH_METHOD:=trust}"
9+
: "${POSTGRES_ROLE_ATTRIBUTES:=LOGIN CREATEDB}"
10+
: "${POSTGRES_EXTENSIONS:=}"
11+
12+
: "${EPHEMERAL_POSTGRES_AUTO_UPDATE:=1}"
13+
: "${EPHEMERAL_POSTGRES_FORCE_BUILD:=0}"
14+
: "${EPHEMERAL_POSTGRES_DATA_DIR:=}"
15+
: "${EPHEMERAL_POSTGRES_LINUX_USER:=$(id -u)}"
16+
: "${EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS:=}"
17+
18+
if [ -f .env.sh ]; then
19+
echo "loading config from '.env.sh'"
20+
source .env.sh
21+
fi
22+
23+
export POSTGRES_VERSION
24+
export POSTGRES_USER
25+
export POSTGRES_PASSWORD
26+
export POSTGRES_HOST_AUTH_METHOD
27+
export POSTGRES_ROLE_ATTRIBUTES
28+
export POSTGRES_EXTENSIONS
29+
30+
export EPHEMERAL_POSTGRES_AUTO_UPDATE
31+
export EPHEMERAL_POSTGRES_FORCE_BUILD
32+
export EPHEMERAL_POSTGRES_DATA_DIR
33+
export EPHEMERAL_POSTGRES_LINUX_USER
34+
export EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS

start-ephemeral-postgres.sh

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,11 @@
22

33
set -eo pipefail
44

5-
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6-
7-
pushd $__dir
5+
__dir="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
6+
pushd "$__dir"
87
trap popd EXIT
98

10-
: "${POSTGRES_VERSION:=17}"
11-
: "${POSTGRES_USER:=postgres}"
12-
: "${POSTGRES_PASSWORD:=postgres}"
13-
: "${POSTGRES_HOST_AUTH_METHOD:=trust}"
14-
: "${POSTGRES_ROLE_ATTRIBUTES:=LOGIN CREATEDB}"
15-
: "${POSTGRES_EXTENSIONS:=}"
16-
17-
: "${EPHEMERAL_POSTGRES_AUTO_UPDATE:=1}"
18-
: "${EPHEMERAL_POSTGRES_FORCE_BUILD:=0}"
19-
20-
if [ -f .env.sh ]; then
21-
echo "loading config from '.env.sh'"
22-
source .env.sh
23-
fi
9+
source ./ephemeral-postgres-config.sh
2410

2511
if [[ "${EPHEMERAL_POSTGRES_AUTO_UPDATE}" -eq 1 ]]; then
2612
if git rev-parse --is-inside-work-tree > /dev/null 2>&1; then
@@ -37,8 +23,8 @@ fi
3723

3824
IMAGE=mnahkies/ephemeral-postgres:$POSTGRES_VERSION
3925

40-
docker stop postgres || echo 'already stopped'
41-
docker rm postgres || echo 'already removed'
26+
docker stop postgres > /dev/null 2>&1 || echo 'already stopped'
27+
docker rm postgres > /dev/null 2>&1 || echo 'already removed'
4228

4329
if [[ "${EPHEMERAL_POSTGRES_FORCE_BUILD}" -ne 0 ]]; then
4430
echo "Force build enabled. Skipping pull and building Docker image with POSTGRES_VERSION=$POSTGRES_VERSION"
@@ -51,13 +37,31 @@ else
5137
fi
5238
fi
5339

54-
if [[ "$OSTYPE" =~ ^linux ]]; then
55-
MNT='--mount type=tmpfs,destination=/var/lib/postgresql/data'
40+
if [ -n "$EPHEMERAL_POSTGRES_DATA_DIR" ]; then
41+
EPHEMERAL_POSTGRES_DATA_DIR=$(realpath "$EPHEMERAL_POSTGRES_DATA_DIR")
42+
43+
if [ ! -d "$EPHEMERAL_POSTGRES_DATA_DIR" ]; then
44+
echo "Creating $EPHEMERAL_POSTGRES_DATA_DIR"
45+
mkdir -p "$EPHEMERAL_POSTGRES_DATA_DIR"
46+
fi
47+
48+
EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS+=" -v $EPHEMERAL_POSTGRES_DATA_DIR:/var/lib/postgresql/data"
49+
echo "Using data directory $EPHEMERAL_POSTGRES_DATA_DIR"
5650
else
57-
MNT=''
51+
if [[ "$OSTYPE" =~ ^linux ]]; then
52+
echo "Using ram disk"
53+
EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS+='--mount type=tmpfs,destination=/var/lib/postgresql/data'
54+
# Postgres encounters permission issues when using the ram disk unless run as its default linux user
55+
EPHEMERAL_POSTGRES_LINUX_USER=''
56+
fi
57+
fi
58+
59+
if [ -n "$EPHEMERAL_POSTGRES_LINUX_USER" ]; then
60+
EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS+=" --user $EPHEMERAL_POSTGRES_LINUX_USER"
5861
fi
5962

60-
docker run -d --rm --name postgres $MNT \
63+
# shellcheck disable=SC2086
64+
docker run -d --name postgres $EPHEMERAL_POSTGRES_DOCKER_RUN_ARGS \
6165
-e POSTGRES_USER="${POSTGRES_USER}" \
6266
-e POSTGRES_PASSWORD="${POSTGRES_PASSWORD}" \
6367
-e POSTGRES_HOST_AUTH_METHOD="${POSTGRES_HOST_AUTH_METHOD}" \

0 commit comments

Comments
 (0)