diff --git a/docker/README.md b/docker/README.md index b23bf89..5d1af81 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,137 +1,69 @@ -# GitDataAI Docker 配置 +# GitDataAI Docker -## 文件说明 +默认镜像仓库:`harbor.gitdata.me/app` -### Dockerfile 文件 +## 服务 -| 文件名 | 服务 | 说明 | -|--------|------|------| -| `gitdata.Dockerfile` | GitData API | 主 API 服务 | -| `email.Dockerfile` | Email Service | 邮件发送服务 | -| `gitpod.Dockerfile` | GitPod Service | Git 服务 | -| `gitsync.Dockerfile` | GitSync Service | Git 同步服务 | -| `migrate.Dockerfile` | Database Migration | 数据库迁移工具 | -| `web.Dockerfile` | Web Frontend | React 前端应用 | +| Dockerfile | 服务 | 端口 | 健康检查 | +|-----------|------|------|---------| +| `gitdata.Dockerfile` | API 服务 | 8080 | `/metrics` | +| `gitpod.Dockerfile` | Git 协议 (HTTP/SSH/gRPC) | 8080, 2222, 50051 | `/health` | +| `gitsync.Dockerfile` | Git 同步 worker | 8081 | `/health` | +| `email.Dockerfile` | 邮件 worker | 8083 | `/health` | +| `web.Dockerfile` | 前端 | 80 | `/` | -### 配置文件 +## 构建 -| 文件名 | 说明 | -|--------|------| -| `docker-compose.yml` | 完整的开发环境配置 | -| `nginx.conf` | Nginx 反向代理配置 | - -## 快速开始 - -### 1. 启动完整开发环境 +先编译 Rust 二进制,再打镜像: ```bash -# 进入 docker 目录 -cd docker +# 编译全部 Rust 服务 +cargo build --release -# 启动所有服务 -docker-compose up -d +# 构建全部镜像 (默认推送到 harbor.gitdata.me/app) +./docker/build.sh -# 查看服务状态 -docker-compose ps +# 只构建指定服务 +./docker/build.sh gitdata gitpod -# 查看日志 -docker-compose logs -f +# 自定义 tag +./docker/build.sh -t v1.2.0 + +# 自定义 registry +./docker/build.sh -r myreg.io/app -t dev ``` -### 2. 单独构建服务 +## 推送 ```bash -# 构建 GitData API -docker build -f docker/gitdata.Dockerfile -t gitdata-api . +# 推送全部 (默认 harbor.gitdata.me/app) +./docker/push.sh -# 构建前端 -docker build -f docker/web.Dockerfile -t gitdata-web . +# 推送指定服务 +./docker/push.sh gitdata gitpod + +# 自定义 tag / registry +./docker/push.sh -t v1.2.0 +./docker/push.sh -r myreg.io/app -t dev ``` -### 3. 环境变量配置 +## 本地开发 -创建 `.env` 文件配置环境变量: +使用 docker compose 启动全部服务(含依赖的 Postgres/Redis/Qdrant/NATS/MinIO): ```bash -# 数据库配置 -POSTGRES_USER=gitdata -POSTGRES_PASSWORD=your_secure_password -POSTGRES_DB=app - -# MinIO 配置 -MINIO_ROOT_USER=admin -MINIO_ROOT_PASSWORD=your_secure_password +docker compose -f docker/docker-compose.yml up -d ``` -## 服务端口 - -| 服务 | 端口 | 说明 | -|------|------|------| -| Web Frontend | 80 | 前端访问入口 | -| GitData API | 8080 | 主 API 服务 | -| Git HTTP | 5023 | Git HTTP 访问 | -| Git RPC | 5030 | Git RPC 服务 | -| SSH | 5022 | SSH Git 访问 | -| GitPod | 5082 | GitPod 服务 | -| GitSync | 5083 | GitSync 健康检查 | -| PostgreSQL | 5432 | 数据库 | -| Redis | 6379 | 缓存 | -| Qdrant | 6333 | 向量数据库 | -| NATS | 4222 | 消息队列 | -| MinIO | 9000/9001 | 对象存储 | - -## 生产环境部署 - -### 1. 修改环境变量 +compose 默认从 `harbor.gitdata.me/app` 拉取镜像,可通过环境变量覆盖: ```bash -# 复制示例配置 -cp .env.example .env - -# 编辑配置文件,修改密码等敏感信息 -vim .env +IMAGE_REGISTRY=myreg.io/app IMAGE_TAG=v1.2.0 \ + docker compose -f docker/docker-compose.yml up -d ``` -### 2. 启动服务 +## 镜像结构 -```bash -# 使用生产配置启动 -docker-compose -f docker-compose.yml up -d - -# 查看服务状态 -docker-compose ps -``` - -### 3. 数据备份 - -```bash -# 备份 PostgreSQL -docker exec gitdata-postgres pg_dump -U gitdata app > backup.sql - -# 备份 MinIO 数据 -docker cp gitdata-minio:/data ./minio-backup -``` - -## 常见问题 - -### 1. 服务启动失败 - -检查日志: -```bash -docker-compose logs -``` - -### 2. 数据库连接失败 - -确保 PostgreSQL 健康检查通过: -```bash -docker-compose ps postgres -``` - -### 3. 端口冲突 - -修改 `docker-compose.yml` 中的端口映射: -```yaml -ports: - - "8081:8080" # 修改宿主机端口 -``` \ No newline at end of file +- Rust 服务:`debian:bookworm-slim` + 预编译二进制(~20MB) +- 前端:多阶段构建 `oven/bun` + `nginx:alpine` +- 数据库迁移在 gitdata 启动时自动执行(见 lib/migrate) diff --git a/docker/build.sh b/docker/build.sh index d0ccdb8..0a94f6d 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -1,131 +1,117 @@ #!/bin/bash -# GitDataAI Docker Build Script - set -e -# Get version from Cargo.toml PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" CARGO_VERSION=$(grep -m1 'version' "${PROJECT_ROOT}/Cargo.toml" | sed 's/.*"\(.*\)".*/\1/') -# Configuration -REGISTRY=${REGISTRY:-""} +REGISTRY=${REGISTRY:-"harbor.gitdata.me/app"} TAG=${TAG:-"${CARGO_VERSION:-latest}"} PLATFORM=${PLATFORM:-"linux/amd64"} +TARGET_DIR=${CARGO_TARGET_DIR:-target} -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color +if command -v podman &>/dev/null; then + DOCKER=podman +elif command -v docker &>/dev/null; then + DOCKER=docker +else + echo "ERROR: neither podman nor docker found" + exit 1 +fi -# Services to build -SERVICES=("gitdata" "email" "gitpod" "gitsync" "migrate" "web") +RUST_BINS=("gitdata" "gitpod" "gitsync" "email-service") +ALL_SERVICES=("gitdata" "gitpod" "gitsync" "email" "web") -# Function to print colored output -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" +log_info() { echo -e "\033[0;32m[INFO]\033[0m $1"; } +log_error() { echo -e "\033[0;31m[ERROR]\033[0m $1"; } + +build_rust() { + log_info "Building Rust binaries: $*" + cd "$PROJECT_ROOT" + cargo build --release "$@" } -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Function to build a service -build_service() { +build_image() { local service=$1 local dockerfile="${PROJECT_ROOT}/docker/${service}.Dockerfile" - local image_name="gitdata-${service}" + local image_name="${REGISTRY}/gitdata-${service}" - # Add registry prefix if set - if [ -n "$REGISTRY" ]; then - image_name="${REGISTRY}/${image_name}" - fi + log_info "Building image ${image_name}:${TAG}" - log_info "Building ${service}..." - - if [ ! -f "$dockerfile" ]; then - log_error "Dockerfile not found: ${dockerfile}" - return 1 - fi - - docker build \ + $DOCKER build \ -f "$dockerfile" \ -t "${image_name}:${TAG}" \ --platform "$PLATFORM" \ + --build-arg TARGET_DIR="$TARGET_DIR" \ "$PROJECT_ROOT" - - log_info "Successfully built ${image_name}:${TAG}" } -# Parse command line arguments +svc_to_bin() { + case $1 in + gitdata) echo "gitdata" ;; + gitpod) echo "gitpod" ;; + gitsync) echo "gitsync" ;; + email) echo "email-service" ;; + web) echo "" ;; + *) echo "" ;; + esac +} + BUILD_SERVICES=() BUILD_ALL=true while [[ $# -gt 0 ]]; do case $1 in - --tag|-t) - TAG="$2" - shift 2 - ;; - --registry|-r) - REGISTRY="$2" - shift 2 - ;; - --platform|-p) - PLATFORM="$2" - shift 2 - ;; + --tag|-t) TAG="$2"; shift 2 ;; + --registry|-r) REGISTRY="$2"; shift 2 ;; + --platform|-p) PLATFORM="$2"; shift 2 ;; --help|-h) echo "Usage: $0 [OPTIONS] [SERVICE...]" echo "" echo "Options:" - echo " -t, --tag TAG Docker image tag (default: latest)" - echo " -r, --registry REG Docker registry prefix" - echo " -p, --platform PLAT Target platform (default: linux/amd64)" - echo " -h, --help Show this help message" + echo " -t, --tag TAG Image tag (default: from Cargo.toml)" + echo " -r, --registry REG Registry prefix (default: harbor.gitdata.me/app)" + echo " -p, --platform PLAT Target platform (default: linux/amd64)" echo "" echo "Services:" - echo " gitdata Main API service" - echo " email Email service" - echo " gitpod GitPod service" - echo " gitsync GitSync service" - echo " migrate Database migration" - echo " web Web frontend" + echo " gitdata gitpod gitsync email web" echo "" echo "Examples:" - echo " $0 # Build all services" - echo " $0 gitdata web # Build specific services" - echo " $0 -t v1.0.0 -r registry.com # Build with custom tag and registry" + echo " $0 # Build all" + echo " $0 gitdata gitpod # Build specific services" + echo " $0 -t v1.2.0 # Build with custom tag" + echo " $0 -r myreg.io/app -t dev # Build with custom registry and tag" exit 0 ;; - *) - BUILD_SERVICES+=("$1") - BUILD_ALL=false - shift - ;; + *) BUILD_SERVICES+=("$1"); BUILD_ALL=false; shift ;; esac done -# Build services -log_info "Starting Docker build..." -log_info "Registry: ${REGISTRY:-none}" -log_info "Tag: ${TAG}" -log_info "Platform: ${PLATFORM}" - if [ "$BUILD_ALL" = true ]; then - log_info "Building all services..." - for service in "${SERVICES[@]}"; do - build_service "$service" + log_info "Building all services (registry=${REGISTRY}, tag=${TAG})" + + build_rust + + for svc in "${ALL_SERVICES[@]}"; do + build_image "$svc" done else - log_info "Building specified services: ${BUILD_SERVICES[*]}" - for service in "${BUILD_SERVICES[@]}"; do - build_service "$service" + log_info "Building services: ${BUILD_SERVICES[*]} (registry=${REGISTRY}, tag=${TAG})" + + rust_bins=() + for svc in "${BUILD_SERVICES[@]}"; do + bin=$(svc_to_bin "$svc") + if [ -n "$bin" ]; then + rust_bins+=("--bin" "$bin") + fi + done + + if [ ${#rust_bins[@]} -gt 0 ]; then + build_rust "${rust_bins[@]}" + fi + + for svc in "${BUILD_SERVICES[@]}"; do + build_image "$svc" done fi -log_info "Build completed successfully!" \ No newline at end of file +log_info "Done." diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 447cd34..4c0789b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,8 +1,4 @@ -# GitDataAI Docker Compose -# Full stack deployment configuration - services: - # PostgreSQL Database postgres: image: postgres:16-alpine container_name: gitdata-postgres @@ -21,7 +17,6 @@ services: retries: 5 restart: unless-stopped - # Redis Cluster redis: image: redis:7-alpine container_name: gitdata-redis @@ -36,7 +31,6 @@ services: retries: 5 restart: unless-stopped - # Qdrant Vector Database qdrant: image: qdrant/qdrant:latest container_name: gitdata-qdrant @@ -46,7 +40,6 @@ services: - qdrant_data:/qdrant/storage restart: unless-stopped - # NATS Message Queue nats: image: nats:alpine container_name: gitdata-nats @@ -56,7 +49,6 @@ services: command: "--jetstream" restart: unless-stopped - # MinIO S3 Storage minio: image: minio/minio:latest container_name: gitdata-minio @@ -71,24 +63,8 @@ services: - minio_data:/data restart: unless-stopped - # Database Migration - migrate: - build: - context: .. - dockerfile: docker/migrate.Dockerfile - container_name: gitdata-migrate - environment: - DATABASE_URL: postgres://${POSTGRES_USER:-gitdata}:${POSTGRES_PASSWORD:-gitdata123}@postgres:5432/${POSTGRES_DB:-app} - depends_on: - postgres: - condition: service_healthy - restart: "no" - - # GitData Main API Service gitdata: - build: - context: .. - dockerfile: docker/gitdata.Dockerfile + image: ${IMAGE_REGISTRY:-harbor.gitdata.me/app/}gitdata-gitdata:${IMAGE_TAG:-latest} container_name: gitdata-api environment: APP_DATABASE_URL: postgres://${POSTGRES_USER:-gitdata}:${POSTGRES_PASSWORD:-gitdata123}@postgres:5432/${POSTGRES_DB:-app} @@ -98,11 +74,12 @@ services: APP_STORAGE_S3_ENDPOINT_URL: http://minio:9000 APP_STORAGE_S3_ACCESS_KEY_ID: ${MINIO_ROOT_USER:-admin} APP_STORAGE_S3_SECRET_ACCESS_KEY: ${MINIO_ROOT_PASSWORD:-mysecret123} + APP_STORAGE_S3_BUCKET: ${APP_STORAGE_S3_BUCKET:-gitdata} + APP_SESSION_SECRET: ${APP_SESSION_SECRET:-supersecretdevkey123} + APP_GIT_RPC_ADDR: gitpod + APP_GIT_RPC_PORT: "50051" ports: - "8080:8080" - - "5023:5023" - - "5030:5030" - - "5022:5022" volumes: - gitdata_repos:/app/data/repos - gitdata_files:/app/data/files @@ -118,20 +95,20 @@ services: condition: service_started minio: condition: service_started - migrate: - condition: service_completed_successfully restart: unless-stopped - # Email Service email: - build: - context: .. - dockerfile: docker/email.Dockerfile + image: ${IMAGE_REGISTRY:-harbor.gitdata.me/app/}gitdata-email:${IMAGE_TAG:-latest} container_name: gitdata-email environment: APP_DATABASE_URL: postgres://${POSTGRES_USER:-gitdata}:${POSTGRES_PASSWORD:-gitdata123}@postgres:5432/${POSTGRES_DB:-app} APP_REDIS_URLS: redis://redis:6379 NATS_URL: nats://nats:4222 + APP_SMTP_HOST: ${APP_SMTP_HOST:-mailhog} + APP_SMTP_PORT: ${APP_SMTP_PORT:-1025} + APP_SMTP_USERNAME: ${APP_SMTP_USERNAME:-dev} + APP_SMTP_PASSWORD: ${APP_SMTP_PASSWORD:-dev} + APP_SMTP_FROM: ${APP_SMTP_FROM:-Gitdata } depends_on: postgres: condition: service_healthy @@ -141,17 +118,19 @@ services: condition: service_started restart: unless-stopped - # GitPod Service gitpod: - build: - context: .. - dockerfile: docker/gitpod.Dockerfile + image: ${IMAGE_REGISTRY:-harbor.gitdata.me/app/}gitdata-gitpod:${IMAGE_TAG:-latest} container_name: gitdata-gitpod environment: APP_DATABASE_URL: postgres://${POSTGRES_USER:-gitdata}:${POSTGRES_PASSWORD:-gitdata123}@postgres:5432/${POSTGRES_DB:-app} APP_REDIS_URLS: redis://redis:6379 + APP_GIT_HTTP_PORT: "8080" + APP_GIT_RPC_PORT: "50051" + APP_SSH_PORT: "2222" ports: - - "5082:5082" + - "2222:2222" + - "8081:8080" + - "50051:50051" volumes: - gitdata_repos:/app/data/repos depends_on: @@ -161,17 +140,15 @@ services: condition: service_healthy restart: unless-stopped - # GitSync Service gitsync: - build: - context: .. - dockerfile: docker/gitsync.Dockerfile + image: ${IMAGE_REGISTRY:-harbor.gitdata.me/app/}gitdata-gitsync:${IMAGE_TAG:-latest} container_name: gitdata-gitsync environment: APP_DATABASE_URL: postgres://${POSTGRES_USER:-gitdata}:${POSTGRES_PASSWORD:-gitdata123}@postgres:5432/${POSTGRES_DB:-app} APP_REDIS_URLS: redis://redis:6379 + APP_GITSYNC_HEALTH_PORT: "8081" ports: - - "5083:5083" + - "8082:8081" volumes: - gitdata_repos:/app/data/repos depends_on: @@ -181,11 +158,8 @@ services: condition: service_healthy restart: unless-stopped - # Web Frontend web: - build: - context: .. - dockerfile: docker/web.Dockerfile + image: ${IMAGE_REGISTRY:-harbor.gitdata.me/app/}gitdata-web:${IMAGE_TAG:-latest} container_name: gitdata-web ports: - "80:80" @@ -200,4 +174,4 @@ volumes: minio_data: gitdata_repos: gitdata_files: - gitdata_avatar: \ No newline at end of file + gitdata_avatar: diff --git a/docker/email.Dockerfile b/docker/email.Dockerfile index 207dde6..e2c55a5 100644 --- a/docker/email.Dockerfile +++ b/docker/email.Dockerfile @@ -1,61 +1,26 @@ -# GitDataAI Backend - Email Service -# Multi-stage build for Rust application +ARG TARGET_DIR=target -# Stage 1: Build the application -FROM rust:1.96-bookworm AS builder +FROM ubuntu:26.04 -# Install system dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - libpq-dev \ - cmake \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 openssh-client procps git \ && rm -rf /var/lib/apt/lists/* +RUN git config --system --add safe.directory '*' -# Create app directory -WORKDIR /app - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY app/ app/ -COPY lib/ lib/ - -# Build the application in release mode -RUN cargo build --release --bin email-service - -# Stage 2: Create runtime image -FROM debian:bookworm-slim - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - libssl3 \ - libpq5 \ - ca-certificates \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user RUN useradd -r -s /bin/false appuser -# Create directories RUN mkdir -p /app/logs \ && chown -R appuser:appuser /app -# Copy binary from builder -COPY --from=builder /app/target/release/email-service /app/email-service - -# Set ownership +COPY ${TARGET_DIR}/release/email-service /app/email-service RUN chown -R appuser:appuser /app -# Switch to non-root user USER appuser - -# Set working directory WORKDIR /app -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD pgrep email-service || exit 1 +EXPOSE 8083 -# Run the application -CMD ["./email-service"] \ No newline at end of file +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8083/health || exit 1 + +CMD ["./email-service"] diff --git a/docker/gitdata.Dockerfile b/docker/gitdata.Dockerfile index 6ada483..174e371 100644 --- a/docker/gitdata.Dockerfile +++ b/docker/gitdata.Dockerfile @@ -1,74 +1,26 @@ -# GitDataAI Backend - GitData Service -# Multi-stage build for Rust application +ARG TARGET_DIR=target -# Stage 1: Build the application -FROM rust:1.96-bookworm AS builder +FROM ubuntu:26.04 -# Install system dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - libpq-dev \ - cmake \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 openssh-client procps git \ && rm -rf /var/lib/apt/lists/* +RUN git config --system --add safe.directory '*' -# Create app directory -WORKDIR /app - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY app/ app/ -COPY lib/ lib/ - -# Build the application in release mode -RUN cargo build --release --bin gitdata - -# Stage 2: Create runtime image -FROM debian:bookworm-slim - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - libssl3 \ - libpq5 \ - ca-certificates \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user RUN useradd -r -s /bin/false appuser -# Create directories -RUN mkdir -p /app/data/repos \ - /app/data/files \ - /app/data/avatar \ - /app/logs \ +RUN mkdir -p /app/data/repos /app/data/files /app/data/avatar /app/logs \ && chown -R appuser:appuser /app -# Copy binary from builder -COPY --from=builder /app/target/release/gitdata /app/gitdata - -# Set ownership +COPY ${TARGET_DIR}/release/gitdata /app/gitdata RUN chown -R appuser:appuser /app -# Switch to non-root user USER appuser - -# Set working directory WORKDIR /app -# Expose ports -# API port EXPOSE 8080 -# Git HTTP port -EXPOSE 5023 -# Git RPC port -EXPOSE 5030 -# SSH port -EXPOSE 5022 -# Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:8080/health || exit 1 +HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ + CMD curl -f http://localhost:8080/metrics || exit 1 -# Run the application -CMD ["./gitdata"] \ No newline at end of file +CMD ["./gitdata"] diff --git a/docker/gitpod.Dockerfile b/docker/gitpod.Dockerfile index deca8dc..e2e8a5f 100644 --- a/docker/gitpod.Dockerfile +++ b/docker/gitpod.Dockerfile @@ -1,65 +1,26 @@ -# GitDataAI Backend - GitPod Service -# Multi-stage build for Rust application +ARG TARGET_DIR=target -# Stage 1: Build the application -FROM rust:1.96-bookworm AS builder +FROM ubuntu:26.04 -# Install system dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - libpq-dev \ - cmake \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 openssh-client procps git \ && rm -rf /var/lib/apt/lists/* +RUN git config --system --add safe.directory '*' -# Create app directory -WORKDIR /app - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY app/ app/ -COPY lib/ lib/ - -# Build the application in release mode -RUN cargo build --release --bin gitpod - -# Stage 2: Create runtime image -FROM debian:bookworm-slim - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - libssl3 \ - libpq5 \ - ca-certificates \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user RUN useradd -r -s /bin/false appuser -# Create directories -RUN mkdir -p /app/data/repos \ - /app/logs \ +RUN mkdir -p /app/data/repos /app/logs \ && chown -R appuser:appuser /app -# Copy binary from builder -COPY --from=builder /app/target/release/gitpod /app/gitpod - -# Set ownership +COPY ${TARGET_DIR}/release/gitpod /app/gitpod RUN chown -R appuser:appuser /app -# Switch to non-root user USER appuser - -# Set working directory WORKDIR /app -# Expose port -EXPOSE 5082 +EXPOSE 8080 2222 50051 -# Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:5082/health || exit 1 + CMD curl -f http://localhost:8080/health || exit 1 -# Run the application -CMD ["./gitpod"] \ No newline at end of file +CMD ["./gitpod"] diff --git a/docker/gitsync.Dockerfile b/docker/gitsync.Dockerfile index 6ce8777..bcc95fa 100644 --- a/docker/gitsync.Dockerfile +++ b/docker/gitsync.Dockerfile @@ -1,65 +1,26 @@ -# GitDataAI Backend - GitSync Service -# Multi-stage build for Rust application +ARG TARGET_DIR=target -# Stage 1: Build the application -FROM rust:1.96-bookworm AS builder +FROM ubuntu:26.04 -# Install system dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - libpq-dev \ - cmake \ +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 openssh-client procps git \ && rm -rf /var/lib/apt/lists/* +RUN git config --system --add safe.directory '*' -# Create app directory -WORKDIR /app - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY app/ app/ -COPY lib/ lib/ - -# Build the application in release mode -RUN cargo build --release --bin gitsync - -# Stage 2: Create runtime image -FROM debian:bookworm-slim - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - libssl3 \ - libpq5 \ - ca-certificates \ - curl \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user RUN useradd -r -s /bin/false appuser -# Create directories -RUN mkdir -p /app/data/repos \ - /app/logs \ +RUN mkdir -p /app/data/repos /app/logs \ && chown -R appuser:appuser /app -# Copy binary from builder -COPY --from=builder /app/target/release/gitsync /app/gitsync - -# Set ownership +COPY ${TARGET_DIR}/release/gitsync /app/gitsync RUN chown -R appuser:appuser /app -# Switch to non-root user USER appuser - -# Set working directory WORKDIR /app -# Expose health check port -EXPOSE 5083 +EXPOSE 8081 -# Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:5083/health || exit 1 + CMD curl -f http://localhost:8081/health || exit 1 -# Run the application -CMD ["./gitsync"] \ No newline at end of file +CMD ["./gitsync"] diff --git a/docker/migrate.Dockerfile b/docker/migrate.Dockerfile deleted file mode 100644 index dab22a0..0000000 --- a/docker/migrate.Dockerfile +++ /dev/null @@ -1,58 +0,0 @@ -# GitDataAI Database Migration Dockerfile -# Multi-stage build for Rust migration tool - -# Stage 1: Build the application -FROM rust:1.96-bookworm AS builder - -# Install system dependencies -RUN apt-get update && apt-get install -y \ - pkg-config \ - libssl-dev \ - libpq-dev \ - cmake \ - && rm -rf /var/lib/apt/lists/* - -# Create app directory -WORKDIR /app - -# Copy workspace files -COPY Cargo.toml Cargo.lock ./ -COPY app/ app/ -COPY lib/ lib/ - -# Build the migration binary -RUN cargo build --release --bin migrate - -# Stage 2: Create runtime image -FROM debian:bookworm-slim - -# Install runtime dependencies -RUN apt-get update && apt-get install -y \ - libssl3 \ - libpq5 \ - ca-certificates \ - && rm -rf /var/lib/apt/lists/* - -# Create non-root user -RUN useradd -r -s /bin/false appuser - -# Create app directory -RUN mkdir -p /app && chown -R appuser:appuser /app - -# Copy binary from builder -COPY --from=builder /app/target/release/migrate /app/migrate - -# Copy migration files -COPY --from=builder /app/lib/migrate/sql /app/sql - -# Set ownership -RUN chown -R appuser:appuser /app - -# Switch to non-root user -USER appuser - -# Set working directory -WORKDIR /app - -# Run migrations by default -CMD ["./migrate", "up"] \ No newline at end of file diff --git a/docker/push.sh b/docker/push.sh index 7804c5b..768a3f0 100755 --- a/docker/push.sh +++ b/docker/push.sh @@ -1,128 +1,83 @@ #!/bin/bash -# GitDataAI Docker Push Script - set -e -# Get version from Cargo.toml PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)" CARGO_VERSION=$(grep -m1 'version' "${PROJECT_ROOT}/Cargo.toml" | sed 's/.*"\(.*\)".*/\1/') -# Configuration -REGISTRY=${REGISTRY:-""} +REGISTRY=${REGISTRY:-"harbor.gitdata.me/app"} TAG=${TAG:-"${CARGO_VERSION:-latest}"} -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color +if command -v podman &>/dev/null; then + DOCKER=podman +elif command -v docker &>/dev/null; then + DOCKER=docker +else + echo "ERROR: neither podman nor docker found" + exit 1 +fi -# Services to push -SERVICES=("gitdata" "email" "gitpod" "gitsync" "migrate" "web") +SERVICES=("gitdata" "gitpod" "gitsync" "email" "web") -# Function to print colored output -log_info() { - echo -e "${GREEN}[INFO]${NC} $1" -} +log_info() { echo -e "\033[0;32m[INFO]\033[0m $1"; } +log_warn() { echo -e "\033[1;33m[WARN]\033[0m $1"; } +log_error() { echo -e "\033[0;31m[ERROR]\033[0m $1"; } -log_warn() { - echo -e "${YELLOW}[WARN]${NC} $1" -} - -log_error() { - echo -e "${RED}[ERROR]${NC} $1" -} - -# Function to push a service -push_service() { +push_image() { local service=$1 - local image_name="gitdata-${service}" + local image="${REGISTRY}/gitdata-${service}:${TAG}" - # Add registry prefix if set - if [ -n "$REGISTRY" ]; then - image_name="${REGISTRY}/${image_name}" - fi - - log_info "Pushing ${service}..." - - # Check if image exists locally - if ! docker image inspect "${image_name}:${TAG}" > /dev/null 2>&1; then - log_error "Image not found: ${image_name}:${TAG}" - log_error "Please build the image first with: ./build.sh ${service}" + if ! $DOCKER image inspect "$image" >/dev/null 2>&1; then + log_error "Image not found: $image" + log_error "Build first: ./build.sh $service" return 1 fi - docker push "${image_name}:${TAG}" - - log_info "Successfully pushed ${image_name}:${TAG}" + log_info "Pushing $image" + $DOCKER push "$image" + log_info "Pushed $image" } -# Parse command line arguments PUSH_SERVICES=() PUSH_ALL=true while [[ $# -gt 0 ]]; do case $1 in - --tag|-t) - TAG="$2" - shift 2 - ;; - --registry|-r) - REGISTRY="$2" - shift 2 - ;; + --tag|-t) TAG="$2"; shift 2 ;; + --registry|-r) REGISTRY="$2"; shift 2 ;; --help|-h) echo "Usage: $0 [OPTIONS] [SERVICE...]" echo "" echo "Options:" - echo " -t, --tag TAG Docker image tag (default: latest)" - echo " -r, --registry REG Docker registry prefix (required)" - echo " -h, --help Show this help message" + echo " -t, --tag TAG Image tag (default: from Cargo.toml)" + echo " -r, --registry REG Registry prefix (default: harbor.gitdata.me/app)" echo "" echo "Services:" - echo " gitdata Main API service" - echo " email Email service" - echo " gitpod GitPod service" - echo " gitsync GitSync service" - echo " migrate Database migration" - echo " web Web frontend" + echo " gitdata gitpod gitsync email web" echo "" echo "Examples:" - echo " $0 -r registry.com # Push all services" - echo " $0 -r registry.com gitdata web # Push specific services" - echo " $0 -r registry.com -t v1.0.0 # Push with custom tag" + echo " $0 # Push all" + echo " $0 gitdata gitpod # Push specific services" + echo " $0 -t v1.2.0 # Push with custom tag" + echo " $0 -r myreg.io/app -t dev # Push with custom registry and tag" exit 0 ;; - *) - PUSH_SERVICES+=("$1") - PUSH_ALL=false - shift - ;; + *) PUSH_SERVICES+=("$1"); PUSH_ALL=false; shift ;; esac done -# Validate registry -if [ -z "$REGISTRY" ]; then - log_error "Registry is required. Use -r or --registry to specify." - echo "Example: $0 -r registry.com" - exit 1 -fi - -# Push services -log_info "Starting Docker push..." log_info "Registry: ${REGISTRY}" -log_info "Tag: ${TAG}" +log_info "Tag: ${TAG}" if [ "$PUSH_ALL" = true ]; then log_info "Pushing all services..." - for service in "${SERVICES[@]}"; do - push_service "$service" + for svc in "${SERVICES[@]}"; do + push_image "$svc" done else - log_info "Pushing specified services: ${PUSH_SERVICES[*]}" - for service in "${PUSH_SERVICES[@]}"; do - push_service "$service" + log_info "Pushing: ${PUSH_SERVICES[*]}" + for svc in "${PUSH_SERVICES[@]}"; do + push_image "$svc" done fi -log_info "Push completed successfully!" \ No newline at end of file +log_info "Done." diff --git a/docker/web.Dockerfile b/docker/web.Dockerfile index a45e549..11c6645 100644 --- a/docker/web.Dockerfile +++ b/docker/web.Dockerfile @@ -1,62 +1,30 @@ -# GitDataAI Frontend Dockerfile -# Multi-stage build for React application with Bun +FROM oven/bun:1 AS builder -# Stage 1: Build the application -FROM node:24-bookworm AS builder - -# Install bun -RUN npm install -g bun - -# Create app directory WORKDIR /app -# Copy package files COPY package.json bun.lock ./ - -# Install dependencies RUN bun install --frozen-lockfile -# Copy source code COPY src/ src/ COPY public/ public/ -COPY index.html ./ -COPY vite.config.ts ./ -COPY tsconfig*.json ./ -COPY eslint.config.js ./ -COPY components.json ./ -COPY orval.config.ts ./ +COPY index.html vite.config.ts tsconfig*.json eslint.config.js components.json orval.config.ts ./ -# Build the application RUN bun run build -# Stage 2: Create runtime image with Nginx FROM nginx:alpine -# Copy custom nginx configuration COPY docker/nginx.conf /etc/nginx/conf.d/default.conf - -# Copy built assets from builder COPY --from=builder /app/dist /usr/share/nginx/html -# Create non-root user -RUN adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx appuser +RUN adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx appuser \ + && chown -R appuser:nginx /var/cache/nginx /var/log/nginx /etc/nginx/conf.d \ + && touch /var/run/nginx.pid && chown appuser:nginx /var/run/nginx.pid -# Set ownership -RUN chown -R appuser:nginx /var/cache/nginx \ - && chown -R appuser:nginx /var/log/nginx \ - && chown -R appuser:nginx /etc/nginx/conf.d \ - && touch /var/run/nginx.pid \ - && chown -R appuser:nginx /var/run/nginx.pid - -# Switch to non-root user USER appuser -# Expose port EXPOSE 80 -# Health check HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:80/ || exit 1 -# Start Nginx -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file +CMD ["nginx", "-g", "daemon off;"]