🐳Upgrade a Database Without Recreating It With Docker
Tags: showdev, tutorial, docker, beginners
Published: 2022-12-02 03:27:24

😟We don't typically have to worry about what happens to the data on our computers. When our computers turn on, they pull the information from the hard drive and that's that. It's not so easy with containers.

🫙Much like geysers, you're not really supposed to go in them once created. Containers are meant to be used and thrown away. They're used for cloud environments and micro-services with tons of moving parts. Containers are _ephemeral._ They are essentially disposable. Best practice is to not modify containers once they're running and instead to make your changes and then spin up a new instance.

##🥅Goal

The goal here is to complete a minor version upgrade of a database container while preserving the DB data. 

##💯Success Criteria

Success in this case will be an upgrade of postgres 9.6.1 to postgres 9.6.2 without version 9.6.2 having to boot up from scratch on first start.

<img width="100%" style="width:100%" src="https://cdn.mos.cms.futurecdn.net/83ZCE6NMYDJ7MVYyHBfau6-970-80.gif">

##🧑‍🏫Instructions 

- Data base upgrade with containers
- Create a postgres container with version 9.6.1
- Use Docker Hub documentation to learn VOLUME path
- Check logs, stop container
- Create a new postgres container with same volume using 9.6.2
- Check logs to validate

## 🧑‍🍳Prerequisites 
📌 Docker Engine + CLI installed
📌 Internet connection

## ⏰Time to Start
######Step 1 : Figure Out Where to Store Data
```-e PGDATA=/var/lib/postgresql/data/pgdata \
-v pgresdb:/var/lib/postgresql/data```


![postgres Docker Hub documentation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xn230se2bfpbz7vmyh67.png)

Searching the docs for postgres on Docker Hub, I found the above section. This is exactly what is needed to change the place where data is stored, except we change `/custom/mount:` to `pgresdb` to name our volume as such.

######Step 2: Run the Container
```docker container run \
-e POSTGRES_PASSWORD=k \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v pgresdb:/var/lib/postgresql/data \
postgres:9.6.1```

- `docker container run` tells Docker we want to start a container
- `-e POSTGRES_PASSWORD` is required to set a password for postgres
- `postgres:9.6.1` specifies we want to download postgres version 9.6.1

######Step 3: Check the Logs
`docker logs -f 'container_id_here'`

![Successful psql start](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lf79i1p1iphfm30v0o01.png)

The log file should be pretty long here since the database is being initialized. The `-f` variable let's us follow the output of the logs as they are created.

######Step 4: Stop & Start Updated Instance
First, stop the container with `docker container stop 'instance_id_here'`.

Then run this command:
```docker container run \
-e POSTGRES_PASSWORD=k \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v pgresdb:/var/lib/postgresql/data \
postgres:9.6.2```

Look familiar? That's because it's the exact same as step 2's command, but with a minor version bump!

###### Step 5: Check the Logs
`docker logs -f 'container_id_here'`

![shorter log file!](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdcw4mkpzwunb8pxlwcw.png)

The log file should be significantly shorter here because it's pulling the DB information from the volume we created earlier.

##Mistakes
- Instead of naming a volume, I put `$(pwd)`. I thought I had to name the working directory the in head of the `-v` command. This lead to creating a `pgdata` but the volume not being shown with the command `docker volume ls`. This led to permissions errors which were hard to troubleshoot.
- Not running the password environment variable led to the server not starting.

##🔥Results 
<img width="100%" style="width:100%" src="https://media.giphy.com/media/a0h7sAqON67nO/giphy.gif">
I learned how to create a volume with Docker via the CLI and do a minor database upgrade _without_ having to recreate the database. I also learned how to access the working directory and how to access/read through log files.

I was actually thinking of this problem before completing this tutorial. I was wondering how developers could account for data persisting through container failures and upgrades, so it's nice to see that Docker has a solution already built in that's fairly easy to implement.