diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fedd669 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,40 @@ +# Node modules +node_modules +**/node_modules + +# Logs +*.log +logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +build +dist +out +.next +.cache +.parcel-cache + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# OS files +.DS_Store +Thumbs.db + +# IDE / Editor folders +.vscode +.idea +*.sublime-workspace +*.sublime-project + +# Temporary files +*.swp +*.bak +*.tmp diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..1b35edc --- /dev/null +++ b/.drone.yml @@ -0,0 +1,139 @@ +--- +kind: pipeline +type: docker +name: default + +platform: + os: linux + arch: arm64 + +workspace: + path: /drone/src + +volumes: + - name: dockersock + host: + path: /var/run/docker.sock + +steps: + - name: fetch-tags + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - apk add --no-cache git + - git fetch --tags + - | + # Get latest Git tag and trim newline + LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null | tr -d '\n') + echo "Latest Git tag fetched: $LATEST_TAG" + + # Save to file for downstream steps + echo "$LATEST_TAG" > /drone/src/LATEST_TAG.txt + + # Read back for verification + IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + echo "Image tag read from file: $IMAGE_TAG" + + # Validate + if [ -z "$IMAGE_TAG" ]; then + echo "❌ No git tags found! Cannot continue." + exit 1 + fi + + - name: check-remote-image + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "Checking if lila-games/tic-tac-toe-ui:$IMAGE_TAG exists on remote Docker..." + - echo "Existing Docker tags for lila-games/tic-tac-toe-ui:" + - docker images --format "{{.Repository}}:{{.Tag}}" | grep "^lila-games/tic-tac-toe-ui" || echo "(none)" + - | + if docker image inspect lila-games/tic-tac-toe-ui:$IMAGE_TAG > /dev/null 2>&1; then + echo "✅ Docker image lila-games/tic-tac-toe-ui:$IMAGE_TAG already exists — skipping build" + exit 78 + else + echo "⚙️ Docker image lila-games/tic-tac-toe-ui:$IMAGE_TAG not found — proceeding to build..." + fi + + - name: build-image + image: docker:24 + environment: + API_BASE_URL: + from_secret: API_BASE_URL + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🔨 Building Docker image lila-games/tic-tac-toe-ui:$IMAGE_TAG ..." + - | + docker build --network=host \ + --build-arg VITE_WS_HOST="$API_BASE_URL" \ + --build-arg VITE_WS_PORT="$API_BASE_URL" \ + --build-arg VITE_WS_SKEY="$API_BASE_URL" \ + -t lila-games/tic-tac-toe-ui:$IMAGE_TAG \ + -t lila-games/tic-tac-toe-ui:latest \ + /drone/src + + - name: push-image + image: docker:24 + environment: + REGISTRY_HOST: + from_secret: REGISTRY_HOST + REGISTRY_USER: + from_secret: REGISTRY_USER + REGISTRY_PASS: + from_secret: REGISTRY_PASS + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🔑 Logging into registry $REGISTRY_HOST ..." + - echo "$REGISTRY_PASS" | docker login $REGISTRY_HOST -u "$REGISTRY_USER" --password-stdin + - echo "🏷️ Tagging images with registry prefix..." + - docker tag lila-games/tic-tac-toe-ui:$IMAGE_TAG $REGISTRY_HOST/lila-games/tic-tac-toe-ui:$IMAGE_TAG + - docker tag lila-games/tic-tac-toe-ui:$IMAGE_TAG $REGISTRY_HOST/lila-games/tic-tac-toe-ui:latest + - echo "📤 Pushing lila-games/tic-tac-toe-ui:$IMAGE_TAG ..." + - docker push $REGISTRY_HOST/lila-games/tic-tac-toe-ui:$IMAGE_TAG + - echo "📤 Pushing lila-games/tic-tac-toe-ui:latest ..." + - docker push $REGISTRY_HOST/lila-games/tic-tac-toe-ui:latest + + - name: stop-old + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - echo "🛑 Stopping old container..." + - docker rm -f blog || true + + - name: run-container + image: docker:24 + volumes: + - name: dockersock + path: /var/run/docker.sock + commands: + - IMAGE_TAG=$(cat /drone/src/LATEST_TAG.txt | tr -d '\n') + + - echo "🚀 Starting container lila-games/tic-tac-toe-ui:$IMAGE_TAG ..." + - | + docker run -d \ + --name blog \ + -p 3002:3000 \ + -e NODE_ENV=production \ + --restart always \ + lila-games/tic-tac-toe-ui:$IMAGE_TAG + +# Trigger rules +trigger: + event: + - tag diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d6ef086 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,41 @@ +# Stage 1: Build +FROM node:20-alpine AS builder + +# Set working directory +WORKDIR /app + +# Copy package.json and package-lock.json (or yarn.lock) +COPY package*.json ./ + +# Install dependencies +RUN npm ci + +# Copy the rest of the app +COPY . . + +# Build arguments +ARG VITE_WS_HOST +ARG VITE_WS_PORT +ARG VITE_WS_SKEY + +# Export them as actual environment variables (Vite needs ENV) +ENV VITE_WS_HOST=${VITE_WS_HOST} +ENV VITE_WS_PORT=${VITE_WS_PORT} +ENV VITE_WS_SKEY=${VITE_WS_SKEY} + +# Build +RUN npm run build + +# Stage 2: Static file server (BusyBox) +FROM busybox:latest + +WORKDIR /app + +# Copy only build frontend files +COPY --from=builder /app/dist /app + +# Expose port +EXPOSE 3000 + +# Default command +CMD ["busybox", "httpd", "-f", "-p", "3000"]