Skip to content

_FILE environment variable support for Docker Secrets #227

Closed
@jasonrichdarmawan

Description

@jasonrichdarmawan

Getting started

A minor patch to support Docker Secrets, so you don't have to store unencrypted secrets in the env file.

The repository should look like this

/
├─ graphql
|  ├─ Dockerfile
|  └─ docker-entrypoint.sh

Dockerfile

FROM node:12-alpine
LABEL description="Instant high-performance GraphQL API for your PostgreSQL database https://github.com/graphile/postgraphile"

# Install PostGraphile and PostGraphile connection filter plugin
RUN npm install -g postgraphile@4

EXPOSE 5000

# patch postgraphile:4.7.1; DATABASE_URL_FILE environment variable implementation.
RUN apk add bash
COPY docker-entrypoint.sh /usr/local/bin/
RUN ln -s /usr/local/bin/docker-entrypoint.sh / # backwards compat
ENTRYPOINT ["docker-entrypoint.sh"] 
CMD ["postgraphile", "-n", "0.0.0.0"]

docker-entrypoint.sh

#!/usr/bin/env bash

# usage: file_env VAR [DEFAULT]
#    ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
#  "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
    local var="$1"
    local fileVar="${var}_FILE"
    local def="${2:-}"
    if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
        echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
        exit 1
    fi
    local val="$def"
    if [ "${!var:-}" ]; then
        val="${!var}"
    elif [ "${!fileVar:-}" ]; then
        val="$(< "${!fileVar}")"
    fi
    export "$var"="$val"
    unset "$fileVar"
}

# Loads various settings that are used elsewhere in the script
# This should be called before any other functions
docker_setup_env() {
    file_env 'DATABASE_URL'
}

# call the function
docker_setup_env

# call postgraphile
exec "$@"

How to use this patch

  1. Create the Docker Secret

First, generate the random strings.

$ python3 -c "import base64, os; print(base64.b64encode(os.urandom(24)).decode('ascii'))"

Then, manually create a Docker Secret file for the POSTGRES_PASSWORD and DATABASE_URL environment variables. Note that DATABASE_URL follows the syntax postgres://<POSTGRES_USER>:<POSTGRES_PASSWORD>@db:5432/<POSTGRES_DB>, POSTGRES_PASSWORD will be stored in environment variable unecrpyted.

$ echo <POSTGRES_PASSWORD> | docker secret create dbpw -
$ echo postgres://<POSTGRES_USER>:<POSTGRES_PASSWORD>@db:5432/<POSTGRES_DB> | docker secret create dburl -

Use docker exec -ti <CONTAINER ID> cat /run/secrets/<secert_name> to read the contents of the secret data file.

  1. Build the Docker Image
$ docker build -t postgraphile:4.7.0-alpine ./graphql
  1. ... via docker stack deploy or docker-compose

docker-compose.yml example

version: '3.7'

networks:
  backend:
  db:

secrets:
  dbpw:
    external: true
  dburl:
    external: true

volumes:
  dbdata:

services:
  db:
    image: postgres:12-alpine
    ports:
      - 5432:5432 # dev build only
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD_FILE=/run/secrets/dbpw
    networks:
      - backend
      - db
    secrets:
      - dbpw
    volumes:
      - dbdata:/var/lib/postgesql/data
  graphql:
    image: postgraphile:4.7.0-alpine
    ports:
      - 5000:5000 # dev build only.
    environment:
      - DATABASE_URL_FILE=/run/secrets/dburl
    networks:
      - backend
      - db
    secrets:
      - dburl

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions