From bd2932f132ba85a9934b83f1d31173f1b69d7e80 Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 16 Sep 2025 08:15:10 +0000 Subject: [PATCH 1/6] feat: add script for adding container tag, and use lightweight alpine linux image --- Dockerfile | 52 +++------------------ script/add-container-tag | 98 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 45 deletions(-) create mode 100755 script/add-container-tag diff --git a/Dockerfile b/Dockerfile index 8a61a6d..208200b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,27 +1,16 @@ -FROM node:24.0.2-slim +FROM alpine:3.22 -ENV DEBIAN_FRONTEND noninteractive -ENV PNPM_VERSION 10.11.0 -ENV TURBO_VERSION 2.5.3 -ENV TSX_VERSION 4.19.4 -ENV TS_NODE 10.9.2 -ENV SWC_CORE 1.11.24 -ENV AWS_CLI 2.27.19 -ENV BUILDKIT_VERSION 0.21.1 +ENV AWS_CLI=2.27.19 -RUN apt-get update -y \ - && apt-get install -y --no-install-recommends \ - software-properties-common \ +RUN apk update \ + && apk add --no-cache \ ca-certificates \ - build-essential \ + build-base \ wget \ jq \ patch \ - python3 \ curl \ - unzip \ - git \ - && apt-get clean + unzip # install awscli v2. see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI}.zip" -o /tmp/awscliv2.zip \ @@ -30,36 +19,9 @@ RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI}.zip" - && rm /tmp/awscliv2.zip \ && rm -rf /tmp/aws -# install node packages -RUN npm i -g pnpm@${PNPM_VERSION} turbo@${TURBO_VERSION} tsx@${TSX_VERSION} ts-node@${TS_NODE} @swc/core@${SWC_CORE} - -RUN curl -L "https://github.com/moby/buildkit/releases/download/v${BUILDKIT_VERSION}/buildkit-v${BUILDKIT_VERSION}.linux-amd64.tar.gz" -o /tmp/buildkit.tar.gz \ - && mkdir -p /tmp/buildkit \ - && tar -C /tmp/buildkit -xzf /tmp/buildkit.tar.gz \ - && mv /tmp/buildkit/bin/buildctl /usr/bin/buildctl \ - && chmod a+x /usr/bin/buildctl \ - && rm -rf /tmp/buildkit \ - && rm /tmp/buildkit.tar.gz - -# install kubectl -RUN curl -L "https://dl.k8s.io/release/v1.30.13/bin/linux/amd64/kubectl" -o "/usr/bin/kubectl-v1.30" \ - && curl -L "https://dl.k8s.io/release/v1.31.9/bin/linux/amd64/kubectl" -o "/usr/bin/kubectl-v1.31" \ - && curl -L "https://dl.k8s.io/release/v1.32.5/bin/linux/amd64/kubectl" -o "/usr/bin/kubectl-v1.32" \ - && chmod a+x /usr/bin/kubectl* - -RUN ln -s /usr/bin/kubectl-v1.32 /usr/bin/kubectl - -# install golang -COPY --from=golang:1.22.0 /usr/local/go/ /usr/local/go/ -ENV GOPATH /go -ENV PATH $GOPATH/bin:/usr/local/go/bin:/usr/bin:${PATH} - # install amazon-ecr-credential-helper RUN curl -L "https://amazon-ecr-credential-helper-releases.s3.us-east-2.amazonaws.com/0.9.1/linux-amd64/docker-credential-ecr-login" -o "/usr/bin/docker-credential-ecr-login" \ && chmod a+x /usr/bin/docker-credential-ecr-login -RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH" -# install uv -# https://docs.astral.sh/uv/reference/installer/#unmanaged-installations -RUN curl -LsSf https://astral.sh/uv/install.sh | env UV_UNMANAGED_INSTALL="/usr/bin" sh \ No newline at end of file +COPY script /script \ No newline at end of file diff --git a/script/add-container-tag b/script/add-container-tag new file mode 100755 index 0000000..ed2b38b --- /dev/null +++ b/script/add-container-tag @@ -0,0 +1,98 @@ +#!/bin/sh -e + +add_docker_tag() { + local IMAGE_PATH="$1" + local NEW_TAG="$2" + local USERNAME="$3" + local PASSWORD="$4" + + local REGISTRY_URL="https://$(echo $IMAGE_PATH | cut -d'/' -f1)" + local REPO_PATH=$(echo $IMAGE_PATH | cut -d'/' -f2- | cut -d':' -f1) + local CURRENT_TAG=$(echo $IMAGE_PATH | cut -d':' -f2) + + # 붙일 태그가 없으면 에러 + if [[ -z "$CURRENT_TAG" ]]; then + echo "Error: Current tag not found in image path '$IMAGE_PATH'" + return 1 + fi + + if [[ -z "$NEW_TAG" ]]; then + echo "Error: New tag is empty" + return 1 + fi + + echo "Start tagging: $REGISTRY_URL/$REPO_PATH, $CURRENT_TAG -> $NEW_TAG" + + # 인증 헤더 설정 + local AUTH_HEADER="" + if [[ -n "$USERNAME" && -n "$PASSWORD" ]]; then + AUTH_HEADER="Authorization: Basic $(echo -n "$USERNAME:$PASSWORD" | base64)" + fi + + local MANIFEST=$(curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "$AUTH_HEADER" "$REGISTRY_URL/v2/$REPO_PATH/manifests/$CURRENT_TAG") + + if [[ $? -ne 0 ]]; then + echo "Error: Failed to fetch manifest for tag '$CURRENT_TAG'" + return 1 + fi + + echo "Adding new tag '$NEW_TAG'..." + local RESULT=$(curl -s -X PUT \ + -H "Content-Type: application/vnd.docker.distribution.manifest.v2+json" \ + -H "$AUTH_HEADER" \ + -d "$MANIFEST" \ + "$REGISTRY_URL/v2/$REPO_PATH/manifests/$NEW_TAG") + + if [[ $? -ne 0 ]]; then + echo "Error: Failed to add tag '$NEW_TAG': $RESULT" + return 1 + fi + + echo "Successfully added tag '$NEW_TAG' to $IMAGE_PATH" +} + + +TAG_TO_ADD=$1 +DOCKER_REGISTRY=$2 +TOKEN=$3 + +if [ -z "$TAG_TO_ADD" ] || [ -z "$DOCKER_REGISTRY" ]; then + echo "Usage: echo -e 'image1\\nimage2\\nimage3' | $0 [token]" + exit 1 +fi + +# stdin에서 이미지 목록을 배열로 읽기 +mapfile -t IMAGES + +if [ ${#IMAGES[@]} -eq 0 ]; then + echo "Error: No images found" + exit 1 +fi + +# if ECR +if [[ "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then + TOKEN=$(aws ecr get-login-password --region us-east-1) +fi + +if [[ -z "$TOKEN" && "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then + echo "Token is empty" + exit 1 +fi + +for IMAGE in "${IMAGES[@]}"; do + if [[ $IMAGE != *"$DOCKER_REGISTRY"* ]]; then + echo "Skipping: $IMAGE (not from $DOCKER_REGISTRY)" + continue + fi + + if [[ $IMAGE == *".dkr.ecr."* ]]; then + USERNAME="AWS" + else + USERNAME=$(echo "$IMAGE" | cut -d'/' -f1) + fi + + echo "add_docker_tag $IMAGE $TAG_TO_ADD $USERNAME ****" + add_docker_tag "$IMAGE" "$TAG_TO_ADD" "$USERNAME" "$TOKEN" & +done +wait + From 09345c000586156360d475ce7b2dc6ec811c1b8c Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 16 Sep 2025 08:38:18 +0000 Subject: [PATCH 2/6] feat: update workflow to support containerize new image --- .github/workflows/docker-publish.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml index c978933..270df1a 100644 --- a/.github/workflows/docker-publish.yml +++ b/.github/workflows/docker-publish.yml @@ -9,11 +9,11 @@ on: #schedule: # - cron: '35 11 * * *' push: - branches: [ main ] + branches: [ main, container-tag-slim ] # Publish semver tags as releases. tags: [ 'v*.*.*' ] pull_request: - branches: [ main ] + branches: [ main, container-tag-slim ] env: # Use docker.io for Docker Hub if empty From 9750125b412060b695ce9a4a7f36c5e6a88b13c9 Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 16 Sep 2025 10:36:10 +0000 Subject: [PATCH 3/6] fix: update AWS CLI version to 2.27.25-r0 in Dockerfile --- Dockerfile | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/Dockerfile b/Dockerfile index 208200b..cb1e691 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM alpine:3.22 -ENV AWS_CLI=2.27.19 +ENV AWS_CLI=2.27.25-r0 RUN apk update \ && apk add --no-cache \ @@ -10,18 +10,7 @@ RUN apk update \ jq \ patch \ curl \ - unzip + unzip \ + aws-cli=${AWS_CLI} -# install awscli v2. see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html -RUN curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64-${AWS_CLI}.zip" -o /tmp/awscliv2.zip \ - && unzip /tmp/awscliv2.zip -d /tmp/ \ - && /tmp/aws/install \ - && rm /tmp/awscliv2.zip \ - && rm -rf /tmp/aws - -# install amazon-ecr-credential-helper -RUN curl -L "https://amazon-ecr-credential-helper-releases.s3.us-east-2.amazonaws.com/0.9.1/linux-amd64/docker-credential-ecr-login" -o "/usr/bin/docker-credential-ecr-login" \ - && chmod a+x /usr/bin/docker-credential-ecr-login - - -COPY script /script \ No newline at end of file +COPY script /script From bc92963aae9b38ee59b6556b76b693973f08bd0c Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 16 Sep 2025 11:53:52 +0000 Subject: [PATCH 4/6] add bash --- Dockerfile | 1 + script/add-container-tag | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index cb1e691..1be315d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,7 @@ RUN apk update \ && apk add --no-cache \ ca-certificates \ build-base \ + bash \ wget \ jq \ patch \ diff --git a/script/add-container-tag b/script/add-container-tag index ed2b38b..90368b6 100755 --- a/script/add-container-tag +++ b/script/add-container-tag @@ -1,4 +1,4 @@ -#!/bin/sh -e +#!/bin/bash -e add_docker_tag() { local IMAGE_PATH="$1" From 6c689401955f07a1c8b89954129a1d770c93db88 Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 16 Sep 2025 12:04:13 +0000 Subject: [PATCH 5/6] fix script --- script/add-container-tag | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/script/add-container-tag b/script/add-container-tag index 90368b6..4bb212b 100755 --- a/script/add-container-tag +++ b/script/add-container-tag @@ -61,14 +61,6 @@ if [ -z "$TAG_TO_ADD" ] || [ -z "$DOCKER_REGISTRY" ]; then exit 1 fi -# stdin에서 이미지 목록을 배열로 읽기 -mapfile -t IMAGES - -if [ ${#IMAGES[@]} -eq 0 ]; then - echo "Error: No images found" - exit 1 -fi - # if ECR if [[ "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then TOKEN=$(aws ecr get-login-password --region us-east-1) @@ -79,6 +71,17 @@ if [[ -z "$TOKEN" && "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then exit 1 fi +# stdin에서 이미지 목록을 배열로 읽기 +IMAGES=() +while IFS= read -r line; do + IMAGES+=("$line") +done + +if [ ${#IMAGES[@]} -eq 0 ]; then + echo "Error: No images found" + exit 1 +fi + for IMAGE in "${IMAGES[@]}"; do if [[ $IMAGE != *"$DOCKER_REGISTRY"* ]]; then echo "Skipping: $IMAGE (not from $DOCKER_REGISTRY)" From 1269d54c3b2cfa7ade459c807766077d23f933a0 Mon Sep 17 00:00:00 2001 From: Jiyeon Baek Date: Tue, 23 Sep 2025 02:43:43 +0000 Subject: [PATCH 6/6] fix: update Dockerfile to include skopeo and refactor add-container-tag script for improved authentication handling --- Dockerfile | 4 ++- script/add-container-tag | 65 +++++++++++++++++----------------------- 2 files changed, 31 insertions(+), 38 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1be315d..a79c5f6 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,8 @@ RUN apk update \ patch \ curl \ unzip \ - aws-cli=${AWS_CLI} + aws-cli=${AWS_CLI} \ + # docker cli tool + skopeo COPY script /script diff --git a/script/add-container-tag b/script/add-container-tag index 4bb212b..bc121b3 100755 --- a/script/add-container-tag +++ b/script/add-container-tag @@ -6,7 +6,7 @@ add_docker_tag() { local USERNAME="$3" local PASSWORD="$4" - local REGISTRY_URL="https://$(echo $IMAGE_PATH | cut -d'/' -f1)" + local REGISTRY_URL=$(echo $IMAGE_PATH | cut -d'/' -f1) local REPO_PATH=$(echo $IMAGE_PATH | cut -d'/' -f2- | cut -d':' -f1) local CURRENT_TAG=$(echo $IMAGE_PATH | cut -d':' -f2) @@ -23,32 +23,24 @@ add_docker_tag() { echo "Start tagging: $REGISTRY_URL/$REPO_PATH, $CURRENT_TAG -> $NEW_TAG" - # 인증 헤더 설정 - local AUTH_HEADER="" + local SOURCE_IMAGE="docker://$REGISTRY_URL/$REPO_PATH:$CURRENT_TAG" + local DEST_IMAGE="docker://$REGISTRY_URL/$REPO_PATH:$NEW_TAG" + + local AUTH_OPTS="" if [[ -n "$USERNAME" && -n "$PASSWORD" ]]; then - AUTH_HEADER="Authorization: Basic $(echo -n "$USERNAME:$PASSWORD" | base64)" + echo "Using provided credentials for authentication: user=$USERNAME password=$PASSWORD" + AUTH_OPTS="--src-creds $USERNAME:$PASSWORD --dest-creds $USERNAME:$PASSWORD" fi - local MANIFEST=$(curl -s -H "Accept: application/vnd.docker.distribution.manifest.v2+json" -H "$AUTH_HEADER" "$REGISTRY_URL/v2/$REPO_PATH/manifests/$CURRENT_TAG") - - if [[ $? -ne 0 ]]; then - echo "Error: Failed to fetch manifest for tag '$CURRENT_TAG'" - return 1 - fi - echo "Adding new tag '$NEW_TAG'..." - local RESULT=$(curl -s -X PUT \ - -H "Content-Type: application/vnd.docker.distribution.manifest.v2+json" \ - -H "$AUTH_HEADER" \ - -d "$MANIFEST" \ - "$REGISTRY_URL/v2/$REPO_PATH/manifests/$NEW_TAG") - - if [[ $? -ne 0 ]]; then - echo "Error: Failed to add tag '$NEW_TAG': $RESULT" + + if skopeo copy $AUTH_OPTS "$SOURCE_IMAGE" "$DEST_IMAGE"; then + echo "Successfully added tag '$NEW_TAG' to $IMAGE_PATH" + return 0 + else + echo "Error: Failed to add tag '$NEW_TAG'" return 1 fi - - echo "Successfully added tag '$NEW_TAG' to $IMAGE_PATH" } @@ -63,20 +55,25 @@ fi # if ECR if [[ "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then - TOKEN=$(aws ecr get-login-password --region us-east-1) + USERNAME="AWS" + PASSWORD=$(aws ecr get-login-password --region us-east-1) +else + USERNAME=$(echo "$TOKEN" | base64 -d | cut -d: -f1) + PASSWORD=$(echo "$TOKEN" | base64 -d | cut -d: -f2) fi -if [[ -z "$TOKEN" && "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then - echo "Token is empty" +if [[ -z "$PASSWORD" && "$DOCKER_REGISTRY" == *".dkr.ecr."* ]]; then + echo "Error: ECR token is required for ECR registry" exit 1 fi -# stdin에서 이미지 목록을 배열로 읽기 -IMAGES=() -while IFS= read -r line; do - IMAGES+=("$line") -done +if [[ -z "$TOKEN" ]]; then + echo "Error: Token is required for non-ECR registry" + exit 1 +fi +# stdin에서 이미지 목록을 배열로 읽기 +mapfile -t IMAGES if [ ${#IMAGES[@]} -eq 0 ]; then echo "Error: No images found" exit 1 @@ -88,14 +85,8 @@ for IMAGE in "${IMAGES[@]}"; do continue fi - if [[ $IMAGE == *".dkr.ecr."* ]]; then - USERNAME="AWS" - else - USERNAME=$(echo "$IMAGE" | cut -d'/' -f1) - fi - - echo "add_docker_tag $IMAGE $TAG_TO_ADD $USERNAME ****" - add_docker_tag "$IMAGE" "$TAG_TO_ADD" "$USERNAME" "$TOKEN" & + echo "add_docker_tag $IMAGE $TAG_TO_ADD $USERNAME" + add_docker_tag "$IMAGE" "$TAG_TO_ADD" "$USERNAME" "$PASSWORD" & done wait