diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2414015 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,54 @@ +# Dependencies +node_modules +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Build outputs +.next +out +dist +build + +# Git +.git +.gitignore +.gitattributes + +# Environment files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE and editors +.vscode +.idea +*.swp +*.swo +*~ +.DS_Store + +# Documentation +README.md +CONTRIBUTING.md +CODE_OF_CONDUCT.md +LICENSE + +# Screenshots and media +src/screenshots +*.png +*.jpg +*.jpeg +*.gif +*.svg +TUXMATE.png + +# Testing +coverage +.nyc_output + +# Misc +*.log +.cache diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml new file mode 100644 index 0000000..843398c --- /dev/null +++ b/.github/workflows/docker-build.yml @@ -0,0 +1,70 @@ +name: Docker Build and Push + +on: + push: + branches: + - main + - docker + tags: + - "v*" + pull_request: + branches: + - main + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GitHub Container Registry + if: github.event_name != 'pull_request' + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=ref,event=branch + type=ref,event=pr + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha,prefix={{branch}}- + type=raw,value=latest,enable={{is_default_branch}} + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + file: ./Dockerfile + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + platforms: linux/amd64,linux/arm64 + build-args: | + NEXT_TELEMETRY_DISABLED=1 + + - name: Image digest + run: echo ${{ steps.meta.outputs.digest }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3ee1f75 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,63 @@ +# Stage 1: Install dependencies +FROM node:20-alpine AS deps +WORKDIR /app + +# Copy package files +COPY package.json package-lock.json ./ + +# Install dependencies +RUN npm ci --only=production && \ + npm cache clean --force + +# Stage 2: Build the application +FROM node:20-alpine AS builder +WORKDIR /app + +# Disable Next.js telemetry during build +ENV NEXT_TELEMETRY_DISABLED=1 + +# Copy package files +COPY package.json package-lock.json ./ + +# Install all dependencies (including devDependencies) +RUN npm ci + +# Copy source code +COPY . . + +# Build Next.js application +RUN npm run build + +# Stage 3: Production runtime +FROM node:20-alpine AS runner +WORKDIR /app + +# Set environment to production +ENV NODE_ENV=production +# Disable Next.js telemetry +ENV NEXT_TELEMETRY_DISABLED=1 + +# Create non-root user for security +RUN addgroup --system --gid 1001 nodejs && \ + adduser --system --uid 1001 nextjs + +# Copy necessary files from builder +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next/standalone ./ +COPY --from=builder /app/.next/static ./.next/static + +# Set correct permissions +RUN chown -R nextjs:nodejs /app + +# Switch to non-root user +USER nextjs + +# Expose port +EXPOSE 3000 + +# Set environment variable for port +ENV PORT=3000 +ENV HOSTNAME="0.0.0.0" + +# Start the application +CMD ["node", "server.js"] diff --git a/README.md b/README.md index 2edca5a..f194811 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,76 @@ npm start +
+

🐳 Docker Deployment

+ +### Quick Start with Docker + +```bash +# Build the Docker image +docker build -t tuxmate:latest . + +# Run the container +docker run -p 3000:3000 tuxmate:latest +``` + +### Using Pre-built Images + +Pre-built Docker images are automatically published to GitHub Container Registry: + +```bash +# Pull and run the latest image +docker pull ghcr.io/abusoww/tuxmate:latest +docker run -p 3000:3000 ghcr.io/abusoww/tuxmate:latest + +# Or use a specific version +docker pull ghcr.io/abusoww/tuxmate:v1.0.0 +docker run -p 3000:3000 ghcr.io/abusoww/tuxmate:v1.0.0 +``` + +### Using Docker Compose (Recommended) + +```bash +# Start the application +docker-compose up -d + +# View logs +docker-compose logs -f + +# Stop the application +docker-compose down +``` + +Open [http://localhost:3000](http://localhost:3000) + +### Configuration + +The Docker container exposes port 3000 by default. You can customize the port mapping: + +```bash +docker run -p 8080:3000 tuxmate:latest +``` + +### Environment Variables + +The following environment variables are configured by default: + +- `NODE_ENV=production` - Run in production mode +- `PORT=3000` - Application port +- `NEXT_TELEMETRY_DISABLED=1` - Disable Next.js anonymous telemetry + +You can override these when running the container: + +```bash +docker run -p 3000:3000 \ + -e PORT=3000 \ + -e NEXT_TELEMETRY_DISABLED=1 \ + tuxmate:latest +``` + +
+ + ## 🛠️ Tech Stack - Next.js 16 @@ -117,13 +187,14 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines. - [x] Copy command & Download script - [x] Package availability indicators - [x] Custom domain +- [x] Docker support for containerized deployment +- [x] CI/CD workflow for automated Docker builds ### Planned - [ ] Search & filter applications - [ ] Winget support (Windows) - [ ] Homebrew support (macOS) -- [ ] Dockerfile for containerized deployment - [ ] Save custom presets / profiles - [ ] Share configurations via URL - [ ] More distros (Gentoo, Void, Alpine) diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..cdbf10d --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' + +services: + tuxmate: + build: + context: . + dockerfile: Dockerfile + image: ghcr.io/retrozenith/tuxmate:latest + container_name: tuxmate + ports: + - "3000:3000" + environment: + - NODE_ENV=production + - PORT=3000 + - NEXT_TELEMETRY_DISABLED=1 + restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s diff --git a/next.config.ts b/next.config.ts index e9ffa30..225e495 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,7 +1,7 @@ import type { NextConfig } from "next"; const nextConfig: NextConfig = { - /* config options here */ + output: 'standalone', }; export default nextConfig;