sdme
github.com/fiorix/sdme

Running an OCI Database with Volumes

Run PostgreSQL with automatically managed OCI volumes that persist data across container removal and re-creation.

Some OCI images declare volumes for data directories that should persist independently from the container. sdme detects these declarations and automatically creates host-side directories that are bind-mounted into the container.

This tutorial demonstrates OCI auto-volumes using PostgreSQL, which declares /var/lib/postgresql as a volume.

Import PostgreSQL

Make sure you have a base rootfs imported (see the different rootfs tutorial). Then import PostgreSQL as an OCI application:

sudo sdme fs import postgres docker.io/postgres --base-fs ubuntu

Verify that sdme detected the volume declaration:

sudo cat /var/lib/sdme/fs/postgres/oci/apps/postgres/volumes

You should see /var/lib/postgresql.

Create and start the container

PostgreSQL requires a password to be set via the POSTGRES_PASSWORD environment variable. Use --oci-env to pass it:

sudo sdme create mydb -r postgres --network-zone=services --hardened --oci-env POSTGRES_PASSWORD=secret --started

sdme automatically creates a host directory at /var/lib/sdme/volumes/mydb/var-lib-postgresql and bind-mounts it into the container at /oci/apps/postgres/root/var/lib/postgresql.

You can verify the volume is mounted:

sudo ls -la /var/lib/sdme/volumes/mydb/

Check the logs

sudo sdme logs mydb --oci

PostgreSQL should be running and ready to accept connections.

Connect to the database

sudo sdme exec mydb --oci -- psql -U postgres -c 'SELECT version();'

Data persistence

The key benefit of OCI volumes is that data persists even when the container is removed.

Create a test table:

sudo sdme exec mydb --oci -- psql -U postgres -c 'CREATE TABLE test (id int, name text);'
sudo sdme exec mydb --oci -- psql -U postgres -c "INSERT INTO test VALUES (1, 'hello');"

Remove the container:

sudo sdme stop mydb
sudo sdme rm mydb

The volume data is still on the host:

sudo ls -la /var/lib/sdme/volumes/mydb/

Create a new container from the same rootfs:

sudo sdme create mydb -r postgres --network-zone=services --hardened --oci-env POSTGRES_PASSWORD=secret --started

Verify the data survived:

sudo sdme exec mydb --oci -- psql -U postgres -c 'SELECT * FROM test;'

Where volumes live on the host

OCI volume data is stored under /var/lib/sdme/volumes/{container}/. The volume path from the OCI image is sanitized (slashes replaced with dashes) to create the directory name:

/var/lib/postgresql  ->  /var/lib/sdme/volumes/mydb/var-lib-postgresql

Suppressing auto-volumes

If you don't want sdme to auto-mount the declared volumes, use --no-oci-volumes:

sudo sdme create mydb -r postgres --no-oci-volumes

You can also use --bind to override a specific volume path with your own host directory. User --bind flags take priority over auto-volumes for the same container path.

Other images with volumes

Many database and stateful images declare volumes in their OCI config:

Not all images declare volumes. For example, redis and nginx do not. Use --bind to manage data directories for those images manually. See the bind mounts tutorial for details.