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:
- Set up SecretHub on your workstation.
- 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
- 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
.