Remove sensitive information from environment variables in postgres docker container Remove sensitive information from environment variables in postgres docker container postgresql postgresql

Remove sensitive information from environment variables in postgres docker container


use args without values to build the image in your Dockerfile:

ARG PASSWORD 

and build it using

export PASSWORD="MYPASS" && docker build ...

in this way the ARG is not there when running the container

here is a complete example:

dockerfile:

FROM postgres:10.0-alpineARG my_userARG my_pass

Compose:

version: "3"services:       db:         build:           context: .           args:            - my_user            - my_pass                environment:           - POSTGRES_USER=${my_user}           - POSTGRES_PASSWORD=${my_pass}           - POSTGRES_DB=db

run it:

export my_user=test && export my_pass=test1cd && docker-compose up -d --build

now if you login to the container and try echo $my_pass you get an empty string

result :

docker exec -ti 3b631d907153 bashbash-4.3# psql -U test dbpsql (10.0)Type "help" for help.db=#


update

Before using docker secrets in Compose, take into consideration this SO question and that github answer.


You can use docker secrets in Compose.

As stated in the relevant section of the docker postgresql docs:

As an alternative to passing sensitive information via environment variables, _FILE may be appended to some of the previously listed environment variables, causing the initialization script to load the values for those variables from files present in the container. In particular, this can be used to load passwords from Docker secrets stored in /run/secrets/<secret_name> files.

Therefore your compose file can read:

version: "3"services:  db:    image: postgres:10.0-alpine  environment:    POSTGRES_USER_FILE: /run/secrets/user    POSTGRES_PASSWORD_FILE: /run/secrets/pass    POSTGRES_DB_FILE: /run/secrets/db  secrets:    - user    - pass    - dbsecrets:  user:    file: user.txt  pass:    file: pass.txt  db:     file: db.txt


I don't want anyone to exec into the container and find out the variables.

This isn't realistic and I wouldn't worry about it.

The fundamental problem here is that Docker doesn't especially have any access controls over which docker commands someone can run. If you can run any docker command at all then you have unrestricted root-level access to the host. For instance, you can

docker run --rm -it -v /:/host busybox vi /host/etc/sudoersdocker exec -it myapp_db envdocker inspect myapp_dbadmindocker exec -it myapp_app cat ./db_config.ymldocker run --rm -it -v /:/host busybox cat /host/$PWD/db_config.yml

The easiest thing to do here would be to not let any users you don't trust have access to the system at all. (If you're in a cloud environment, two cloud instances of half the size generally have the same cost as one bigger instance, so partitioning users this way could be straightforward.)

In theory you could limit things by making sure docker access is restricted (for instance, behind sudo), passing credentials only in files, and making sure the corresponding host files also have appropriate file permissions so they can't be read. That generally involves moving this configuration out of the docker-compose.yml file. It's not a "usual" Docker configuration but it does address the problem that environment variables aren't really that secure.