How to set up and use Postgres locally using Docker
Here are my personal notes on how to set up Postgres locally using Docker. This is by no means the perfect or one-and-only method, but it works for my specific needs, and might help you as-well.
I have also included how to easily download and import data from a Heroku-hosted Postgres database, although the same can easily be adapted for other hosting solutions too.
- Some familiarity with Terminal (I recommend iTerm for Mac, or cmder for Windows)
- A Mac or access to a Linux (virtual) machine (Full Windows support is outside the scope of this guide)
- About 15 minutes for the initial setup
- Set up Docker
- Launch a Postgres instance
- (optional) Restore data from a dump file
Setting up Docker
In case you already have Docker set up on your machine, you can skip to the next step. If not, read on;
You can download Docker Desktop for Mac and follow its installation instructions. Once installed and launched, you'll see a Docker status menu icon in the top-right of your display. The first time you launch Docker it might take a few minutes for it to initialize, so wait for it to complete before you proceed.
Note: Docker Desktop comes with an application called Kitematic, which allows you to more easily control docker containers using a GUI. You can use this application to start and stop containers and modify basic settings, but you'll still need to use Terminal for some of the commands mentioned, as these are not available through Kitematic.
This guide should work without issue on any recent version of Ubuntu. I have successfully used this on Ubuntu 16.04 as-well as 18.04 without issue, and it should work fine on other versions too although I have not tried this myself.
Start by installing the following required packages:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
And now add Docker's official GPG key, this will allow us to add the Docker repository:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Now add Docker's repository, this will allow you to install Docker using
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
Now that everything is prepared, you can install docker community edition with the following command:
sudo apt update && sudo apt install docker-ce
When the installation is finished, add your user to the docker group so you don't have to use
sudo when working with Docker:
sudo usermod -aG docker $USER
Close and re-open your Terminal (or logout and back in if you're doing this on a remote machine) for the changes to take full effect.
(Optional) Start Docker at Boot
If you'd like to have Docker start at system boot, you can run this command:
sudo systemctl enable docker
(Optional) Allow TCP acces to Docker
If you're running Docker on a separate (virtual) machine, you might want to enable TCP access so you can use Docker from your local machine more conveniently.
Assuming you used
systemctl (above) to start Docker at boot, run this command:
sudo systemctl edit docker
Your favorite command line text editor of choice will open with an empty file. Paste or write the following in:
[Service] ExecStart= ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
Update: It seems like they made a change to Docker at some point that killed support for adding
-H -fd://, which was the previously recommended way to have Docker listen to the default unix socket as-well. I am not sure when exactly this change was made, and if it's a permanent one or not, but the method I describe above seems to work and is also referenced here.
Save the file (
«enter» if you're using Nano, or
«enter» if you're using VIM), and run the following commands:
sudo systemctl daemon-reload && sudo systemctl restart docker
You should now be able to remotely access your Docker. You can run any command as you normally would from your local machine, you only need to add
-H to your command with the IP address of the (virtual) machine that Docker is running on. For example:
docker -H tcp://<ip-of-docker-host>:<port> container ls --all
The default port is
2375and if you're using this can be omitted from the aforementioned command.
To not have to add the IP address every time you run a Docker command, you can add an environment variable to your
.bashrc or equivalent file. Assuming you're adding it to your
.bashrc, you can add it like so:
echo export DOCKER_HOST=tcp://<ip-of-docker-host>:<port> >> ~/.bashrc
Be sure to adapt this to your specific needs. For example, if you're using something like Oh My ZSH you might want to add it to your
Setting up and launching a Postgres Docker instance
Once you've taken the following steps once, you don't need to repeat them. You can simply start your container up (again) by running
docker start postgres
Creating a new Postgres Docker container
Docker containers inherently don't have permanent storage, so we'll start by creating a Docker volume. This makes it easier to if, for whatever reason, you want to destroy and launch a new Postgres container without losing your database data.
Run the following command to create a Docker volume. Note that the example uses the name
pgdata, but you can change this to whatever you like. Be sure to use the same name in all subsequent commands too if you do change it though.
docker volume create pgdata
Now we can create the container. I recommend using an easy to remember port such as
54320, which is Postgres' default port with a zero added at the end. This way it can be easily remembered and at the same time you avoid possible conflicts should you, for whatever reason, already have another Postgres instance running on the default port.
docker run --name postgres -e POSTGRES_PASSWORD=<your-desired-password> -d -p 54320:5432 -v pgdata:/var/lib/postgresql/data postgres:9.6
Note: Be sure to set the password to something secure enough. You should never expose your Docker instance or Postgres container to the world but it's important to ensure no unwanted person (even via your local network) can access all your data.
Docker will automatically download the Postgres image if you don't already have it on your machine. When the command finishes, a fresh Postgres container should be up and running in the background. To confirm ,try connecting to it using your favorite GUI client or by using something like the
psql command-line interface.
The IP address to connect to will be that of the (virtual) machine Docker is running on, with the port you have specified (
54320 if you followed my example), the username
postgres and the password you have specified in the recentmost command.
Creating a Database
You can now create a database to use to either import your existing data into, or for setting up your new project with.
docker exec -i postgres psql -U postgres -c "CREATE DATABASE <your-desired-db-name> WITH ENCODING='UTF8' OWNER=postgres;"
Tip: You do not have to specify your password with this command as it is defined in the container's environment variable.
You should nw have a new and clean database, ready for use.
(Optional) Restoring a DB Dump
To restore a database dump into your local Docker container, first ensure your container is currently running. You can use
docker container ls to check if it's on already. If it's not, simply start it by running
docker start postgres.
Obtaining a dump of your Heroku-hosted databae
There are several ways to go about obtaining a database dump file from Heroku. If you have permission to accces the Heroku application in question, you can visit the Heroku datastores page and download the recent-most backup, or use Heroku's command-line interface to fetch the same file. This guide will assume the latter route, and walk you through how to set this up for convenient (re-)use.
Using Heroku's CLI is probably the easiest method after initial setup, a fetching an updated dump file will only take you one command. If, however, you only plan to fetch a dump file once (or very rarely at most), it migth be easiest to simply manually download via Heroku's Dashboard.
Start by installing the Heroku CLI if you haven't already. for macOS you can use brew (or, alternatively, Heroku's installer):
brew install heroku/brew/heroku
curl https://cli-assets.heroku.com/install-ubuntu.sh | sh
After installing, log in with your Heroku user credentials by triggering this command and following its steps:
When this is done, you can easily download the recent-most backup using the following command:
heroku pg:backups:download -app <name-of-your-app>
Note: this creates a filed called
latest.dumpin the current working directory. Be sure to run this command in a convenient location, such as
Restoring the data into your Docker container
Assuming you have the Docker container running and a data dump file ready, you can run the following command to import all dat. Be sure to substitute
./latest.dump to where your dump file is located, if it's not in the current working directory and called latest.dump.
docker exec -i postgres pg_restore --verbose --clean --no-acl --no-owner -h localhost -U postgres -d <your-db-name> < ./latest.dump
This command may take several minutes to complete, depending on how big your database is. Verbose mode is enabled in the above command so you can more easily track what's going on. Once it finishes, you should be all set and ready to go.
I hope this guide was helpful to you. I had originally written this down for my own reference, but thought it might be useful for others as-well. Happy coding!