How to Run a Local Database Using Docker
So, you are working on your side project and the time has come and you need a database? Awesome! In this article we want to show you how simple it is to start a database on your local machine, using Docker.
This article will not go into any detail about how to properly secure your database. The commands provided are only meant to be executed in a safe, non-production environment, like your local development machine. For ways to host a secure database, please have a look at the section "Ready to move into the cloud?" at the end of this article and do your own research.
This is entirely up to you. There are a lot of different database types to choose from, and there is no right or wrong. It all depends on your specific use case.
This article includes examples for Redis and PostgreSQL. To figure out which database you should choose, please refer to other resources. I can recommend this Video: "Did I Pick The Right Database?" (1h) from Theo Browne. It provides an excellent overview of the different types of databases and when to use them.
The most common databases are relational databases (Wikipedia: Relational Database). Most of them can be managed with a domain-specific language (DSL) called "SQL" (e.g. MySQL, PostgreSQL, MariaDB). In this article we will show how to start a PostgreSQL database locally.
Another set of popular "databases" are key-value data stores (e.g. Redis, Memcached). Most often these are not used as databases, but rather as a cache for other databases. Personally, I like to use them for small side projects because of how easy they are to set up and work with. This article will provide an example of how to start Redis.
There are more types of databases like non-relational/NoSQL databases (e.g. MongoDB, CouchDB). These won't be covered in this article.
Docker
If you want to follow along with the commands and code snippets in this article, you need to have Docker installed on your machine. If you are unsure whether that's the case, run the following command:
docker -v
This will print the version of your installed Docker. In case you get an error, switch to docker.com and download and install Docker.
Deno
Once we start a database, we want to verify that we can connect to it. There are a lot of ways to connect to a (local) database. In this article we are going to use the Deno JavaScript REPL (Wikipedia: REPL) to connect to the local database(s). This is entirely optional. If you want to follow along with the code snippets to verify that the database can be connected to, you need to have Deno installed. If you are unsure if that's the case, run the following command:
deno -V
This will print the version of your installed deno
CLI. In case you get an error, head over to deno.land to download and install Deno.
Redis is a key-value data store that uses the system memory to store data. Since it does not need to perform time-consuming I/O disk operations, it is extremely fast. The amount of data you can store in it is restricted by the size of your memory, though.
Redis comes with an official Docker image in the Docker Hub. We are going to use this image to run Redis on our local machine.
Run the following command, and you're good to go:
docker run --name some-redis --publish 6379:6379 --detach redis
If everything worked, this command will respond with the container ID that it just created.
Let's have a closer look at the command itself:
docker run
takes an image, turns it into a container, and runs that container.--name some-redis
assigns the name 'some-redis' to the created container. This will help to identify and control it later.--publish 6379:6379
publishes the container-internal TCP port 6379 to the outside world. This allows us to connect with Redis, which is listening at port 6379 by default.--detach
runs the container in "detached" mode. This means that you can happily close the terminal after you ran that command. The container will continue to run.redis
the name of the image that we want to use. This has to be the last argument to the command, otherwise the arguments would be passed to the entrypoint of that image.
To verify that the container got created and is running, you can list your running docker containers with this command:
docker container ls
The output of this command includes information about the running containers, such as the name some-redis
as well as the applied port mapping 0.0.0.0:6379->6379/tcp
.
Now we want to verify that we can connect to Redis and use it as a database. Like discussed in the prerequisites, we chose the Deno runtime to do this. To connect to and interact with our database we need a "driver". The Deno ecosystem provides a very convenient Redis driver, that we are going to use in our example script.
You can run this script in the Deno REPL, which you can enter by running deno
in your terminal. Now either copy the below code into the REPL all at once and execute it, or execute it line by line:
Database drivers for Redis exist for almost all known programming languages, so feel free to search for a driver that fits your needs.
Postgres (officially PostgreSQL), is a classical relational database. It is slightly less convenient to set up than Redis, but - to be fair - it's a "proper" database. If you are familiar with SQL (or want to learn it), this is a great choice. It's a well-established database with a huge community and a lot of online resources.
Postgres also comes with an official Docker image which we are going to use:
docker run --name some-postgres -p 5432:5432 -d --env POSTGRES_USER=user --env POSTGRES_PASSWORD=password postgres:alpine
Let's take a closer look at this command:
docker run
same as for the Redis command.--name some-postgres
similar to the Redis command, this assigns a name to the created container.-p 5432:5432
shorthand for--publish 5432:5432
(by default Postgres listens on port 5432).-d
shorthand for--detach
.--env POSTGRES_USER=user --env POSTGRES_PASSWORD=password
provide environment variables that are passed to inside the container. Here we provide a default postgres username asPOSTGRES_USER
(will be the superuser) and a password for that user asPOSTGRES_PASSWORD
. These are made up, feel free to choose something else. Take a look at the linked Docker image for more details.postgres
the image that we want to use for the container.
Like before, we will use a Deno driver and the Deno REPL to verify that we can connect to this database. Start the Deno REPL by running deno
, and then execute this code in it (preferably a single command at a time):
The databases started this way will lose their data if you remove, or even stop, the containers. To persist the data, you need to mount a file on your local hard drive where the data can be stored. If you are interested, you can take a look at the Docker Storage documentation on how to do so.
Unfortunately, each database stores its data differently, so there is no easy solution that fits all scenarios. Also note, that in the case of in-memory data stores like Redis you need to dump the memory-state to a file (Redis - Persistance documentation) to not lose it.
An example for storing the data from Postgres on the host system using a "bind mount", could look like this:
docker run --name some-postgres -p 5432:5432 -d --env POSTGRES_USER=user --env POSTGRES_PASSWORD=password --mount type=bind,source="$(pwd)"/postgres-data,target=/var/lib/postgresql/data postgres:alpine
This is the same command that we used before, but with one additional argument:
--mount type=bind,source="$(pwd)"/postgres-data,target=/var/lib/postgresql/data
This will mount the location at which Postgres stores its data (default: /var/lib/postgresql/data
) to a folder called postgres-data
in the current directory (pwd
) on the host system. If you always start the Postgres container with this command, your database data will persist, even when the container got removed. Note, that this directory on the host system will be owned exclusively by the user "user"
(as specified in the POSTGRES_USER
environment variable), so you can't look at the file(s) in it.
You want to lift your project, including your database, up into the clouds (i.e. "deploy")? There are great websites that offer affordable "Database as a Service" (DBaaS) services. Alongside the well-known and big SaaS providers like AWS, Azure, and Cloudflare, there are smaller projects emerging that focus more on usability. I want to emphasize the following two providers, that I've been using for private projects and am very happy with:
planetscale.com Very fast, generous free tier
railway.app Free "Starter" plan in which you receive 5$ or 500 hours of usage per month (whichever limit is reached first)
These are no affiliate links, I'm just genuinely happy with their services.
Obviously there is a lot more to databases than what we talked about in this article. Two of the big remaining challenges are security and persistence. Depending on your application's architecture and your system's infrastructure these will need to be solved in very different ways.
However, to get started with databases, starting one on your local machine is a perfect first step. We hope that we were able to make this process less scary with this blog post, and we continue to wish you a pleasant journey 🙌