0
0
Lập trình
Admin Team
Admin Teamtechmely

Hướng Dẫn Di Chuyển Hình Ảnh Docker ECR Giữa Các Kho Chứa

Đăng vào 3 tuần trước

• 5 phút đọc

Hướng Dẫn Di Chuyển Hình Ảnh Docker ECR Giữa Các Kho Chứa (Với Tự Động Hóa)

Mỗi khi làm việc với AWS ECR, có thể bạn sẽ phải đối mặt với tình huống cần phải di chuyển hình ảnh container giữa các kho chứa ECR. Có thể là do quy ước đặt tên đã thay đổi, hoặc có một cấu trúc kho mới được giới thiệu, hoặc bạn chỉ đơn giản muốn dọn dẹp.

Dù lý do là gì, việc thực hiện điều này thủ công - từng hình ảnh một - thật chậm chạp và đau đớn. Trong các đội ngũ phát triển nhanh, bất kỳ điều gì làm chậm lại quy trình làm việc đều ảnh hưởng đến tốc độ và độ tin cậy.

Đó là lý do tại sao tôi đã xây dựng một script tự động hóa để di chuyển hình ảnh một cách nhanh chóng và an toàn. Nó sử dụng skopeo để sao chép hình ảnh giữa các kho chứa mà không cần phải kéo và đẩy chúng một cách thủ công.

🛠️ Yêu Cầu Cần Thiết

  • AWS CLI đã được cấu hình với một profile có quyền truy cập vào các kho ECR.
  • jq để phân tích cú pháp JSON.
  • skopeo để sao chép hình ảnh container.

Cài Đặt skopeo

  • macOS (Homebrew)
bash Copy
brew install skopeo
  • Ubuntu/Debian
bash Copy
sudo apt-get update
sudo apt-get -y install skopeo
  • Windows (qua WSL2 hoặc Chocolatey)

    • Nếu bạn đang sử dụng WSL2 (Ubuntu), chỉ cần làm theo hướng dẫn cài đặt cho Ubuntu.
    • Nếu bạn đang trên Windows với Chocolatey:
    bash Copy
    choco install skopeo

📜 Script Di Chuyển

Dưới đây là script mà tôi sử dụng trên macOS (cũng hoạt động với GNU/Linux và WSL, chỉ có cú pháp date là khác nhau).

Nó di chuyển tất cả hình ảnh được đẩy trong vòng N ngày qua từ kho ECR nguồn đến kho ECR đích.

👉 Lưu nó với tên migrate-ecr-images.sh và chạy nó.

bash Copy
#!/usr/bin/env bash
set -euo pipefail

# --- kiểm tra skopeo và cài đặt nếu chưa có (macOS Homebrew) ---
if ! command -v skopeo >/dev/null 2>&1; then
  echo "skopeo chưa được tìm thấy, đang cài đặt..."
  if ! command -v brew >/dev/null 2>&1; then
    echo "Homebrew là cần thiết nhưng không được tìm thấy. Vui lòng cài đặt Homebrew trước: https://brew.sh/"
    exit 1
  fi
  brew install skopeo
fi

SRC_REPO="java-micro-repo"
DST_REPO="repo"
WINDOW_DAYS=90
DRY_RUN=false

# --- phát hiện môi trường từ profile AWS ---
REGION="${AWS_REGION:-${AWS_DEFAULT_REGION:-$(aws configure get region)}}"
: "${REGION:?Region chưa được thiết lập trong môi trường hoặc cấu hình AWS}"
ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
REG_HOST="${ACCOUNT_ID}.dkr.ecr.${REGION}.amazonaws.com"

# --- trợ giúp ngày BSD/GNU ---
isi_bsd_date=false
if date -v-1d +%s >/dev/null 2>&1; then is_bsd_date=true; fi
cutoff_epoch() {
  if $is_bsd_date; then date -u -v-"${WINDOW_DAYS}"d +%s; else date -u -d "${WINDOW_DAYS} days ago" +%s; fi
}
to_epoch() {
  ts="$1"
  if $is_bsd_date; then
    ts_norm=$(printf "%s" "$ts" \
      | sed -E 's/Z$/+0000/' \
      | sed -E 's/([+-][0-9]{2}):([0-9]{2})$/\1\2/' \
      | sed -E 's/([0-9]{2}:[0-9]{2}:[0-9]{2})\.[0-9]+/\1/')
    case "$ts_norm" in *+????|*-[0-9][0-9][0-9][0-9]) : ;; *) ts_norm="${ts_norm}+0000" ;; esac
    date -j -u -f "%Y-%m-%dT%H:%M:%S%z" "$ts_norm" +%s
  else
    date -u -d "$ts" +%s
  fi
}

CUTOFF_EPOCH="$(cutoff_epoch)"

echo "Nguồn:      ${REG_HOST}/${SRC_REPO}"
echo "Điểm đến: ${REG_HOST}/${DST_REPO}"
echo "Thời gian:      trong ${WINDOW_DAYS} ngày qua"
echo "Chạy thử:     ${DRY_RUN}"
echo

# --- đảm bảo kho đích tồn tại ---
if ! aws ecr describe-repositories --repository-names "$DST_REPO" >/dev/null 2>&1; then
  echo "Tạo kho đích: $DST_REPO"
  aws ecr create-repository --repository-name "$DST_REPO" >/dev/null
  aws ecr put-image-tag-mutability --repository-name "$DST_REPO" --image-tag-mutability MUTABLE >/dev/null || true
fi

# --- lấy mật khẩu ECR cho xác thực skopeo ---
ECR_PASS="$(aws ecr get-login-password --region "$REGION")"

# --- thu thập các thẻ gần đây ---
TMP_LIST="$(mktemp)"; TMP_TAGS="$(mktemp)"
aws ecr describe-images --repository-name "$SRC_REPO" --output json \
| jq -r '.imageDetails[] | select(.imageTags!=null) | .imagePushedAt as $t | .imageTags[] | "\($t)\t\(.)"' > "$TMP_LIST"

while IFS=$'\t' read -r pushed tag; do
  epoch="$(to_epoch "$pushed")" || continue
  if [ "$epoch" -ge "$CUTOFF_EPOCH" ]; then printf "%s\n" "$tag"; fi
done < "$TMP_LIST" | sort -u > "$TMP_TAGS"

if ! [ -s "$TMP_TAGS" ]; then
  echo "Không có hình ảnh được đẩy trong vòng ${WINDOW_DAYS} ngày qua. Không có gì để làm."
  rm -f "$TMP_LIST" "$TMP_TAGS"; exit 0
fi

echo "Đã tìm thấy $(wc -l < "$TMP_TAGS" | tr -d ' ') thẻ(s):"
sed 's/^/  - /' "$TMP_TAGS"
echo

FAILED=()
while IFS= read -r TAG; do
  [ -z "$TAG" ] && continue
  SRC="docker://${REG_HOST}/${SRC_REPO}:${TAG}"
  DST="docker://${REG_HOST}/${DST_REPO}:${TAG}"
  echo "Đang sao chép ${TAG}…"
  if [ "$DRY_RUN" = true ]; then
    echo "  [chạy thử] skopeo copy --all ${SRC} -> ${DST}"
    continue
  fi
  if ! skopeo copy --all \
        --src-creds "AWS:${ECR_PASS}" \
        --dest-creds "AWS:${ECR_PASS}" \
        "$SRC" "$DST"; then
    echo "  ❌ Thất bại: ${TAG}"
    FAILED+=("$TAG")
  else
    echo "  ✅ Hoàn thành: ${TAG}"
  fi
done < "$TMP_TAGS"

rm -f "$TMP_LIST" "$TMP_TAGS"

echo
if [ "${#FAILED[@]}" -gt 0 ]; then
  echo "Hoàn thành với lỗi:"
  printf '  - %s\n' "${FAILED[@]}"
  exit 1
else
  echo "Tất cả các thẻ yêu cầu đã được sao chép thành công."
fi

⚡ Cách Hoạt Động

  1. Tìm các hình ảnh gần đây
    Sử dụng aws ecr describe-images, nó lọc các thẻ theo ngày imagePushedAt trong vòng WINDOW_DAYS.

  2. Tạo kho đích nếu chưa có
    Để bạn không phải làm điều này một cách thủ công.

  3. Sao chép hình ảnh với skopeo
    Không cần phải kéo và đẩy lại - skopeo sao chép trực tiếp giữa các kho.

  4. Hỗ trợ chế độ chạy thử
    Đặt DRY_RUN=true để xem trước những gì sẽ xảy ra.

🔧 Ví Dụ Sử Dụng

Sao chép 90 ngày hình ảnh gần đây từ java-micro-repo đến repo:

bash Copy
SRC_REPO="java-micro-repo" DST_REPO="repo" WINDOW_DAYS=90 ./migrate-ecr-images.sh

Chạy một chạy thử (không thay đổi gì):

bash Copy
DRY_RUN=true ./migrate-ecr-images.sh

✅ Tại Sao Điều Này Hữu Ích

  • Tiết kiệm hàng giờ so với việc sao chép thủ công.
  • Tự động hóa việc tạo kho nếu chưa có.
  • Tôn trọng tốc độ → cho phép bạn tập trung vào việc lập trình, không phải dọn dẹp.
  • Đa nền tảng: hoạt động trên macOS, Ubuntu và Windows.

🎯 Kết Luận

Script này đã trở thành một công cụ tiết kiệm thời gian lớn trong đội ngũ của tôi. Bất cứ khi nào chúng tôi cần đổi tên hoặc cấu trúc lại các kho chứa ECR, chỉ cần một lệnh.

Nếu bạn thường xuyên làm việc với AWS ECR, tôi khuyên bạn nên giữ script này trong bộ công cụ của bạn. 🔧

👉 Bạn đã gặp khó khăn gì trong việc di chuyển hình ảnh ECR chưa? Hãy chia sẻ suy nghĩ của bạn trong phần bình luận - tôi rất muốn biết cách bạn đã giải quyết vấn đề này.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào