자체 빌드 이미지 3종(cloudnative-pg/cnpg-postgresql/etcd) + 대응 헬름 차트 도입
security-catalog 프로젝트에서 첫 실사용 자체 빌드 이미지 3종을 포팅한다 — 전부
상위 태그·베이스 OS 교체로 해소 안 되는 CVE(Go 모듈 정적 링크 또는 미수정 CRITICAL/
HIGH)를 자체 빌드(소스 컴파일 또는 SUSE BCI 재설치)로 대응한다:
- images/cloudnative-pg: CNPG operator, release-1.30 소스 컴파일 + bci-micro
- images/cnpg-postgresql: PostgreSQL 18.4, bci-base + zypper 재설치
- images/etcd: etcd v3.7.1, 소스 컴파일(x/text 강제 업그레이드) + bci-micro
함께 추가:
- manifests/helm/{cloudnative-pg,cnpg-cluster,etcd} — 위 이미지를 참조하는 카탈로그 차트
- scripts/deploy-test/*.sh, .claude/deploy-test-procedure.md — CVE 0건과 별개로
"실제로 뜨는가"를 검증하는 배포 스모크 테스트
- .claude/pitfalls.md — 자체 빌드/배포 테스트 중 실측한 함정 모음
검토 중 발견해 반영한 수정:
- cloudnative-pg 차트의 image 블록을 etcd와 동일한 registry/repository/tag 3필드+
따옴표 포맷으로 통일 — 기존 포맷(repository에 registry+repo 결합, 따옴표 없음)은
patch-catalog-tag.py 의 split 패처가 tag만 갱신하고 repository는 그대로 남기는
조용한 부분 치환을 일으켜, 향후 레지스트리 마이그레이션 시 깨진 참조를 만들 수 있었다
- cnpg-cluster 차트의 SLES 커버리지 코멘트를 최신 실측(trivy가 SLES 15.7을 정상
커버함, 2026-07-29 재측정)에 맞게 정정 — 폐기된 "측정 불가/OVAL 우회 필요" 결론이
남아있었다
- CLAUDE.md/MEMORY.md 의 "images/ 디렉토리 없음" 서술을 갱신하고, 레지스트리
마이그레이션(docker.io/wbsong111 → docker.io/paasup)·decisions/analysis 문서 이관·
리소스 프로파일 추가를 다음 작업으로 기록
이 3개 이미지는 아직 dip-catalog 자체 CI(build-image.yml)로 빌드·게이트·push 를
실행해본 적이 없다 — 현재 참조 태그는 security-catalog 쪽에서 이미 검증된 것이다.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# cloudnative-pg — CloudNativePG 오퍼레이터 자체 빌드
|
||||
|
||||
CNPG 오퍼레이터(컨트롤러) 이미지를 업스트림 소스에서 직접 컴파일한다.
|
||||
`manifests/helm/cloudnative-pg/0.29.0/custom-values.yaml`·`dip-values.yaml` 의
|
||||
`image.repository`/`image.tag` 가 이 산출물을 가리킨다.
|
||||
|
||||
security-catalog 프로젝트에서 포팅했다. 목표 정의·CVE 조사 실측·이미지 채택 결정
|
||||
근거(각각 `doc/cve-zero-pipeline.md`, `doc/analysis/cloudnative-pg-operator-cve.md`,
|
||||
`doc/decisions/0005-cloudnative-pg-operator-self-build.md`)는 security-catalog 프로젝트에
|
||||
있고 dip-catalog 에는 아직 이관되지 않았다 — 신규 자체 빌드 이미지 추가 절차 전반은
|
||||
[.claude/image-authoring.md](../../.claude/image-authoring.md) 참고.
|
||||
|
||||
> **자체 빌드는 대응 우선순위 3번이다.** 상위 태그 교체·베이스 OS 교체로 목표를
|
||||
> 만족할 수 있으면 그 쪽을 쓴다. 자체 빌드는 업스트림 서명·provenance·SBOM attestation 을
|
||||
> 잃고 재빌드 책임을 지는 선택이다.
|
||||
|
||||
## 왜 자체 빌드하나 — 그리고 왜 `cnpg-postgresql` 과 다른 방법인가
|
||||
|
||||
업스트림 `ghcr.io/cloudnative-pg/cloudnative-pg:1.30.0` 은 실효 HIGH 3건
|
||||
(`CVE-2026-39822` stdlib, `CVE-2026-56852` `golang.org/x/text`, `GHSA-hrxh-6v49-42gf`
|
||||
`google.golang.org/grpc`)으로 차단된다. 상위 태그가 없다(2026-07-30 확인, 최신 릴리스가
|
||||
여전히 `v1.30.0`). 업스트림 배포 이미지 베이스가 `gcr.io/distroless/static-debian13`
|
||||
(OS 패키지 사실상 0개)라 **베이스 OS 를 바꾸는 것만으로는 고쳐지지 않는다** — CVE 는
|
||||
바이너리에 정적 링크된 Go 모듈 버전이 원인이다. 자체 빌드(소스 컴파일)만 유효한 대응이다.
|
||||
|
||||
`cnpg-postgresql`(OS 베이스 교체 + zypper 패치)과 성격이 다르지만, **오케스트레이션은
|
||||
동일한 [scripts/build/build-hardened-image.sh](../../scripts/build/build-hardened-image.sh)
|
||||
하나를 공유한다.** 이 이미지가 그 스크립트의 계약(`build.env` 가 `DOCKERFILE`·`TARGET`·
|
||||
`BUILD_ARGS`·`APP_VERSION` 선언, `verify.sh` 가 `VERIFY-OK` 로 종료)만 지키면, 이미지
|
||||
종류(OS 패키지 설치형 vs 소스 컴파일형)는 스크립트가 몰라도 된다 — 근거는
|
||||
[.claude/image-authoring.md](../../.claude/image-authoring.md) 참고.
|
||||
|
||||
## 소스·버전 관리
|
||||
|
||||
| 항목 | 값 |
|
||||
| --- | --- |
|
||||
| 소스 | `https://github.com/cloudnative-pg/cloudnative-pg.git` |
|
||||
| pinned commit | `source.build.env` 의 `SOURCE_COMMIT` (release-1.30 브랜치) |
|
||||
| 빌더 | 공식 `golang` 이미지 (`source.build.env` 의 `GO_BUILDER_TAG`, go.mod 요구 버전과 일치) |
|
||||
| 최종 베이스 | `registry.suse.com/bci/bci-micro:15.7` — security-catalog 는 SUSE BCI 하나만 쓰기로 결정했다(ADR 미이관); 업스트림의 distroless 대신 여기 적용 |
|
||||
|
||||
빌더 스테이지(Go 컴파일)는 공식 `golang` 이미지를 그대로 쓴다 — 최종 이미지에 남는 것이
|
||||
아니라 컴파일 산출물만 최종 스테이지로 넘어오므로 스캔·정책 대상이 아니다. `bci-micro`
|
||||
는 SUSE BCI 중 가장 가벼운 변종이지만 `bci-base` 와 달리 `nonroot`(uid 65532) 계정이
|
||||
미리 없어 `source.Dockerfile` 이 직접 만든다(`/etc/passwd`·`/etc/group` 에 추가).
|
||||
|
||||
`SOURCE_COMMIT` 은 **자동 추적하지 않는다.** `cnpg-postgresql` 의 PGDG 버전처럼 사람이
|
||||
업스트림 `release-1.30` 브랜치(또는 그다음 패치 릴리스가 나오면 그 태그)를 보고
|
||||
`source.build.env` 를 고쳐 PR 을 여는 것 자체가 갱신 트리거다.
|
||||
|
||||
**권장 점검 주기**: 카탈로그 게이트가 이 이미지의 차단 CVE 를 다시 보고할 때, 또는
|
||||
업스트림이 `v1.30.1`(혹은 그 이상) 을 릴리스했을 때 — 릴리스가 나오면 그쪽으로 갈아타는
|
||||
것(대응 우선순위 a)이 이 자체 빌드를 유지하는 것보다 항상 우선이다.
|
||||
|
||||
## 빌드
|
||||
|
||||
```sh
|
||||
# 로컬 빌드 (push 없음)
|
||||
IMAGE=cloudnative-pg BASE_OS=source bash scripts/build/build-hardened-image.sh /tmp/out
|
||||
|
||||
# 레지스트리에 push 까지 (현재 실제 배포 이미지도 이 네임스페이스에 있다)
|
||||
IMAGE=cloudnative-pg BASE_OS=source REGISTRY=docker.io/wbsong111 \
|
||||
bash scripts/build/build-hardened-image.sh /tmp/out
|
||||
```
|
||||
|
||||
수행 순서: **빌드 → 기능 검증(`verify.sh`) → SBOM → 전 심각도 스캔 → 게이트 판정.**
|
||||
dip-catalog 의 `scan-sbom.sh` 는 커버리지 자가진단(`CoverageProbe`)이 없다는 점에
|
||||
유의한다 — `doc/sbom-pipeline.md` 참고. `verify.sh` 는 `manager version` 출력에 pinned
|
||||
commit 이 실제로 반영됐는지(ldflags 주입 확인), 이미지 `Config.User` 가
|
||||
`65532:65532`(nonroot)인지, `--help` 가 정상 종료하는지를 확인한다 — 실제 컨트롤러
|
||||
기동(k8s API 필요)은 이 스모크 테스트 범위 밖이며, dev 클러스터 배포 테스트
|
||||
(`.claude/deploy-test-procedure.md`)가 담당한다.
|
||||
|
||||
### 파일 구성
|
||||
|
||||
| 파일 | 역할 |
|
||||
| --- | --- |
|
||||
| `source.Dockerfile` | 빌드 정의 — 소스 컴파일(builder 스테이지) + SUSE BCI(`bci-micro`) 패키징(final 스테이지) |
|
||||
| `source.build.env` | pinned commit·버전·빌더 이미지 태그. `BUILD_ARGS` 에 나열한 이름만 `--build-arg` 로 전달된다 |
|
||||
| `verify.sh` | 기능 검증. 호스트에서 bash 로 실행되며 직접 `docker run --entrypoint /manager` 를 호출한다(게스트 스크립트 주입 방식보다 상위 호환 — 최종 이미지에 셸이 없는 경우에도 그대로 동작한다) |
|
||||
|
||||
베이스 변종이 하나뿐이라 파일명이 `source.*` 로 고정돼 있다 — `cnpg-postgresql` 처럼
|
||||
변종이 늘면 `<variant>.Dockerfile`/`<variant>.build.env` 로 분기한다.
|
||||
|
||||
### 태그
|
||||
|
||||
```
|
||||
docker.io/wbsong111/cloudnative-pg:1.30.0-security-hardened-20260730
|
||||
└ app ─┘└ 슬러그 ┘└ 하드닝 ┘└ 빌드일 ┘
|
||||
```
|
||||
|
||||
이 태그는 security-catalog 프로젝트에서 이미 빌드·게이트 PASS·push 된 실제 이미지다.
|
||||
dip-catalog 는 이를 그대로 재사용한다 — 재빌드·재푸시 여부는 `MEMORY.md` 참고.
|
||||
@@ -0,0 +1,11 @@
|
||||
# build-image.yml 이 읽는 카탈로그 반영 메타데이터. 빌드 정의(<variant>.build.env)와는
|
||||
# 별개다 — 이건 "이 이미지가 어느 차트의 어느 필드를 가리키는가" 만 담는다.
|
||||
|
||||
CHART_DIRS="manifests/helm/cloudnative-pg/0.29.0"
|
||||
|
||||
# 태그 표기 스타일 — imageName(단일 필드 문자열) | split(registry/repository/tag 분리)
|
||||
TAG_STYLE=split
|
||||
TAG_BLOCK=image
|
||||
|
||||
# base_os 입력을 안 주면 쓸 기본 변종 (images/<image>/<DEFAULT_BASE_OS>.build.env)
|
||||
DEFAULT_BASE_OS=source
|
||||
@@ -0,0 +1,80 @@
|
||||
# CloudNativePG 오퍼레이터 — 업스트림 소스를 pinned commit 으로 직접 컴파일한다.
|
||||
#
|
||||
# 업스트림(https://github.com/cloudnative-pg/cloudnative-pg)의 Dockerfile 은 이미 goreleaser
|
||||
# 로 빌드된 바이너리(`dist/manager/manager_<arch>`)를 COPY 만 한다 — 컴파일 자체는 이 Dockerfile
|
||||
# 밖(Makefile `docker-build` → goreleaser)에서 일어난다. 우리는 그 컴파일 단계를 Dockerfile
|
||||
# 안으로 가져와 `go build` 로 직접 재현한다. `cnpg-postgresql/suse.Dockerfile` 이 "업스트림
|
||||
# Dockerfile 을 다른 배포판으로 이식"한 것이라면, 이건 "업스트림이 Dockerfile 밖에서 하던
|
||||
# 빌드를 Dockerfile 안으로 흡수"한 것이다.
|
||||
#
|
||||
# 왜 자체 빌드인가 — cloudnative-pg:1.30.0 이 게이트에서 차단하는 CVE 3건(stdlib·x/text·grpc)
|
||||
# 은 OS 패키지가 아니라 바이너리에 정적 링크된 Go 모듈 버전이 원인이다. 배포 이미지 베이스가
|
||||
# distroless(OS 패키지 사실상 0개)라 베이스 OS 교체로는 고칠 수 없다 — 소스를 다시 컴파일해야
|
||||
# 한다. 세 CVE 모두 업스트림 release-1.30 브랜치에 이미 백포트돼 있다(SOURCE_COMMIT 이 그
|
||||
# 커밋을 가리킨다) — 근거: doc/analysis/cloudnative-pg-operator-cve.md
|
||||
#
|
||||
# 업스트림과의 대응 관계 (release-1.30 브랜치 Dockerfile 기준)
|
||||
# go build (Makefile build-manager) → 동일 (ldflags 까지 그대로)
|
||||
# goreleaser 멀티아치(manager_amd64/arm64) → 단일 아키텍처(linux/amd64)만 직접 COPY.
|
||||
# 심볼릭 링크 대신 같은 바이너리를 두 경로에 COPY (아래 "실측으로 드러난 필수 조건" 참고)
|
||||
# distroless base(gcr.io/distroless/static-debian13:nonroot) → SUSE BCI(bci-micro)로 교체.
|
||||
# 카탈로그는 SUSE BCI 하나만 쓴다(decisions/0001) — 최종 런타임 이미지에도 동일하게 적용한다.
|
||||
# builder 스테이지(Go 컴파일)는 공식 golang 이미지를 그대로 쓴다 — 컴파일 결과물에는
|
||||
# 영향이 없고, 최종 이미지에만 남는 게 무엇인지가 스캔·정책 대상이다
|
||||
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_BUILDER_TAG=1.26.5-trixie
|
||||
# FROM 에서 쓰는 ARG 는 반드시 첫 FROM 이전(전역 스코프)에 선언해야 한다 — 스테이지 안에서
|
||||
# 선언하면(예: 이전엔 builder 스테이지 RUN 다음에 둠) 그 스테이지 지역 변수가 되어 다음
|
||||
# FROM 의 이미지명 해석에 쓰이지 않는다(실측: "FROM argument 'RUNTIME_BASE' is not
|
||||
# declared" 경고와 함께 빈 이미지명 에러 발생).
|
||||
ARG RUNTIME_BASE=registry.suse.com/bci/bci-micro:15.7
|
||||
|
||||
# 호스트 네이티브 아키텍처로 빌더를 띄운다. Go 크로스컴파일은 에뮬레이션이 필요 없으므로
|
||||
# --platform=$BUILDPLATFORM 로 고정해 에뮬레이션 오버헤드를 피한다(로컬 arm64 Docker 데스크톱
|
||||
# 에서 linux/amd64 결과물을 만들 때 특히 중요).
|
||||
FROM --platform=$BUILDPLATFORM golang:${GO_BUILDER_TAG} AS builder
|
||||
ARG TARGETARCH
|
||||
ARG SOURCE_COMMIT
|
||||
ARG APP_VERSION
|
||||
WORKDIR /src
|
||||
|
||||
# BuildKit 의 git context 지원 — tarball+checksum 관리 없이 git 자체가 커밋 무결성을 보장한다.
|
||||
ADD https://github.com/cloudnative-pg/cloudnative-pg.git#${SOURCE_COMMIT} /src
|
||||
|
||||
# 업스트림 Makefile 의 LDFLAGS·.goreleaser.yml 의 build 설정을 그대로 재현한다.
|
||||
# (release-1.30 기준 go.mod: go 1.26.5, google.golang.org/grpc v1.82.1, golang.org/x/text v0.39.0)
|
||||
RUN --mount=type=cache,target=/root/go/pkg/mod \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
set -eux; \
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -trimpath \
|
||||
-ldflags "-s -w \
|
||||
-X github.com/cloudnative-pg/cloudnative-pg/pkg/versions.buildVersion=${APP_VERSION} \
|
||||
-X github.com/cloudnative-pg/cloudnative-pg/pkg/versions.buildCommit=${SOURCE_COMMIT} \
|
||||
-X github.com/cloudnative-pg/cloudnative-pg/pkg/versions.buildDate=$(date -u +%Y-%m-%d)" \
|
||||
-o /out/manager ./cmd/manager
|
||||
|
||||
FROM ${RUNTIME_BASE} AS final
|
||||
WORKDIR /
|
||||
|
||||
# bci-micro 는 root 만 있고 65532 사용자가 없다(distroless 의 nonroot 변종과 달리 nonroot
|
||||
# 계정을 미리 만들어두지 않는다) — 직접 만든다. bci-micro 에 bash·coreutils 는 있다
|
||||
# (zypper·rpm 은 없음 — "micro" 는 패키지 매니저가 빠진 것이지 셸까지 없는 건 아니다).
|
||||
RUN set -eux; \
|
||||
echo 'nonroot:x:65532:65532:nonroot:/home/nonroot:/bin/false' >> /etc/passwd; \
|
||||
echo 'nonroot:x:65532:' >> /etc/group; \
|
||||
mkdir -p /home/nonroot; \
|
||||
chown 65532:65532 /home/nonroot
|
||||
|
||||
# 실측으로 드러난 필수 조건: 오퍼레이터는 `operator/manager_<GOARCH>` 를 런타임에 glob 해서
|
||||
# "가용 아키텍처" 목록을 만든다(pkg/utils/discovery.go DetectAvailableArchitectures) — 이
|
||||
# 목록이 비어 있으면 Cluster 리컨실이 "invalid architecture: amd64" 로 실패한다(배포
|
||||
# 테스트 2026-07-30 에서 재현). 업스트림은 멀티아치 심볼릭 링크로 이걸 만들지만, 우리는
|
||||
# 단일 아키텍처만 다루므로 같은 바이너리를 두 경로에 COPY 해 같은 효과를 낸다.
|
||||
COPY --from=builder /out/manager /manager
|
||||
COPY --from=builder /out/manager /operator/manager_amd64
|
||||
COPY --from=builder /src/licenses /licenses
|
||||
COPY --from=builder /src/LICENSE /licenses/LICENSE
|
||||
USER 65532:65532
|
||||
ENTRYPOINT ["/manager"]
|
||||
@@ -0,0 +1,32 @@
|
||||
# CloudNativePG 오퍼레이터 — 소스 컴파일형 자체 빌드 (유일한 변종)
|
||||
#
|
||||
# build-hardened-image.sh 가 source 한다. BUILD_ARGS 에 나열한 이름만 --build-arg 로 넘어간다.
|
||||
# 이 이미지는 소스를 직접 컴파일하므로 "베이스 OS" 선택지가 없다 — BASE_OS=source 로 호출한다:
|
||||
# IMAGE=cloudnative-pg BASE_OS=source bash scripts/build/build-hardened-image.sh <OUT_DIR>
|
||||
#
|
||||
# 왜 자체 빌드하는가·CVE 근거 → doc/analysis/cloudnative-pg-operator-cve.md
|
||||
# 결정 → doc/decisions/0004-cloudnative-pg-operator-self-build.md
|
||||
|
||||
DOCKERFILE=source.Dockerfile
|
||||
TARGET=final
|
||||
TAG_SLUG=security
|
||||
|
||||
# build-hardened-image.sh 가 태그·verify.sh 전달용으로 요구하는 범용 필수값.
|
||||
# 스톡 1.30.0 과는 태그 슬러그(TAG_SLUG=security)로 구분되므로 버전 문자열 자체는 그대로 둔다.
|
||||
APP_VERSION=1.30.0
|
||||
|
||||
# release-1.30 브랜치 HEAD, 2026-07-30 확인 — CVE-2026-39822(stdlib)·CVE-2026-56852(x/text)·
|
||||
# GHSA-hrxh-6v49-42gf(grpc) 가 모두 이 커밋에 백포트돼 있다. 갱신할 때는 release-1.30 의
|
||||
# 최신 커밋으로 사람이 다시 고른다(자동 추적하지 않음 — cnpg-postgresql 의 PGDG 버전처럼
|
||||
# 사람이 트리거해야 하는 갱신 축).
|
||||
SOURCE_COMMIT=4463551204bc5cdb5af05b2c60a2d6b58ce9ff6a
|
||||
|
||||
# go.mod 의 `go 1.26.5` 요구를 만족하는 공식 golang 이미지 태그. 이 이미지는 builder
|
||||
# 스테이지에서만 쓰이고 최종 이미지에는 남지 않는다.
|
||||
GO_BUILDER_TAG=1.26.5-trixie
|
||||
|
||||
# 최종 런타임 베이스 — 카탈로그는 SUSE BCI 하나만 쓴다(decisions/0001). bci-base 대신
|
||||
# 가장 가벼운 bci-micro 를 쓴다(패키지 매니저 없음, bash·coreutils 는 있음).
|
||||
RUNTIME_BASE=registry.suse.com/bci/bci-micro:15.7
|
||||
|
||||
BUILD_ARGS="SOURCE_COMMIT GO_BUILDER_TAG APP_VERSION RUNTIME_BASE"
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
# cloudnative-pg 오퍼레이터 이미지 기능 검증 — 호스트에서 bash 로 실행된다
|
||||
# (build-hardened-image.sh 가 `env TAG=... PLATFORM=... SOURCE_COMMIT=... bash verify.sh`
|
||||
# 형태로 호출한다).
|
||||
#
|
||||
# cnpg-postgresql/verify.sh 와 달리 게스트 셸을 쓰지 않는다 — 최종 이미지 베이스가
|
||||
# gcr.io/distroless/static-debian13:nonroot 라 셸이 아예 없다(`/bin/sh` 없음, 업스트림
|
||||
# Dockerfile 도 이 사실을 자기 빌더 스테이지 주석에 명시한다). 대신 `--entrypoint /manager`
|
||||
# 로 바이너리를 직접 실행해 검증한다 — 실제 컨트롤러 기동(k8s API 필요)은 이 스모크
|
||||
# 테스트 범위 밖이며, dev 클러스터 배포 테스트가 담당한다.
|
||||
#
|
||||
# 마지막 줄에 VERIFY-OK 를 출력하면 통과다. build-hardened-image.sh 가 그것으로 판정한다.
|
||||
set -e
|
||||
|
||||
TAG="${TAG:?TAG 환경변수가 필요하다}"
|
||||
PLATFORM="${PLATFORM:-linux/amd64}"
|
||||
SOURCE_COMMIT="${SOURCE_COMMIT:?SOURCE_COMMIT 환경변수가 필요하다 (build-hardened-image.sh 가 build.env 에서 전달)}"
|
||||
SHORT_COMMIT="${SOURCE_COMMIT:0:8}"
|
||||
|
||||
echo "== manager version =="
|
||||
OUT="$(docker run --rm --platform "$PLATFORM" --entrypoint /manager "$TAG" version)"
|
||||
echo " $OUT"
|
||||
case "$OUT" in
|
||||
*"$SHORT_COMMIT"*) ;;
|
||||
*) echo "FAIL: version 출력에 pinned commit($SHORT_COMMIT) 이 없다 — ldflags 주입 확인 필요"; exit 1 ;;
|
||||
esac
|
||||
|
||||
echo "== 실행 사용자 (nonroot, 이미지 메타데이터) =="
|
||||
# 셸이 없어 컨테이너 안에서 id 를 실행할 수 없다 — 이미지가 선언한 기본 User 를 확인한다.
|
||||
# 위 version 실행 자체가 이 기본 사용자로 이미 성공했다(권한 문제였다면 여기까지 오지 못한다).
|
||||
USER_CFG="$(docker inspect --format '{{.Config.User}}' "$TAG")"
|
||||
[ "$USER_CFG" = "65532:65532" ] || { echo "FAIL: 이미지 Config.User 가 65532:65532 가 아니다 (실제: $USER_CFG)"; exit 1; }
|
||||
echo " Config.User=$USER_CFG"
|
||||
|
||||
echo "== --help 스모크 (k8s API 없이 도는 유일한 확인 범위) =="
|
||||
docker run --rm --platform "$PLATFORM" --entrypoint /manager "$TAG" --help >/dev/null
|
||||
echo " /manager --help 종료 코드 0"
|
||||
|
||||
echo "VERIFY-OK"
|
||||
Reference in New Issue
Block a user