Skip to main content
Version: Next

Docker Integration

SyVault integrates with Docker workflows to inject secrets at runtime without baking them into images. The primary mechanism is the sy exec command, which resolves secrets and passes them as environment variables to a child process.

Runtime Injection with sy exec

The recommended approach is to install the sy binary in your container image and use it as the entrypoint. Secrets are fetched from SyVault at container startup and injected into the application process. They never appear in image layers, build logs, or docker inspect output.

Dockerfile

FROM node:20-slim

# Install the sy CLI
COPY --from=syvault/cli:latest /usr/local/bin/sy /usr/local/bin/sy

WORKDIR /app
COPY package*.json ./
RUN npm ci --production
COPY . .

# The entrypoint fetches secrets and launches the app
ENTRYPOINT ["sy", "exec", \
"--env", "DB_HOST=sy://Production/Database/field/host", \
"--env", "DB_PORT=sy://Production/Database/field/port", \
"--env", "DB_USER=sy://Production/Database/field/username", \
"--env", "DB_PASS=sy://Production/Database/field/password", \
"--"]
CMD ["node", "server.js"]

Running the Container

Pass the SyVault client credentials as environment variables at runtime:

docker run -d \
-e SY_SERVER=https://vault.example.com \
-e SY_CLIENT_ID=c9a1b2d3-4e5f-6789-abcd-ef0123456789 \
-e SY_CLIENT_SECRET="$(cat /path/to/client-secret.key)" \
-p 3000:3000 \
myapp:latest

SY_CLIENT_ID and SY_CLIENT_SECRET are the only credentials passed to the container. The actual database password, API keys, and other secrets are resolved inside the container at startup and exist only in the application process's environment.

Entrypoint Script

For more complex logic (conditional secrets, health checks before fetching), use a shell entrypoint:

#!/bin/sh
set -e

# Wait for SyVault to be reachable
until sy profile list > /dev/null 2>&1; do
echo "Waiting for SyVault..."
sleep 2
done

# Launch the app with secrets injected
exec sy exec \
--env DB_HOST=sy://Production/Database/field/host \
--env DB_PASS=sy://Production/Database/field/password \
--env REDIS_URL=sy://Production/Redis/field/url \
-- "$@"
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "server.js"]

Docker Compose

A complete Docker Compose example with SyVault secrets injection:

version: "3.9"

services:
api:
build: .
ports:
- "3000:3000"
environment:
- SY_SERVER=https://vault.example.com
- SY_CLIENT_ID=c9a1b2d3-4e5f-6789-abcd-ef0123456789
- SY_CLIENT_SECRET=${SY_CLIENT_SECRET}
entrypoint:
- sy
- exec
- --env
- DB_HOST=sy://Production/Database/field/host
- --env
- DB_PASS=sy://Production/Database/field/password
- --env
- REDIS_URL=sy://Production/Redis/field/url
- --
command: ["node", "server.js"]
depends_on:
- redis

worker:
build: .
environment:
- SY_SERVER=https://vault.example.com
- SY_CLIENT_ID=d8b2c3e4-5f6a-7890-bcde-f01234567890
- SY_CLIENT_SECRET=${SY_WORKER_CLIENT_SECRET}
entrypoint:
- sy
- exec
- --env
- DB_HOST=sy://Production/Database/field/host
- --env
- DB_PASS=sy://Production/Database/field/password
- --env
- QUEUE_URL=sy://Production/SQS/field/url
- --
command: ["node", "worker.js"]

redis:
image: redis:7-alpine
ports:
- "6379:6379"

Set SY_CLIENT_SECRET in a .env file (excluded from version control):

# .env (DO NOT COMMIT)
SY_CLIENT_SECRET=base64-encoded-private-key-for-api
SY_WORKER_CLIENT_SECRET=base64-encoded-private-key-for-worker

Build-Time vs Runtime Secrets

ApproachWhen to UseSecurity
sy exec at runtimeApplication credentials (DB, API keys, tokens)Secrets never in image layers
Docker BuildKit secretsBuild-time needs (private npm registry, license keys)Secrets not persisted in layers but available during build
Hardcoded in DockerfileNeverSecrets visible in image history

If you need a secret during docker build (for example, to install a private npm package), use Docker BuildKit's --secret flag:

# syntax=docker/dockerfile:1
FROM node:20-slim
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
# Fetch the token with sy and pass it to the build
docker build --secret id=npm_token,src=<(sy secret notation "sy://CI/NPM/field/token") .

Multi-Stage Build with sy

For images that need the sy binary only at runtime, use a multi-stage copy:

FROM syvault/cli:latest AS sy
FROM node:20-slim
COPY --from=sy /usr/local/bin/sy /usr/local/bin/sy
# ... rest of your image

This keeps the image size minimal and avoids pulling the full SyVault CLI build toolchain.