Docker logo

Secrets Management for Docker

The easiest way to get secrets into your Docker app is to bake them into your image. But when doing so, not only are you sacrificing security, you’ll also need to build separate images for all your environments. On top of that, rotating a secret would need to trigger a rebuild of all those images. Yuck.

This guide will help you to inject secrets into your Dockerized app without compromising either security or ease of implementation.

To do this, we’ll use the run command from the SecretHub CLI, which injects secrets into your app as environment variables.

Before you begin

Before you start, make sure you have completed the following steps:

  1. Install the SecretHub CLI for your OS.
  2. Sign up for a SecretHub account.
  3. To demonstrate the concept, we’ll use the demo secrets. If you haven’t done so already, create them in your workspace by running:
    secrethub demo init
    
  4. Install Docker

Step 1: Wrap your app start command

The recommended way to use SecretHub with Docker, is to use secrethub run within the container. Let’s look at a simple Alpine Dockerfile for a Node.js app as an example:

FROM node:alpine

COPY . .
RUN npm install

CMD ["npm", "start"]

To inject secrets into this app, use apk to install the CLI onto the image and change the entrypoint to secrethub run:

FROM node:alpine
RUN apk update && apk add --repository https://alpine.secrethub.io/alpine/edge/main --allow-untrusted secrethub-cli

COPY . .
RUN npm install

USER node

ENTRYPOINT ["secrethub", "run", "--"]
CMD ["npm", "start"]

Step 2: Define secrets

Now that your image contains the SecretHub CLI, it is time to define which secrets the container will be using. The easiest way to achieve this is by using secret references in environment variables.

SecretHub will replace any environment variables that match the following format with the corresponding: secrethub://path/to/secret.

When running Docker locally, you can set environment variables with the -e flag. For example:

docker run -e PASSWORD=secrethub://your-username/demo/password <image>

In a real-world scenario, you probably don’t control the docker run command yourself, but let an orchestrator handle that.

In that case, you can put the secret references in the environment section of your task definition of your orchestrator, e.g.:

Place this in your docker-compose.yml:

environment:
  PASSWORD: secrethub://your-username/demo/password

Place this in your deployment.yml:

env:
  - name: PASSWORD
    value: secrethub://your-username/demo/password

Place this in your task-definition.json:

"environment": [
  "name": "PASSWORD",
  "value": "secrethub://your-username/demo/password"
]

Place this in your jobspec.hcl:

env {
  PASSWORD = "secrethub://your-username/demo/password"
}

Step 3: Provide a credential

The last step for your Docker container to load secrets is to give it a credential, so it can authenticate to SecretHub and decrypt the secrets.

When running the container in the cloud, you’ll want to create a service account for the app. This way you can control and monitor the access per environment your app runs in.

But for local testing, you can also just use your personal credential.

To provide your container with a credential, there’s roughly three options:

Option 1 Mount a credential file

The CLI will look for a credential at $HOME/.secrethub/credential, so you can mount it as a volume onto the container like this (assuming your docker image is running as the user node):

docker run -v $HOME/.secrethub/credential:/home/node/.secrethub/credential <images>

Option 2 Set the credential as an environment variable

You can also set the credential by passing it as the SECRETHUB_CREDENTIAL environment variable to the container.

When running locally, this would look like this:

docker run -e SECRETHUB_CREDENTIAL=$(cat $HOME/.secrethub/credential) <image>

This is especially useful in situations where mounting a file is inconvenient, but you can easily specify environment variables (for example, in a CI runner or an orchestrator).

Option 3 Use an Identity Provider

If you’re running the container on AWS, you can use the AWS Identity Provider so you don’t have to deal with credential files at all. See the AWS ECS for a step-by-step guide on how to use this Identity Provider.

After configuring an AWS service account, all that’s left in your container is to set the SECRETHUB_IDENTITY_PROVIDER environment variable to aws.

See also