One of the most common mistakes developers make is accidentally exposing secrets in their Docker images. Consider this problematic example:

```dockerfile
# DON'T DO THIS

ARG NPM_TOKEN
ENV NPM_TOKEN=$NPM_TOKEN
RUN echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
```

This approach seems convenient but is fundamentally flawed because:

- The secret becomes part of the image layer history
- Anyone with access to the image can extract the secret
- The secret persists even after being "removed"

## The Right Way: Using Secret Mounts

Docker provides a secure way to handle secrets during build time using secret mounts. Here's the correct approach:

```dockerfile
# DO THIS INSTEAD

RUN --mount=type=secret,id=npm_token \
 NPM_TOKEN=$(cat /run/secrets/npm_token) \
 echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc
```

### Key Characteristics of Secret Mounts

1. **Temporary Access**
   - Secrets are only available during the specific build step
   - They're not persisted in the final image or layer history
2. **Filesystem Mounting**
   - Secrets are mounted at `/run/secrets/<secret_name>`
   - Each secret gets its own file in this directory
3. **Build-time Only**
   - Secrets mounted this way are only available during build time
   - They're automatically cleaned up after the build step completes

## Using Secrets in Docker Compose

For runtime secrets in a Docker Compose environment, you can define them in your compose file:

```yaml
services:
  myapp:
    image: myapp:latest
    secrets: - my_secret
    build:
      context: .
secrets: - npm_token
```

```yaml
secrets:
  my_secret:
    file: ./my_secret.txt
  npm_token:
    environment: NPM_TOKEN
```

## How to use multi-stage builds with secrets

1. **Use Build-time Secrets for Dependencies**

Imagine that you have a private npm package that you need to install for a docker container that you need to distribute. However, you don't want the consumers of the docker container to have access to the npm token. Baking that into the image via an `ARG` or `ENV` instruction is a bad idea. Instead, you can use a multi-stage build to install the npm package and then remove the secret.

```dockerfile
# Example for private npm packages

RUN --mount=type=secret,id=npm_token \
 npm config set //registry.npmjs.org/:_authToken=$(cat /run/secrets/npm_token) && \
 npm install && \
 npm config rm //registry.npmjs.org/:_authToken
```

2. **Multi-stage Builds with Secrets**

```dockerfile
FROM node:alpine AS builder
RUN --mount=type=secret,id=npm_token \

# Use secret for building

FROM node:alpine

# Final image has no trace of secrets

COPY --from=builder /app/dist ./dist
```
