#!/usr/bin/env bash ############################################################################### # [폐쇄망 안에서 실행] images/*.tar 를 컨테이너 엔진에 적재한다. # # ./bin/load-images.sh # 엔진 자동 감지 (docker 우선) # ./bin/load-images.sh docker # ./bin/load-images.sh podman # ENGINE="sudo podman" ./bin/load-images.sh # # --verify-only 적재하지 않고 tar 과 태그만 확인한다 # --force 이미 있는 태그도 다시 적재한다 # # 어떤 이미지가 있어야 하는지는 compose.yml 에서 읽고, 각 tar 이 어떤 태그를 담고 있는지는 # tar 안의 manifest.json 에서 읽는다. 별도 목록 파일을 두지 않는다. # # docker save 가 만든 OCI 아카이브는 podman load 도 그대로 읽는다. 적재 후 태그는 # 양쪽에서 같은 짧은 이름(pi-continuum:76d67d4 등)으로 해석된다. ############################################################################### . "$(dirname -- "${BASH_SOURCE[0]}")/lib.sh" VERIFY_ONLY=false FORCE=false for arg in "$@"; do case "${arg}" in --verify-only) VERIFY_ONLY=true ;; --force) FORCE=true ;; docker|podman) ENGINE_ARG="${arg}" ;; -h|--help) sed -n '2,18p' "$0"; exit 0 ;; *) die "알 수 없는 인자: ${arg}" ;; esac done resolve_engine "${ENGINE_ARG}" [ -f "${ENV_FILE}" ] && load_env log "엔진: ${ENGINE} (${ENGINE_KIND})" # ── 1. 번들의 tar 훑기 ────────────────────────────────────────────────────── TARS=() while IFS= read -r f; do TARS+=("${f}"); done < <(find "${IMAGES_DIR}" -maxdepth 1 -name '*.tar' | sort) [ "${#TARS[@]}" -gt 0 ] || die "images/ 에 tar 이 없다. 번들을 온전히 복사했는지 확인한다." log "번들 이미지 ${#TARS[@]} 개" declare -A TAG_OF_TAR=() for tar_path in "${TARS[@]}"; do file="$(basename "${tar_path}")" tags="$(tar_tags "${tar_path}" | paste -sd, -)" [ -n "${tags}" ] || die "${file} 에서 이미지 태그를 읽지 못했다 (docker save 산출물이 맞는지 확인한다)." TAG_OF_TAR["${tar_path}"]="${tags}" printf ' %-52s %s\n' "${file}" "${tags}" done # ── 2. compose 가 요구하는 이미지와 대조 ──────────────────────────────────── log "compose.yml 이 요구하는 이미지와 대조" BUNDLED="$(printf '%s\n' "${TAG_OF_TAR[@]}" | tr ',' '\n' | sort -u)" missing="" while IFS= read -r want; do [ -n "${want}" ] || continue printf '%s\n' "${BUNDLED}" | grep -qxF "${want}" || missing="${missing} ${want}" done < <(required_images) [ -z "${missing}" ] || die "번들에 없는 이미지가 있다:${missing} .env 의 APP_IMAGE / PROCESSING_IMAGE 가 tar 의 태그와 같은지 확인한다." log " 모두 있음" if [ "${VERIFY_ONLY}" = true ]; then log "--verify-only: 적재하지 않고 끝낸다." exit 0 fi # ── 3. 적재 ──────────────────────────────────────────────────────────────── loaded=0 skipped=0 for tar_path in "${TARS[@]}"; do file="$(basename "${tar_path}")" first_tag="${TAG_OF_TAR[${tar_path}]%%,*}" if [ "${FORCE}" != true ] && engine image inspect "${first_tag}" >/dev/null 2>&1; then log "건너뜀 (이미 있음): ${first_tag} — 다시 적재하려면 --force" skipped=$((skipped + 1)); continue fi log "적재: ${file} → ${first_tag}" engine load -i "${tar_path}" >/dev/null engine image inspect "${first_tag}" >/dev/null 2>&1 \ || die "${file} 적재 후에도 ${first_tag} 를 찾을 수 없다." loaded=$((loaded + 1)) done log "적재 완료: ${loaded} 개 (건너뜀 ${skipped} 개)" # ── 4. 결과 확인 ─────────────────────────────────────────────────────────── log "로컬 이미지:" while IFS= read -r tag; do [ -n "${tag}" ] || continue printf ' %-70s %s\n' "${tag}" \ "$(engine image inspect "${tag}" --format '{{.Size}} bytes / {{.Architecture}}' 2>/dev/null || echo '???')" done < <(required_images) # ── 5. 설정 파일 점검 ─────────────────────────────────────────────────────── # nginx·postgres 이미지는 순정이라 conf/ 를 bind mount 해야 뜬다. require_conf log "conf/ 설정 파일 확인" cat <