Mike Barkas

Software Technologies

Mike Barkas

Mike Barkas

Software Technologies

Run psql in an initContainer

February 2, 2025

Kubernetes initContainers are handy for setting up configurations your container app may need before it starts up. I use psql command line client to setup roles and tables in Postgres.

Run psql commands in yaml

Using psql container and running the psql command directly in the initContainer will have some limitations. Writing long commands will have to be done in the yaml file.

Example snippet: deployment.yaml

    spec:
      initContainers:
        - name: init-db
          image: my-psql-container
          command:
            - /bin/sh
            - -c
            - psql -h ${DB_HOST} -U ${DB_USER} -d ${DB_NAME} -c "CREATE TABLE ...."
          env:
            - name: DB_HOST
              value: "my-db-host"

Run shell script file

Another option is to run a shell script in the psql container. Instead of writing our your commands in the yaml file, include a file for the shell script. This will give you more options for logic control and also make it easier to include environment variables.

Example snippet: deployment.yaml

    spec:
      initContainers:
        - name: init-db
          image: my-psql-container
          command:
            - /bin/sh
            - -c
            - /scripts/init-db.sh
          volumeMounts:
            - name: init-script
              mountPath: /scripts
              subPath: init-db.sh
          env:
            - name: DB_HOST
              value: "my-db-host"
Note: The init-db.sh file needs to be mounted for the pod to use. You can use a configMap or persistent volume.

Since you are using a Bash script, you can use your environment variables to define variables for the psql command. Use your environment variables to define variables for the psql command with the -v option.

Example snippet: init-db.sh

psql -U ${USER} -h ${HOST} -v myvar1="$ENV_VAR1" -v myvar2="$ENV_VAR2" ...

Passing environment variables with the -v option when calling the psql command will make myvar1 and myvar2 available in your sql. This will also allow you to use variables in your sql file heredoc.

Another benefit for using variables your sql commands is to include sql variable placeholders. This will help reduce the opportunity for sql injection.

Example snippet: init-db.sh

psql -U ${USER} -h ${HOST} -v myvar1="$ENV_VAR1" -v myvar2="$ENV_VAR2" ...
    CREATE DATABASE :myvar1 WITH OWNER :myvar2 ...

Since psql uses a env var for password, in your script you can authenticate to the Postgres server with different roles. You just need to re-assign the environment variable PGPASSWORD before the psql command.

Example snippet: init-db.sh

PGPASSWORD=${ENV_VAR_PASSWORD} psql -U ${USER} -h ${HOST} -v myvar1="$ENV_VAR1" -v myvar2="$ENV_VAR2" ...

My Github examples

I use this example setting up a database user and table for a containerized app in my k8s homelab. Github initContainer example

How to use environment variables in heredoc for an sql file: Github heredoc example