Building a temporary database for testing and development
Tags: docker, database, testing
Published: 2021-06-20 16:32:42

### TL;DR
Add the initial data to the volume, and run docker-compose with the renew anon volumes argument (-V)

### Introduction
So you have built your system and now is time to test it, or you want to do a demo and everything needs to be set up on a given state. Unfortunately, you were testing some changes and now you need to clean up the database, or even worse perform a series of actions just to get it in the desired state.

Luckily there are a few actions you can take to make your life easier.

These next tips will assume you have docker and docker compose installed as these will be the backbone of the solution.

## Step 1 - An empty database with docker

Let's say you just want a runnable database to start developing, perhaps you are playing with some ORM[^1] solution, an empty database can be quite handy.

The following docker command can do the trick for postgres:

```sh
docker run -e POSTGRES_USER=my_user -e POSTGRES_PASSWORD=my_password -e POSTGRES_DB=some_db postgres:13 
```

A one-liner and we have an accessible database to our heart's content.

## Step 2 - A databse witth initial data and docker
A database without data is nice but a database already set up is even nicer. For that we can use [volumes](https://docs.docker.com/storage/volumes/) and an initial data for the database dump. [The initialization scripts section] of the postgres image tells us that all we need to do is copy some [dump](https://www.postgresql.org/docs/12/app-pgdump.html) to the folder /docker-entrypoint-initdb.d/.

This would be done with this argument:

```sh
--mount type=bind,source=/some/path/my_dump.sql,target=/docker-entrypoint-initdb.d/dump.sql 
```

So our full command would look like 

```sh
docker run -e POSTGRES_USER=my_user -e POSTGRES_PASSWORD=my_password -e POSTGRES_DB=some_db  --mount type=bind,source=/some/path/my_dump.sql,target=/docker-entrypoint-initdb.d/dump.sql  postgres:13 
 ```

[^1]: [Object Relational Mapping](https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping)

### Step 3 - Tidying it up with docker-compose
Docker is useful but docker-compose makes things more manageable.

With 2 tricks we can have our database running temporarily without much hassle.

#### Step 3.1 Convert the docker to docker-compose yaml

Let's just add the arguments of our command line to a compose file.

```yaml
# docker-compose.yml
version: "3"
services:
  db:
    image: postgres:13
    environment:
      POSTGRES_PASSWORD: "my_password"
      POSTGRES_USER: "my_user"
      POSTGRES_DB: "some_db"
    volumes:
      -  ./some/path/my_dump.sql:/docker-entrypoint-initdb.d/my_dump.sql
```

This is very nice, run it with the following command, and your database will be there same as before.

```sh
docker-compose up

```
#### Step 3.2 Making sure our database remains the same

If we ran the previous command and delete a record we would be losing that record next time. This is sometimes not desirable for testing, demos, or even general development. I find oy very calming to have the same environment every time.

To achieve that we need to renew the volumes. Running it with the argument -V , from [compose docs](https://docs.docker.com/compose/reference/up/) ,this states the following:

>  -V, --renew-anon-volumes   Recreate anonymous volumes instead of retrieving data from the previous containers.

This makes our command to start the database looks like this:

```sh
docker-compose up -V db
```

Now if you delete some initial data and execute the command again the state will be brought right back to how it was.

Hope you folks find it helpful.