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.