DEV Community

Cover image for The Simplest Possible Docker Setup For PostgreSQL
i. welch canavan
i. welch canavan

Posted on • Originally published at shipshape.io

The Simplest Possible Docker Setup For PostgreSQL

Recently I was working through Xiaoru Li’s excellent tutorial on Next-Auth and I needed a Postgresql database quick. My search got a lot of results that were similar, but different enough for me to lose confidence in any given solution. I spent a little time searching for a simple configuration and this is what I came up with. For those of you in a rush, copy and paste away:

version: "3.8"

services:
  postgres:
    image: postgres:13-alpine
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: username
      POSTGRES_PASSWORD: password
      POSTGRES_DB: postgres
    volumes:
      - ./data:/var/lib/postgresql/data\
Enter fullscreen mode Exit fullscreen mode

Now, for the rest of you who aren’t even sure why this is necessary or aren’t sure why there are so many suggestions when you search for this problem, let’s dig in.

Why Docker at all?

In my career, it has been immeasurably beneficial to make sure that the low level technologies and languages I am relying upon are “insulated” from the computer I am developing on. By insulated, I mean it is best to use Docker or a version manager (e.g. rbenv, pyenv, nvm, ...) rather than installing a technology directly on to your operating system.

For example, when you use an already installed language (like python on MacOS) you run the risk of breaking how your OS functions. When you install a language directly (e.g. brew install python on MacOS) you run the risk of packages conflicting.

Using a version manager allows you to easily reset the installation of a language if anything goes wrong. Presuming your configuration and package manifests are intact you should have an easy time getting back up and running. Using a version manager also helps you run different version of a language or database for different projects so you can easily switch between them.

Running your DB inside of docker can be thought as the ultimate version manager, it not only keeps different versions separate from each other, it keeps each version isolated in its own virtual machine.

Docker-compose vs docker run

When looking for a “minimally viable” way to get Postgres running the results were fairly evenly split between suggestions using docker run and suggestions using docker-compose. docker run is a way of running commands inside of a docker container, if the container does not exist it will create it before running the command. docker-compose prompts docker to run a variety of commands (up, down, stop) relative to a docker-compose.yml configuration file. There are a lot of differences between the two methods, but syntactically you can think of the difference between them as the difference between passing all of your eslint options as flags in the command line and running eslint in conjunction with an .eslintrc file.

Using a docker-compose.yml file is the easier route, as it is the more legible of the two options.

Exploded docker-compose.yml

What is the docker-compose.yml file doing? Let's go line by line.

version: "3.8"
Enter fullscreen mode Exit fullscreen mode

The docker-compose.yml API has different versions, this is something to be keenly aware of while researching and creating your configuration. It is typically best to use the latest version. You should also check what version of Docker Engine you are running.

services:
  postgres:
Enter fullscreen mode Exit fullscreen mode

A typical docker-compose.yml in a professional environment will have several services configured to work together. For our purpose we only need the one. The key for your service is arbitrary, you could name it db or banana, but for organizational purposes it makes most sense to match the key to the Docker image you are relying upon.

image: postgres:13-alpine
Enter fullscreen mode Exit fullscreen mode

This is the image tag, the list of available options is available on Docker Hub. postgres refers to the Docker image you would like to use. 13-alpine is a tag of the image with 13 referring to the version of Postgres you would like to use and alpine denoting a flavor of linux that is stripped down to be as small as possible. You can always specify simply postgres or postgres:latest if size or version doesn't matter to you.

restart: always
Enter fullscreen mode Exit fullscreen mode

What it says on the label! Always restart this container when docker engine starts.

ports:
  - "5432:5432"
Enter fullscreen mode Exit fullscreen mode

This forwards the Docker containers ports to your machine's ports. 5432 is PostgreSQL's default port. You should only need to change this if you have a conflicting process using the same port.

environment:
  POSTGRES_USER: prisma
  POSTGRES_PASSWORD: prisma
  POSTGRES_DB: tabata
Enter fullscreen mode Exit fullscreen mode

While there are other environment variables available for your PostgreSQL container, this is all you need to get the container running. If the container and database do not yet exist docker-compose up will create a database with this name, user, and password.

volumes:
  - ./data:/var/lib/postgresql/data\
Enter fullscreen mode Exit fullscreen mode

Volumes allow your data to persist in-between bringing your container up and down. This tells docker where to store that persisted data and links it to the location within your container.

You know something I don't?

If you've made it to the end and you see a way to make this configuration even leaner, please let me know!

Top comments (1)

Collapse
 
slavius profile image
Slavius

It probably should be noted that while running PostgreSQL in Docker might be simplification it is also an overcomplication. The only exception here is Linux where docker runs natively talking to Linux kernel. On MacOS and Windows there's hidden VM running Linux that runs docker connected via virtual network adapter bridge with memory limited to the Docker VM. This may cause issues and slowdowns and prevents some scenarios (like testing how PostgreSQL performs on different filesystems, with different sync options and different kernel settings).
Also you lose some control over your PostgreSQL settings as several .conf settings can only be changed by editing config files.

An alternative option would be portable PostgreSQL (zip, tgz) that you can unpack and run in a folder on your local disk.