PostgreSQL — commonly known as “Postgres” — is a popular open-source relational database. The PostgreSQL Images based on Wolfi and maintained by Chainguard provide distroless Images that are suitable for building and running PostgreSQL workloads.
Because Chainguard Images (including the PostgreSQL image) are rebuilt daily with the latest sources and include the absolute minimum of dependencies, they have significantly fewer vulnerabilities than equivalent images, typically zero. This means you can use the Chainguard PostgreSQL Image to run Postgres databases in containerized environments with a smaller footprint and greater security.
In order to illustrate how the PostgreSQL Chainguard Image might be used in practice, this tutorial involves setting up an example PHP application that uses a Postgres database. This guide assumes you have Docker installed to run the demo; specifically, the procedure outlined in this guide uses Docker Compose to manage the environment on your local machine.
This step involves downloading the demo application code to your local machine. To ensure that the application files don’t remain on your system navigate to a temporary directory like /tmp/.
Your system will automatically delete the /tmp/ directory’s contents the next time it shuts down or reboots.
The code that comprises this demo application is hosted in a public GitHub repository managed by Chainguard. Pull down the example application files from GitHub with the following command.
git clone --sparse https://github.com/chainguard-dev/edu-images-demos.git
Because this guide’s demo application code is stored in a repository with other examples, we don’t need to pull down every file from this repository. For this reason, this command includes the --sparse option. This will initialize a sparse-checkout file; this causes the working directory to contain only the files in the root of the repository until the sparse-checkout configuration is modified.
Navigate into this new directory.
To retrieve the files you need for this tutorial’s sample application, run the following git command.
git sparse-checkout set postgres
This modifies the sparse-checkout configuration initialized in the previous git clone command so that the checkout only consists of the repo’s postgres directory.
From here, you can run the application and use a web browser to observe it working in real time, which we’ll do in the next section.
We encourage you to check out the application code on GitHub to better understand how this application works, but we’ll provide a brief overview here.
This demo creates a LEPP (Linux, (E)NGINX, PostgreSQL and PHP-FPM) environment based on Wolfi Chainguard Images. We will use Docker Compose to bring up the environment, which will spin up three containers: an app container, a postgres container, and an nginx container. These will run as services.
Once the environment is up, you can visit the demo in your web browser. The index.php file contains code that does the following:
Every time you reload the page, a new entry will be added to the table.
Note that this application includes a Dockerfile.
RUN apk update && apk add php-pgsql
This Dockerfile takes the public php:latest-fpm-dev Chainguard Image and installs the php-pgsql package onto it. This image comes with drivers that allow PHP applications to connect to MySQL or MariaDB databases by default but it doesn’t have an equivalent for PostgreSQL. For this reason, we use this Dockerfile to install this package in order for the PHP application to be able to connect to the Postgres database.
Execute the following command to build an image with this Dockerfile, and then create and start each of the three containers and bring up the application.
docker compose up -d
The -d option is short for --detach; this will cause the containers to run in the background, allowing you to continue using the same terminal window. If you run into permissions issues when running this command, try running it again with sudo privileges.
Note: If at any point you’d like to stop and remove these containers, run docker compose down.
docker compose down
Once all the containers have started, you’ll be able to visit the application and observe it working. Open up your preferred web browser and navigate to localhost:8000. There, you’ll be presented with text like the following
Every time you refresh your browser, a new entry will appear.
This shows that the application is recording each visit in the PostgreSQL database and that the application is working correctly.
After confirming that the application is functioning as expected, you can read through the next section to explore how else you can work with the postgres container.
The docker-compose.yml file contains some configuration details regarding the PostgreSQL database used in this example application. Run the following command to inspect the contents of this file.
We’re interested in the postgres service:
. . .
. . .
This section defines a few environment variables relating to the database used in the example application. Importantly, they specify that the application database is named php-test and runs under a user named php with the password “password”. Using this information, you can connect to the php-test database running in the container with a command like the following.
docker exec -it postgres-postgres-1 \
psql -p 5432 -U php -W -d php-test
docker exec allows you to execute commands within a running container. The -i argument allows you to execute an interactive command while the -t option allocates a pseudo-TTY to the process within the container. Because our goal is to access the sample database through the psql command line client, these options are necessary. Next, enter the name of the container running the PostgreSQL database; by default, this will be named postgres-postgres-1.
Following that, the remainder of this command represents the command that will be run within the container. Here, we run the psql command to access the database specifying that we want to connect over port 5432 as the php user. The -W option indicates that we want to be prompted to enter the password interactively, and -d php-test specifies that we want to connect to the php-test database.
Enter password and you’ll then be presented with the psql command prompt.
Type "help" for help.
From here, you can interact with the database from within the postgres-postgres-1 container as you would with any other PostgreSQL database. For example, you could update existing tables, create new ones, and insert or delete data.
To close the psql prompt, you can enter the following command.
Of course, you likely won’t be regularly managing your containerized databases over the command line. The purpose of this section is to only show that you can interact with the database running in this container just like you would with any other Postgres database.
If your project requires a more specific set of packages that aren't included within the general-purpose PostgreSQL Chainguard Image, you'll first need to check if the package you want is already available on the wolfi-os repository.
If the package is available, you can use the wolfi-base image in a Dockerfile and install what you need with apk, then use the resulting image as base for your app.
Check the "Using the wolfi-base Image" section of our images quickstart guide for more information.
If the packages you need are not available, you can build your own apks using melange. Please refer to this guide for more information.