Working with this in several environments I found it's easier to run postgres in a Docker container using a modified postgres image. What follows are simple steps for doing that.
First install Docker.
Second create a directory to contain your dB and open a terminal in that directory.
Third build the desired image. Create a Dockerfile
that tells Docker what the image should look like. This is what I use to specify that I want a container running a postgres db and to include python3 as a procedural language extension (though you could specify python2). Note that I specify the version of postgres I want (13) and the compatible plpython3 (also 13).
I also include a reference to a 'requirements' file (see next step):
FROM postgres:13
RUN apt-get update
RUN apt-get -y install python3 postgresql-plpython3-13
RUN apt-get -y install python3-pip
RUN apt-get clean && \
rm -rf /var/cache/apt/* /var/lib/apt/lists/*
# Requirements installation
COPY requirements_dockerbuild13.txt /tmp/
RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install --requirement /tmp/requirements_dockerbuild13.txt
Fourth, is an optional step to specify any additional libraries/packages/modules of interest. Those can be put in a 'requirements.txt' file. If you don't have any requirements just delete the line referring to them in the Dockerfile
. If you do have requirements then create a 'requirements.txt' file. In my case I wanted the image to also include 'pandas' and 'networkx'. My file looks like (yes, two lines of text):
pandas>=1.3.5
networkx>=2.0
Fifth, at the command line in your terminal run docker build -t xxx .
. The -t xxx
is the name you give to the image and the .
means the Dockerfile is in the current directory. Voila you've now have a postgres image named 'xxx' that contains postgres/python3/plpython3/pandas/networkx In my case the tag I used was 'postgresql-plpython3-13'.
To use the image you launch it using docker-compose up -d
and that command will launch an image in accordance with the docker-compose.yml
located in the directory. Yes, one more text file to create. Mine looked like this:
version: "3"
services:
postgres:
image: postgresql-plpython3-13 <--- name of the image just created
container_name: cain_db <--- arbitrary name of container running image
command: ["-c", "logging_collector=on","-c", "log_statement=all"]
volumes:
- ./caindata:/var/lib/postgresql/data <--- *comments below*
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=cain_data <---- name of db
ports:
- 5566:5432 <--- making the db available on port 5566 instead of 5432
volumes:
caindata: <--- name of the volume
That docker-compose file makes docker run a container named cain_db with the postgres image you created running inside it. That db can be connected to on port 5566 a port I chose to be different from the default postgres port (I could have used 5432). The db will be named 'cain_data' and here's the important bit: the db will be in a folder in the current directory named 'caindata' as opposed to /var/lib/postgresql/data which is where MacOS would put it.
To shut down the container use docker-compose down --remove-orphans
. The database will persist and when you launch docker-compose up -d
everything will be as it was when you shut down.
Recap:
- build the desired image with or without requirements file
- compose the appropriate docker-compose.yml file
- launch db with
docker-compose up
, shut down with docker-compose down
Additional notes:
- If you follow all the steps you'll have a directory with: a file called
Dockerfile
, a file called requirements.txt
, a file called docker-compose.yml
, and a sub-directory with the db.
- Neat thing, add a 'readme' file and zip the directory. Now you can provide someone else who has Docker with your complete db.