diff --git a/.dockerignore b/.dockerignore index 793867a..d024ac3 100644 --- a/.dockerignore +++ b/.dockerignore @@ -3,6 +3,7 @@ dist coverage .git .gitignore +image.oci.tar Dockerfile* docker-compose*.yml .env diff --git a/.env.dockerize.example b/.env.dockerize.example index f8bd90f..0ea78b4 100644 --- a/.env.dockerize.example +++ b/.env.dockerize.example @@ -1,2 +1,10 @@ USER= TOKEN= +# DOCKER_TLS_CERTDIR= # dind의 TLS 인증서 디렉터리 활성화 +DOCKER_HOST=tcp://127.0.0.1:2375 # dind 데몬에 접속하도록 설정 +DOCKER_BUILDKIT=1 # BuildKit 활성화(빠르고 캐시 효율적) +REGISTRY= # 푸시할 레지스트리 호스트 +IMAGE= # 레포지토리/이미지 이름 +TAG= +BLOB_CHUNK=52428800 # 50MB chunks (default: 50MB) +BLOB_MAX=104857600 # 100MB max (Cloudflare Tunnel limit) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 40259be..75aa53e 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -1,12 +1,39 @@ -name: Test Runner +name: BKON API Server Deploy on: push: - branches: ["main"] + branches: ['main'] + +env: + REGISTRY: ${{ secrets.REGISTRY }} # 예: git.mnco.dev + IMAGE: ${{ secrets.IMAGE }} # 예: mnco/regecy-wallet-backend + TAG: Test jobs: - check-runner: - runs-on: [ubuntu-latest] # 러너 라벨과 일치해야 함 + build-and-push: + runs-on: ubuntu-latest steps: - - name: Print hello - run: echo "✅ Runner is working!" + - uses: actions/checkout@v4 + + - name: Create .env.dockerize + run: | + umask 077 + cat > .env.dockerize < /var/log/dockerd.log 2>&1 & +DOCKERD_PID=$! + +# Give the daemon a moment to start +sleep 3 + +# Wait for Docker daemon to be ready +log "Waiting for Docker daemon to be ready..." +tries=0 +max_tries=60 +until docker version >/dev/null 2>&1; do + if [ $tries -ge $max_tries ]; then + log "ERROR: Docker daemon failed to start within reasonable time" + log "Docker daemon logs:" + if [ -f /var/log/dockerd.log ]; then + cat /var/log/dockerd.log + else + log "Log file not found" + fi + # Try to see if the daemon is running + if ps -p $DOCKERD_PID > /dev/null; then + log "Docker daemon process is still running (PID: $DOCKERD_PID)" + else + log "Docker daemon process has exited" + fi + kill $DOCKERD_PID 2>/dev/null || true + wait $DOCKERD_PID 2>/dev/null || true + exit 1 + fi + log "Waiting for Docker daemon... ($tries/$max_tries)" + tries=$((tries + 1)) + sleep 1 +done +log "Docker daemon is ready" + +# Install regctl if not present +log "Checking for regctl..." +if ! command -v regctl >/dev/null 2>&1; then + log "Installing regctl..." + wget -O /usr/local/bin/regctl https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 + chmod 755 /usr/local/bin/regctl +fi + +# Enable Docker BuildKit +export DOCKER_BUILDKIT=1 + +# Check if required environment variables are set +log "Checking environment variables..." +missing_vars="" +[ -z "$USER" ] && missing_vars="$missing_vars USER" +[ -z "$TOKEN" ] && missing_vars="$missing_vars TOKEN" +[ -z "$REGISTRY" ] && missing_vars="$missing_vars REGISTRY" +[ -z "$IMAGE" ] && missing_vars="$missing_vars IMAGE" +[ -z "$TAG" ] && missing_vars="$missing_vars TAG" + +if [ -n "$missing_vars" ]; then + log "ERROR: Missing required environment variables:$missing_vars" + kill $DOCKERD_PID 2>/dev/null || true + wait $DOCKERD_PID 2>/dev/null || true + exit 1 +fi + +# Login to registry +log "Logging into registry $REGISTRY..." +echo "$TOKEN" | docker login "$REGISTRY" -u "$USER" --password-stdin +if [ $? -eq 0 ]; then + log "Successfully logged into registry" +else + log "ERROR: Failed to login to registry" + kill $DOCKERD_PID 2>/dev/null || true + wait $DOCKERD_PID 2>/dev/null || true + exit 1 +fi + +# Build Docker image +log "Building Docker image $REGISTRY/$IMAGE:$TAG..." +if docker buildx build \ + --platform linux/amd64 \ + --target runner \ + -t "$REGISTRY/$IMAGE:$TAG" \ + --provenance=false \ + --sbom=false \ + -o "type=oci,dest=./image.oci.tar" \ + .; then + log "Successfully built Docker image" +else + log "ERROR: Failed to build Docker image" + kill $DOCKERD_PID 2>/dev/null || true + wait $DOCKERD_PID 2>/dev/null || true + exit 1 +fi + +# Push Docker image +log "Pushing Docker image to registry..." + +# Set blob settings with defaults +BLOB_CHUNK="${BLOB_CHUNK:-5242880}" +BLOB_MAX="${BLOB_MAX:-104857600}" + +# Configure registry settings +regctl registry set "$REGISTRY" --blob-chunk "$BLOB_CHUNK" --blob-max "$BLOB_MAX" + +# Import and push the image +if regctl image import "$REGISTRY/$IMAGE:$TAG" ./image.oci.tar -v info; then + log "Successfully pushed Docker image to registry" +else + log "ERROR: Failed to push Docker image to registry" + kill $DOCKERD_PID 2>/dev/null || true + wait $DOCKERD_PID 2>/dev/null || true + exit 1 +fi + +log "Docker build and push process completed successfully!" + +# Shutdown Docker daemon +log "Shutting down Docker daemon..." +kill $DOCKERD_PID 2>/dev/null || true +wait $DOCKERD_PID 2>/dev/null || true + +log "Docker daemon shutdown complete" +log "Exiting container..." +exit 0 diff --git a/dockerize.yml b/dockerize.yml index a0482ee..5d256b9 100644 --- a/dockerize.yml +++ b/dockerize.yml @@ -1,39 +1,18 @@ services: # docker compose 서비스 정의 루트 - dind: # Docker-in-Docker 데몬 컨테이너 + builder-dind: # Docker-in-Docker 데몬과 빌더가 결합된 컨테이너 image: docker:24-dind # 도커 데몬이 포함된 공식 dind 이미지(v24) privileged: true # 컨테이너 안에서 도커 데몬을 구동하려면 privileged 권한 필요 environment: - - DOCKER_TLS_CERTDIR= # dind의 TLS 인증서 디렉터리 비활성화(평문 2375 사용) + - DOCKER_TLS_CERTDIR=${DOCKER_TLS_CERTDIR:-} # dind의 TLS 인증서 디렉터리 활성화(평문 2375 사용)비활성화(평문 2375 사용) + - DOCKER_HOST=${DOCKER_HOST:-tcp://127.0.0.1:2375} # 로컬 도커 데몬에 접속 volumes: - dind-cache:/var/lib/docker # 도커 레이어/이미지 캐시를 볼륨에 보존해 재빌드 가속 - ./docker-daemon.json:/etc/docker/daemon.json:ro # 도커 데몬 설정(동시 업로드 제한 등) 주입 - healthcheck: - test: ['CMD-SHELL', 'docker info > /dev/null 2>&1 || exit 1'] # 데몬 준비 여부 검사 - interval: 2s # 2초마다 헬스체크 - timeout: 1s # 1초 넘기면 실패로 간주 - retries: 30 # 최대 30회 재시도(약 60초 대기) - - builder: # 빌드/푸시를 수행하는 도커 CLI 컨테이너 - image: docker:24-cli # 도커 CLI만 포함된 경량 이미지(v24) - depends_on: - dind: - condition: service_healthy # dind 헬스체크 통과 후에만 시작 - working_dir: /workspace # 작업 디렉터리(호스트의 리포지토리를 마운트) - volumes: - .:/workspace # 현재 리포지토리를 컨테이너에 바인드 마운트 + working_dir: /workspace # 작업 디렉터리(호스트의 리포지토리를 마운트) env_file: - ./.env.dockerize # USER/TOKEN, TAG 등 환경변수 로드 - environment: - - DOCKER_HOST=tcp://dind:2375 # dind 데몬에 접속하도록 설정 - - DOCKER_BUILDKIT=1 # BuildKit 활성화(빠르고 캐시 효율적) - - REGISTRY=git.mnco.dev # 푸시할 레지스트리 호스트 - - IMAGE=mnco/regecy-wallet-backend # 레포지토리/이미지 이름 - - TAG=latest # 기본 태그 - command: [ - 'sh', - '-lc', - 'until docker version >/dev/null 2>&1; do echo ''waiting for dind...''; sleep 1; done; echo "$$TOKEN" | docker login $$REGISTRY -u $$USER --password-stdin && docker buildx build --platform linux/amd64 --target runner -t $$REGISTRY/$$IMAGE:$$TAG --provenance=false --sbom=false --push .', - ] # dind 대기 → 레지스트리 로그인 → buildx 빌드/푸시 + command: ['sh', './bin/dockerize.sh'] volumes: dind-cache: # dind의 /var/lib/docker를 저장하는 네임드 볼륨