Skip to content

Docker support#4

Open
ngoyal16 wants to merge 13 commits intoAsyncFuncAI:mainfrom
ngoyal16:docker-support-2753185481020516427
Open

Docker support#4
ngoyal16 wants to merge 13 commits intoAsyncFuncAI:mainfrom
ngoyal16:docker-support-2753185481020516427

Conversation

@ngoyal16
Copy link

@ngoyal16 ngoyal16 commented Feb 5, 2026

What

Added comprehensive Docker support for the AsyncReview application, including a production-ready setup and a local development environment with hot-reloading.

Why

To enable users to run the application easily without manually installing dependencies (Python, Node.js, Deno) on their host machine, and to provide a consistent environment for both development and production.

How

  • Backend Dockerfile: Created Dockerfile.backend using python:3.11-slim, installing uv and deno for the runtime environment.
  • Frontend Dockerfile: Created web/Dockerfile with a multi-stage build (Dev, Build, Prod) to optimize image size and build times.
  • Production Compose: docker-compose.yml orchestrates the backend and frontend, with Nginx serving the frontend and proxying API requests on port 3000.
  • Dev Compose: docker-compose.dev.yml overrides the setup to expose the backend on port 8000 and enable hot-reloading for both services.
  • Configuration: Updated web/vite.config.ts to accept API_URL from the environment.
  • Documentation: Added DOCKER.md with usage instructions and updated Makefile with convenience commands.

Testing

  • Tests added/updated (Frontend type fixes)
  • Manual testing done (Verified builds and configuration)

Checklist

  • Code follows project style
  • Self-reviewed
  • No breaking changes (or documented)

google-labs-jules bot and others added 5 commits February 5, 2026 09:35
- Added `Dockerfile.backend` for Python/FastAPI backend (with uv and deno).
- Added `web/Dockerfile` for React/Vite frontend (multi-stage: dev, build, prod).
- Added `web/nginx.conf` for production serving of frontend.
- Added `docker-compose.yml` for immutable production deployment.
- Added `docker-compose.dev.yml` for local development with hot-reloading.
- Added `DOCKER.md` with instructions.
- Updated `web/vite.config.ts` to support dynamic API URL via env var.
- Updated `README.md` to link to Docker guide.

Co-authored-by: ngoyal16 <10145666+ngoyal16@users.noreply.github.com>
- Added `Dockerfile.backend` for Python/FastAPI backend (with uv and deno).
- Added `web/Dockerfile` for React/Vite frontend (multi-stage: dev, build, prod).
- Added `web/nginx.conf` for production serving of frontend.
- Added `docker-compose.yml` for immutable production deployment (Frontend on port 3000 proxies to Backend).
- Added `docker-compose.dev.yml` for local development (Hot-reload, ports 3000 and 8000 exposed).
- Updated `Makefile` with `docker-up` and `docker-dev` convenience targets.
- Added `DOCKER.md` with detailed instructions.
- Updated `web/vite.config.ts` to support dynamic API URL via env var.
- Updated `README.md` to link to Docker guide.

Co-authored-by: ngoyal16 <10145666+ngoyal16@users.noreply.github.com>
- Added `Dockerfile.backend` for Python/FastAPI backend (with uv and deno).
- Added `web/Dockerfile` for React/Vite frontend (multi-stage: dev, build, prod).
- Added `web/nginx.conf` for production serving of frontend.
- Added `docker-compose.yml` for immutable production deployment (Frontend on port 3000 proxies to Backend).
- Added `docker-compose.dev.yml` for local development (Hot-reload, ports 3000 and 8000 exposed).
- Updated `Makefile` with `docker-up` and `docker-dev` convenience targets.
- Added `DOCKER.md` with detailed instructions.
- Updated `web/vite.config.ts` to support dynamic API URL via env var.
- Updated `README.md` to link to Docker guide.
- Fixed TypeScript errors in `web/src/components/PRSummary.tsx` and `web/src/types.ts`.

Co-authored-by: ngoyal16 <10145666+ngoyal16@users.noreply.github.com>
Co-authored-by: ngoyal16 <10145666+ngoyal16@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@gemini-code-assist
Copy link

Summary of Changes

Hello @ngoyal16, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the deployment and development experience for the AsyncReview application by introducing robust Dockerization. The changes provide a consistent and isolated environment for running the application, eliminating the need for manual dependency installation on host machines and streamlining both production deployments and local development with features like hot-reloading.

Highlights

  • Comprehensive Docker Support: Introduced full Docker support for the AsyncReview application, enabling both production and local development environments.
  • New Dockerfiles and Compose Configurations: Added Dockerfile.backend for the Python backend, web/Dockerfile for the frontend (multi-stage build), docker-compose.yml for production, and docker-compose.dev.yml for development with hot-reloading.
  • Simplified Workflow with Makefile: Integrated new docker-up and docker-dev commands into the Makefile for easy startup of Dockerized environments.
  • Enhanced Frontend Configuration: Updated web/vite.config.ts to dynamically configure the API URL via an environment variable, improving flexibility for containerized deployments.
  • Detailed Docker Documentation: A new DOCKER.md guide has been added, providing instructions for setting up and using Docker for AsyncReview, including troubleshooting tips.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • DOCKER.md
    • Added new documentation detailing Docker setup for production and development, including prerequisites, quick start commands, CLI usage, and troubleshooting.
  • Dockerfile.backend
    • Added a new Dockerfile for the Python backend, based on python:3.11-slim.
    • Includes installation of system dependencies (curl, unzip), uv package installer, and Deno runtime.
    • Sets up the working directory, copies application files, installs Python dependencies, and caches Deno dependencies.
    • Exposes port 8000 and defines the default command to run the Uvicorn server.
  • Makefile
    • Added new .PHONY targets: docker-up and docker-dev.
    • Implemented docker-up command to start the production Docker Compose setup, including a check for the .env file.
    • Implemented docker-dev command to start the development Docker Compose setup with hot-reloading, also checking for the .env file.
    • Updated the help target to include the new Docker commands.
  • README.md
    • Added a link to the new DOCKER.md for Docker-specific instructions.
  • docker-compose.dev.yml
    • Added a new Docker Compose file for development, overriding the main docker-compose.yml.
    • Configures the backend service with volume mounts for hot-reloading and exposes port 8000.
    • Configures the frontend service to use the dev target of its Dockerfile, mounts web directory, exposes port 5173, and sets API_URL.
  • docker-compose.yml
    • Added a new Docker Compose file for production.
    • Defines a backend service using Dockerfile.backend, loading environment variables from .env, and ensuring restart on failure.
    • Defines a frontend service using the prod target of web/Dockerfile, exposing port 3000, depending on the backend, and ensuring restart on failure.
  • web/Dockerfile
    • Added a new multi-stage Dockerfile for the frontend.
    • Includes base stage for installing Node.js dependencies.
    • Defines dev stage for development server with exposed port 5173.
    • Defines build stage for creating optimized production build.
    • Defines prod stage using Nginx to serve the built frontend and custom nginx.conf.
  • web/nginx.conf
    • Added a new Nginx configuration file for the frontend production server.
    • Configures Nginx to serve static files, support SPA routing, and proxy API requests to the backend service.
    • Includes specific headers and settings for Server-Sent Events (SSE) support.
  • web/package-lock.json
    • Updated package-lock.json to include new platform-specific optional dependencies for esbuild and @rollup/rollup.
  • web/src/components/PRSummary.tsx
    • Minor refactor in PRSummary component, removing unused index parameter from commitsList.map.
  • web/src/types.ts
    • Added an optional changedFiles property to the PRInfo interface.
  • web/vite.config.ts
    • Modified the Vite proxy configuration to use process.env.API_URL as the target, falling back to http://localhost:8000.
Activity
  • The author has added comprehensive Docker support for the application.
  • Frontend type fixes were implemented as part of the changes.
  • Manual testing was performed to verify builds and configurations.
  • The code adheres to the project's style guidelines.
  • The author has self-reviewed the changes.
  • No breaking changes were introduced, or they have been documented.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces comprehensive Docker support, which is an excellent addition for improving developer experience and ensuring deployment consistency. However, it introduces critical security vulnerabilities as the API is exposed without authentication, and both the backend and frontend containers run with root privileges, making it unsafe for non-local environments. Additionally, there are opportunities to enhance the Docker setup for better reproducibility, performance, and robustness, such as pinning dependency versions, optimizing Docker layer caching, and adding healthchecks to the services.

Comment on lines 23 to 29
COPY pyproject.toml README.md ./
COPY cr/ ./cr/
COPY cli/ ./cli/

# Install python dependencies
# We use --system to install into the container's system python environment
RUN uv pip install --system .

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

To improve Docker build performance and leverage layer caching, it's recommended to copy dependency files and install dependencies in a separate layer before copying the application source code. The current setup copies all source code before installing dependencies, which invalidates the cache on any file change, forcing a re-installation of all dependencies.

A better structure would be:

# Copy dependency manifest
COPY pyproject.toml ./

# Install dependencies
RUN uv pip install ... # Command to install from pyproject.toml

# Copy source code
COPY . .

The uv pip install --system . command complicates this pattern as it requires the source code. Consider exploring ways to install dependencies from pyproject.toml without the full source code present, for example by generating a requirements.txt during your build. This will significantly speed up rebuilds.

Comment on lines +37 to +38
# Default command
CMD ["uvicorn", "cr.server:app", "--host", "0.0.0.0", "--port", "8000"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The backend container runs as the root user by default. This violates the principle of least privilege and increases the security risk; if the application is compromised, the attacker would have full root access within the container. It is recommended to create a non-root user and switch to it using the USER instruction.

RUN useradd -m -u 1000 appuser
USER appuser

# Default command
CMD ["uvicorn", "cr.server:app", "--host", "0.0.0.0", "--port", "8000"]

Comment on lines 20 to 25
FROM nginx:alpine AS prod
COPY --from=build /app/dist /usr/share/nginx/html
# We will copy a custom nginx config to handle SPA routing and API proxying
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

The production Nginx container runs as root to bind to port 80. For improved security, it is recommended to use a non-root Nginx image (like nginxinc/nginx-unprivileged) or configure Nginx to run as a non-root user and bind to a higher port (e.g., 8080).


# Install uv
# explicit path to ensure it's available
COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For reproducible builds, it's a best practice to pin dependencies to a specific version instead of using the :latest tag. This prevents unexpected build failures if a breaking change is introduced in a new version of the tool.

COPY --from=ghcr.io/astral-sh/uv:0.2.3 /uv /bin/uv

- .env
environment:
- PYTHONUNBUFFERED=1
restart: unless-stopped

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To make your service orchestration more robust, consider adding a healthcheck to the backend service. This ensures that dependent services, like the frontend, don't start until the backend is actually healthy and ready to accept traffic. Your application already exposes a /health endpoint that is perfect for this.

    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

Comment on lines +19 to +20
depends_on:
- backend

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To complement the backend healthcheck, you should update depends_on to wait for the backend service to be healthy before starting the frontend. This prevents race conditions on startup.

    depends_on:
      backend:
        condition: service_healthy

@sashimikun
Copy link

🔍 AsyncReview Analysis

Code Review Summary

Files reviewed: 6 files (Docker configuration and documentation)
Overall assessment: REQUEST_CHANGES

The PR adds necessary Docker support, which is great for developer experience. However, the current implementation contains critical security risks (running containers as root) and production quality issues (unpinned versions, large image sizes, missing security headers) that must be addressed before merging to main.


Findings

P0 - Critical

  • [Dockerfile.backend:1] Security: Running as Root

    • The container runs as the default root user. If the application is compromised, the attacker gains root access to the container.
    • Fix: Create a non-privileged user (e.g., appuser) and switch to it using the USER instruction.
  • [web/Dockerfile:27] Security: Running as Root (Nginx)

    • The production Nginx container runs as root. Standard security practice requires running as an unprivileged user.
    • Fix: Use a non-root user and bind to a high port (e.g., 8080) instead of 80.

P1 - High

  • [Dockerfile.backend:4] Security: Remote Script Execution

    • Installing Deno via curl ... | sh poses a supply chain risk.
    • Fix: Download a specific version/checksum or use a multi-stage copy from a verified image.
  • [Dockerfile.backend:1] Quality: Unpinned Base Images

    • Uses python:3.11-slim and uv:latest. This leads to non-reproducible builds.
    • Fix: Pin to specific patch versions (e.g., python:3.11.9-slim-bookworm, uv:0.5.1).
  • [Dockerfile.backend] Quality: Lack of Multi-stage Build

    • The image includes build tools (curl, unzip, uv) and cached files in the final layer, resulting in a large image size.
    • Fix: Use a multi-stage build (Builder -> Runtime).
  • [web/nginx.conf] Security: Missing Security Headers

    • Missing X-Frame-Options, Content-Security-Policy, and HSTS headers.
    • Fix: Explicitly add these headers in the server block.
  • [web/nginx.conf] Stability: Missing Resource Limits

    • No client_max_body_size set. Defaults to 1MB (might break uploads) or allows unlimited if misconfigured.
    • Fix: Set an explicit limit (e.g., 10M).

P2 - Medium

  • [docker-compose.yml] Security: Port Exposure
    • Exposes port 80 directly. Ensure this is behind a load balancer terminating TLS in production.
  • [web/Dockerfile] Quality: Mixed Environments
    • dev and prod stages in one file increase complexity. Ensure target is always specified in build commands.

Fix Suggestions (P0/P1 only)

Refactored Dockerfile.backend (Multi-stage, Non-root, Pinned)

# Stage 1: Builder
FROM python:3.11.9-slim-bookworm AS builder

# Pin uv version
COPY --from=ghcr.io/astral-sh/uv:0.5.1 /uv /bin/uv
WORKDIR /build

# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl ca-certificates unzip \
    && rm -rf /var/lib/apt/lists/*

# Install Deno (Manual install to avoid curl|sh risk)
ENV DENO_VERSION=1.46.3
RUN curl -fsSL https://github.com/denoland/deno/releases/download/v${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip \
    -o deno.zip && unzip deno.zip && mv deno /usr/local/bin/deno && rm deno.zip

# Cache Python dependencies
COPY pyproject.toml ./
RUN uv pip install --system --no-cache .

# Copy source and reinstall to include local packages
COPY README.md ./
COPY cr/ ./cr/
COPY cli/ ./cli/
RUN uv pip install --system --no-cache .

# Stage 2: Runtime
FROM python:3.11.9-slim-bookworm AS runtime

# Create non-root user
RUN groupadd -g 10001 appgroup && \
    useradd -u 10001 -g appgroup -m -s /sbin/nologin appuser

ENV PATH="/usr/local/bin:$PATH" \
    PYTHONUNBUFFERED=1

WORKDIR /app

# Copy artifacts from builder
COPY --from=builder /usr/local/bin/deno /usr/local/bin/deno
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=builder /build/cr ./cr

# Switch to non-root user
USER appuser

EXPOSE 8000
CMD ["uvicorn", "cr.server:app", "--host", "0.0.0.0", "--port", "8000"]

Hardened web/nginx.conf

server {
    listen 80;
    server_name localhost;

    # P1 Fix: Security Headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self';" always;

    # P1 Fix: DoS Protection
    client_max_body_size 10M;

    location / {
        root /usr/share/nginx/html;
        index index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://backend:8000/api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Timeout settings
        proxy_read_timeout 300s;
    }

    # ... (rest of config)
}

Additional Notes

  • Testing: Please verify that the hot-reloading in docker-compose.dev.yml still works with the new user permissions (files mounted from host might have ownership issues on Linux).
  • Secrets: Double-check that .env is listed in .gitignore to prevent accidental commits of API keys.

Generated by AsyncReview using gemini/gemini-3-pro-preview

ngoyal16 and others added 7 commits February 6, 2026 07:38
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@ngoyal16
Copy link
Author

ngoyal16 commented Feb 6, 2026

@sashimikun can you please review the updated changes and do let me know if someting else needs to be done

@sashimikun
Copy link

🔍 AsyncReview Analysis

The PR looks very promising and implements several best practices, but there is a critical missing file that needs to be addressed before merging.

🔴 Changes Requested

1. Missing .dockerignore
You are performing COPY . . in Dockerfile.backend and web/Dockerfile, but I do not see a .dockerignore file in the root or web/ directory.

  • Why this matters: Without it, you are copying local artifacts like __pycache__, .venv, .git, node_modules, and potentially sensitive .env files into your image. This leads to bloated images, cache invalidation issues, and security risks.
  • Action: Please add a .dockerignore file excluding:
    .git
    .venv
    __pycache__
    node_modules
    .env
    dist
    coverage
    

2. Verify web/vite.config.ts
The PR description mentions updating vite.config.ts to accept API_URL, but I cannot verify this change in the diff.

  • Action: Please ensure the frontend build actually uses the API_URL environment variable so that the production Nginx container proxies requests correctly to the backend service.

✅ specific approvals

  • Security: Excellent job pinning versions (python:3.11.8, uv:0.5.29, deno v1.40.3) and implementing non-root users (appuser, nginx) in the production images.
  • Nginx Config: The web/nginx.conf is well-configured with security headers and correctly proxies /api to the backend.
  • Dev Experience: The docker-compose.dev.yml setup with hot-reloading (using anonymous volumes for node_modules) is a solid developer experience improvement.

Generated by AsyncReview using gemini/gemini-3-pro-preview

Co-authored-by: google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com>
@ngoyal16
Copy link
Author

ngoyal16 commented Feb 8, 2026

@sashimikun i have added .dockerignore file also i confirm that their is API base url is their in the vite config file.

do let me know if anything is missing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants