docker compose 실행시 sops에 등록된 age의 secret, public를 환경 변수로 주입하여 실행합니다.
실행 주체에 따라 아래와 같은 ENV 네이밍으로 넘겨주면 됩니다.
mise
secret: MISE_SOPS_AGE_KEY
public: MISE_SOPS_AGE_RECIPIENTS
sops
secret: SOPS_AGE_KEY
public: SOPS_AGE_RECIPIENTS
dockerfile
# ci/dockerfile
FROM alpine:3.22 AS base
WORKDIR /with-enc-env
ENV MISE_DATA_DIR="/mise" \
MISE_CONFIG_DIR="/mise" \
MISE_CACHE_DIR="/mise/cache" \
MISE_INSTALL_PATH="/usr/local/bin/mise" \
PATH="/mise/shims:$PATH" \
MISE_OVERRIDE_CONFIG_FILENAMES="mise.ci.toml"
RUN apk add --no-cache ca-certificates curl openssh-client \
&& rm -rf /var/cache/apk/* \
&& curl -fsSL https://mise.run | sh
RUN ln -s /run/secrets/s1 ./s1.enc.yaml || true
RUN ln -s /run/secrets/s2 ./s2.enc.yaml || true
COPY mise.ci.toml .
RUN mise install
RUN mise trust
CMD ["sh", "-c", "mise run my-task"]docker compose
secrets 파일은 이미지에 남지 않도록 시크릿으로 전달합니다.
# ci/docker-compose.yml
name: with-enc-env
services:
with-env:
build:
context: .
dockerfile: dockerfile
secrets:
- source: s1
target: /run/secrets/s1
- source: s2
target: /run/secrets/s2
environment:
MISE_SOPS_AGE_KEY: ${MISE_SOPS_AGE_KEY?required}
MISE_SOPS_AGE_RECIPIENTS: "ci-age-public-key"
secrets:
s1:
file: ./s1.enc.yaml
s2:
file: ./s2.enc.yaml만약 해당 secrets에 대한 권한이 현재 로컬 컴퓨터에도 있다면 다음과 같이 로컬에서도 실행할 수 있습니다.
#!/usr/bin/env bash
set -euxo pipefail
# age는 현재 로컬 컴퓨터의 권한으로 실행함
MISE_SOPS_AGE_RECIPIENTS="age1amv4lddeydj9jzz7shynunmrnzt8e4mt4y25uuq2qemjtjvc5uwsnkzntc" \
MISE_SOPS_AGE_KEY=$(grep '^AGE-SECRET-KEY-' "$SOPS_AGE_KEY_FILE") \
docker compose run --build --rm with-enc-envmise.ci.toml
mise의 태스크로 실행시 env에 있는 암호화된 시크릿이 주입되어 있는 격리된 환경에서 실행됩니다.
저는 mise의 sops 환경변수만 있어도 sops를 단독으로도 실행시킬 수 있도록 sops의 환경변수도 설정을 해주었습니다.
# ci/mise.ci.toml
[tools.sops]
version = "3.11.0"
[tools.age]
version = "1.2.1"
[tools.my-task]
run = '''
echo "$MY_SECRET_1"
echo "$MY_SECRET_2"
'''
[env]
SOPS_AGE_KEY = { value = "{{env.MISE_SOPS_AGE_KEY}}", redact = true, read_only = true }
SOPS_AGE_RECIPIENTS = { value = "{{env.MISE_SOPS_AGE_RECIPIENTS}}", redact = true, read_only = true }
_.file = [
{ path = "./s1.enc.yaml", redact = true, read_only = true },
{ path = "./s2.enc.yaml", redact = true, read_only = true }
]
github ci
먼저 age secrets, public key 추가가 필요합니다.
저는 github CICD_SOPS 환경에 미리 아래처럼 추가했어요.
secret: SOPS_AGE_SECRET
public: SOPS_AGE_PUBLIC
# .github/workflows/ci.yml
name: Read secret test
on:
push:
branches:
- main
paths:
- 'ci/*.enc.yaml'
- '.github/workflows/ci.yml'
- 'ci/dockerfile'
- 'ci/docker-compose.yml'
jobs:
run: test-run
runs-on: ubuntu-latest
environment: CICD_SOPS
steps:
- uses: actions/checkout@v5
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build Docker Image with Cache
uses: docker/build-push-action@v6
with:
context: ci
file: ci/dockerfile
load: true
tags: with-enc-env:latest
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Run VPS Sync
env:
MISE_SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_SECRET }}
MISE_SOPS_AGE_RECIPIENTS: ${{ vars.SOPS_AGE_PUBLIC }}
run: |
cd ci
docker compose run --rm with-enc-env