Docker Community Forums

Share and learn in the Docker community.

Best Practice: How to use Python CLI app secrets in Docker Images?

Hey folks,

I am trying to figure out a way to include secrets that should not be known to the end user in an image they can pull locally and run. I am looking at this approach since packaging multi-platform Python apps with Pyinstaller (or any other Python packager) usually trigger the antivirus system when run directly on a user’s machine.

Here is the use case:

  1. This is a Python command-line application in a Docker image that will be used internally in the enterprise
  2. Enterprise end-users will pull the image from the internal artifact repository and run locally
  3. The Python application in the Docker image requires an enterprise, not individual, API key
  4. We need to employ least privilege principles, so the API key cannot be known by or exposed to users

In looking at all the various Docker documentation and articles, the recommendation is to use environment variables for things like secrets. This is great if the image is deployed to a container somewhere (K8 etc) and secrets can be used. If I use environmental variables, a user could execute the shell and simply printenv to see them.

I have a proof-of-concept, but I have no idea if this is good practice or not.

  1. Use a custom EnvVar class to return hard-coded secrets instead of python-dotenv.
  2. Use a file replacement template in the CI/CD pipeline to insert the secrets into the EnvVar class so the secrets aren’t stored in the VCS
  3. Use a multistage build Dockerfile
  4. In the build stage, use Pyinstaller to create single file executables for each script in the CLI
  5. Use the Distroless Python image for the app stage

Using the above approach, I haven’t found a way to expose the secrets since they aren’t environmental variables in the OS and the EnvVar class is compiled into the Pyinstaller executables. In addition, there is no OS or Python package manager in the Distroless Python image, so I can’t add anything to get at the executables. Even using the Python REPL from bash, I can’t get at anything since the source files aren’t in the final build.

Good? Bad? Any different approaches? I’d appreciate any constructive thoughts, comments, or suggestions.