Have you ever had the problem where a tool or a piece of software works fine on your machine, but the moment you install it on someone else's you get all kinds of issues? Well, I have, and particularly for this reason Docker was invented! In this blog post we will take a quick look at what Docker is and how easy it is to run a database in a Docker container. This container will work on any machine. I promise. Along the way you also learn some Docker specific lingo.
According to the official docs, Docker is and "open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications."
For fully understanding Docker we also need to talk about the difference between Docker and a Virtual Machine (VM). The latter is often run in cloud environments like AWS and Azure. Whenever you create a VM you are sharing the hardware with others and other VMs. What these cloud environments are doing is virtualise the hardware. Docker doesn't do that and does it differently. In a VM you can have multiple Operating Systems running on the same hardware, whilst with Docker you virtualise the Operating System. Therefore, the big difference between VMs and Docker containers is that the former can have multiple (Guest) Operating Systems on the same hardware, through for example VMWare. Whilst when you install Docker, you are going to use the Docker Engine to create isolated entities on the OS. These entities are called containers. Docker therefor allows you to automate the deployment of applications in these containers.
Enough theory, let's jump into installing Docker and firing up a Postgres database. In order to use Docker you first need to install it. You can either install Docker on a Desktop machine (both Windows and Mac), or on a server (Linux based installations). For this tutorial we're going to install Docker on a Mac. Windows installation instructions can be found here. For a Mac (and I think also for Windows) the installation is fairly straightforward. You download the app and drag it to Applications. Then you double click the Docker.app and it should start. You can check if it's working if there is a Docker icon (the whale or ship like image with containers) on the top right next to your other small icons. If this is the case you can quickly follow the 'Hello World' example to get up and running.
Hands down the easiest way of running a clean Postgres database is by running this command in a terminal window (after Docker has been installed):
docker run --name postgres-db -e POSTGRES_PASSWORD=docker -p 5432:5432 -d postgres
But what does it do?
Now you can connect to this brand new Postgres database in any tool that allows you to communicate with databases. I tend to use RazorSQL or DBeaver. You need to use the following connection details to actually connect to the DB:
Once connected you can do anything you want with the database (Create tables, load data etc). But as you can see the database is completely empty. However, the real power of Docker is when you want to easily provision a database that has already content in it. This can be a simple or a complex database structure and schema. The choice is all yours. What this also means is that you can easily spin up such a container (and shut it down). Let's see how below:
In order to create a pre-populated database we need to create a Dockerfile. This is a bit of a strange file. At least the first time I saw one. It doesn't have a file extension. It's basically a text document that is being used by Docker and describes what it needs to do. Basically a set of instructions. In our example we want to do the following:
Above I described what I want in this file. Now let's create it. Create an new file and call it 'Dockerfile'. Use a text editor like VS Code to open it and add the following:
FROM postgres ENV POSTGRES_PASSWORD docker ENV POSTGRES_DB world COPY world.sql /docker-entrypoint-initdb.d/
The last line points at a SQL dump file. You can find the one I'm using here. Download it and put the .sql file in the same folder as the Dockerfile. Next step is to create our image by typing this command in the terminal:
docker build -t my-postgres-db ./
The above line tells Docker to build an image from the Dockerfile and give it a name of 'my-postgres-db'. In order to see your images you can run
docker images -a
Great, now we got our own image called 'my-postgres-db'. We can run it as a container by doing the following:
docker run -d --name my-postgresdb-container -p 5432:5432 my-postgres-db
You can now connect to this database by using the login details specified in the Dockerfile.
In case you want to remove images you can run this command:
docker image rm 'nameOfTheImage'