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.
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:
This will print the version of your installed Docker. In case you get an error, switch to docker.com and download and install Docker.
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 runtakes an image, turns it into a container, and runs that container.
--name some-redisassigns the name 'some-redis' to the created container. This will help to identify and control it later.
--publish 6379:6379publishes 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.
--detachruns 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.
redisthe 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
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 runsame as for the Redis command.
--name some-postgressimilar to the Redis command, this assigns a name to the created container.
-p 5432:5432shorthand for
--publish 5432:5432(by default Postgres listens on port 5432).
--env POSTGRES_USER=user --env POSTGRES_PASSWORD=passwordprovide environment variables that are passed to inside the container. Here we provide a default postgres username as
POSTGRES_USER(will be the superuser) and a password for that user as
POSTGRES_PASSWORD. These are made up, feel free to choose something else. Take a look at the linked Docker image for more details.
postgresthe 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:
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 🙌