fix(dev): docker·podman 둘 다 견고화(런타임 강제지정 + podman localhost/·image-archive 로드)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -268,22 +268,48 @@ def bind_env(alias: str, conn: dict) -> dict:
|
||||
|
||||
|
||||
# ── 워크로드: 빌드 + kind load + Deployment/Service/Ingress ─────────────────────
|
||||
def _effective_image(image: str) -> str:
|
||||
"""podman 은 레지스트리(도메인) 미지정 이미지에 'localhost/' 를 붙여 저장한다 → kind load·Deployment 이름 불일치.
|
||||
podman 이고 첫 컴포넌트가 레지스트리(도메인 '.'·포트 ':' 포함 또는 'localhost')가 아니면 localhost/ 를 붙여 일치시킨다.
|
||||
docker 는 그대로(무영향). 레지스트리 지정 이미지(gitea.yakenator.io/…)는 두 런타임 모두 그대로."""
|
||||
if RUNTIME != "podman":
|
||||
return image
|
||||
first = image.split("/", 1)[0]
|
||||
if "/" not in image or ("." not in first and ":" not in first and first != "localhost"):
|
||||
return f"localhost/{image}"
|
||||
return image
|
||||
|
||||
|
||||
def _image_id(image: str) -> str:
|
||||
r = sh([RUNTIME, "image", "inspect", "--format", "{{.Id}}", image], check=False)
|
||||
return (r.stdout or "").strip() if r.returncode == 0 else ""
|
||||
|
||||
|
||||
def build_and_load(image: str, ctx_dir: str) -> str:
|
||||
import tempfile
|
||||
log(f"이미지 빌드({RUNTIME}) {image} ← {ctx_dir}")
|
||||
sh([RUNTIME, "build", "-t", image, ctx_dir], capture=False)
|
||||
log(f"kind load → 클러스터 {KIND_CLUSTER}")
|
||||
env = {"KIND_EXPERIMENTAL_PROVIDER": "podman"} if RUNTIME == "podman" else {}
|
||||
sh(["kind", "load", "docker-image", image, "--name", KIND_CLUSTER], capture=False, env=env)
|
||||
if RUNTIME == "podman":
|
||||
# podman 은 'kind load docker-image' 이름 해석이 불안정('not present locally') → save → image-archive 로 안정 로드.
|
||||
tar = os.path.join(tempfile.gettempdir(), f"yak-{sanitize(image)}.tar")
|
||||
sh([RUNTIME, "save", "-o", tar, image], capture=False)
|
||||
try:
|
||||
sh(["kind", "load", "image-archive", tar, "--name", KIND_CLUSTER],
|
||||
capture=False, env={"KIND_EXPERIMENTAL_PROVIDER": "podman"})
|
||||
finally:
|
||||
try:
|
||||
os.remove(tar)
|
||||
except OSError:
|
||||
pass
|
||||
else:
|
||||
sh(["kind", "load", "docker-image", image, "--name", KIND_CLUSTER], capture=False)
|
||||
return _image_id(image)
|
||||
|
||||
|
||||
def deploy_workload(project: str, ns: str, w: dict, src_conns: dict) -> tuple[str, bool]:
|
||||
image = w["image"].replace("${TAG}", TAG)
|
||||
# podman localhost/ 보정 — 빌드·kind load·Deployment 이미지 이름을 일치시킨다(docker 는 그대로).
|
||||
image = _effective_image(w["image"].replace("${TAG}", TAG))
|
||||
port = int(w.get("port", 8080))
|
||||
ex = w.get("expose", {}) or {}
|
||||
res = w.get("resources", {}) or {}
|
||||
|
||||
@ -406,6 +406,12 @@ PY
|
||||
# dev status 로컬 배포 상태 · dev clean 이 프로젝트 리소스만 삭제 · dev down kind 클러스터 삭제
|
||||
# 로컬 dev = CLI 로컬 완결(오프라인 반복). 같은 이미지를 push 하면 promote --to val/prod 로 그대로 직선.
|
||||
_dev_runtime() {
|
||||
# 강제 지정(YAK_DEV_RUNTIME=docker|podman) 우선 — docker·podman 둘 다 있을 때 팀/머신이 고정.
|
||||
case "${YAK_DEV_RUNTIME:-}" in
|
||||
docker) command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1 && { echo docker; return; }; echo ""; return ;;
|
||||
podman) command -v podman >/dev/null 2>&1 && podman info >/dev/null 2>&1 && { echo podman; return; }; echo ""; return ;;
|
||||
esac
|
||||
# 자동 감지 — docker 데몬 우선, 없으면 podman.
|
||||
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then echo docker; return; fi
|
||||
if command -v podman >/dev/null 2>&1 && podman info >/dev/null 2>&1; then echo podman; return; fi
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user