Skip to content

Conversation

@SSinist3r
Copy link

@SSinist3r SSinist3r commented Jan 6, 2026

This PR adds the docker support with updated documentation for docker deployment and it also auto build and push docker images to ghcr.io github registry.


Important

Adds Docker support with CI/CD for LLM-API-Key-Proxy, including Dockerfiles, GitHub Actions, and updated documentation for deployment and OAuth management.

  • Docker Support:
    • Adds Dockerfile for building the application image.
    • Adds docker-compose.yml and docker-compose.dev.yml for production and development setups.
    • Configures volume mounts for .env, oauth_creds, logs, and key_usage.json.
  • CI/CD:
    • Adds .github/workflows/docker-build.yml to automate Docker image build and push to GitHub Container Registry on main and dev branch pushes.
    • Includes steps for QEMU setup, Docker Buildx, and image tagging.
  • Documentation:
    • Updates README.md and Deployment guide.md with Docker deployment instructions.
    • Provides guidance on OAuth credential management and environment variable setup for Docker.

This description was created by Ellipsis for 0452066. You can customize this summary. It will automatically update as commits are pushed.

@SSinist3r SSinist3r requested a review from Mirrowel as a code owner January 6, 2026 07:14
@SSinist3r SSinist3r changed the base branch from main to dev January 6, 2026 07:16
@SSinist3r SSinist3r changed the title Update documentation with Docker deployment guide and format improvements Docker Support with updated documentation with Docker deployment guide Jan 6, 2026
Repository owner deleted a comment from mirrobot-agent bot Jan 6, 2026
@mirrobot-agent
Copy link
Contributor

mirrobot-agent bot commented Jan 6, 2026

Starting my review of the Docker support PR. I'll be analyzing the Dockerfile, CI workflow, compose files, and documentation updates. Will report back with findings shortly.

Copy link
Contributor

@mirrobot-agent mirrobot-agent bot left a comment

Choose a reason for hiding this comment

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

Overall Assessment

This is a well-structured PR that adds comprehensive Docker support to the project. The implementation follows Docker best practices with multi-stage builds, proper layer caching, and multi-architecture support. The CI/CD pipeline is solid with automatic image publishing and cleanup.

Strengths:

  • Clean multi-stage Dockerfile with proper dependency caching
  • Thoughtful CI workflow with path filtering and artifact attestation
  • Comprehensive documentation covering both compose and manual deployment
  • Good separation between production (docker-compose.yml) and development (docker-compose.dev.yml) configurations

Key Suggestions

  1. key_usage.json mount — The compose file mounts this as a bind mount, which will create a directory if the file doesn't exist. Consider adding a note or handling this edge case.

  2. Non-root user — The container runs as root, which works but is worth hardening for production.

  3. Dynamic package name — Minor consistency improvement in the cleanup job.

Architectural Feedback

The approach is sound. Using GHCR for image hosting with automatic builds on push is the right choice for this project. The separation of concerns between the build workflow and compose files is clean.

Nitpicks and Minor Points

  • The .dockerignore excludes .github/ which is correct, but note that workflow changes won't trigger rebuilds (the path filter correctly only watches the workflow file itself).
  • The documentation updates include many formatting fixes beyond Docker — this is fine but makes the diff larger than the feature scope.

Questions for the Author

  • Should a HEALTHCHECK instruction be added to the Dockerfile for better container orchestration support?
  • Is there a reason the docker-compose*.yml files aren't included in the workflow path triggers? Changes to compose wouldn't require a rebuild, but just confirming this is intentional.

This review was generated by an AI assistant.

# Mount logs directory for persistent logging
- ./logs:/app/logs
# Mount key_usage.json for usage statistics persistence
- ./key_usage.json:/app/key_usage.json
Copy link
Contributor

Choose a reason for hiding this comment

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

Potential startup issue: Mounting key_usage.json directly will create a directory if the file does not exist on the host. Consider either:

  1. Adding a note to the Quick Start section about running touch key_usage.json before docker compose up, or
  2. Using a bind mount with explicit file creation check

The manual Docker run documentation mentions touch key_usage.json, but this could easily be missed by users going straight to Docker Compose.

Comment on lines +24 to +49
FROM python:3.11-slim

WORKDIR /app

# Copy installed packages from builder
COPY --from=builder /root/.local /root/.local

# Make sure scripts in .local are usable
ENV PATH=/root/.local/bin:$PATH

# Copy application code
COPY src/ ./src/

# Create directories for logs and oauth credentials
RUN mkdir -p logs oauth_creds

# Expose the default port
EXPOSE 8000

# Set environment variables
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONPATH=/app/src

# Default command - runs proxy with the correct PYTHONPATH
CMD ["python", "src/proxy_app/main.py", "--port", "8000"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Security consideration: The container runs as root user. While this works fine, running as a non-root user is a best practice for production deployments.

This is non-blocking — the current setup works, but consider adding a non-root user for security hardening in a future iteration:

RUN useradd --create-home appuser
USER appuser

- name: Delete old container images
uses: actions/delete-package-versions@v5
with:
package-name: llm-api-key-proxy
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor maintainability note: The package-name is hardcoded as llm-api-key-proxy, while IMAGE_NAME uses github.repository dynamically. If the repository is ever forked or renamed, this cleanup job would fail silently.

Consider using dynamic extraction:

Suggested change
package-name: llm-api-key-proxy
package-name: ${{ github.event.repository.name }}

@Mirrowel
Copy link
Owner

Mirrowel commented Jan 8, 2026

@mirrobot-agent. So, how ready is this? I assume this can be merged(after resolving). Resolve conflicts here, and provide an overview of what this PR does and accomplishes, and how.

@mirrobot-agent
Copy link
Contributor

mirrobot-agent bot commented Jan 8, 2026

@Mirrowel, I'm checking the current state of this PR to assess its merge readiness. I'll:

  1. Check for any merge conflicts
  2. Review the current branch status
  3. Provide a comprehensive overview of what this PR accomplishes

Starting the analysis now.

@mirrobot-agent
Copy link
Contributor

mirrobot-agent bot commented Jan 8, 2026

@Mirrowel, I've resolved the merge conflicts and the PR is now ready for merge!


✅ Conflicts Resolved

The conflicts in README.md have been fixed. The issue was a clash between:

  1. Docker PR's table formatting in the Advanced Features section
  2. Upstream dev's additions of GEMINI_CLI_QUOTA_REFRESH_INTERVAL and ANTIGRAVITY_QUOTA_REFRESH_INTERVAL environment variables

I merged both changes, preserving the clean table formatting from this PR while including the new quota variables from upstream.


📋 PR Overview: Docker Support

This PR adds comprehensive Docker containerization to the LLM-API-Key-Proxy project. Here's what it accomplishes:

What's Added

File Purpose
Dockerfile Multi-stage build optimized for production (~50 lines)
docker-compose.yml Production deployment using pre-built GHCR image
docker-compose.dev.yml Local development with live builds
.dockerignore Optimized build context (excludes logs, creds, .git, etc.)
.github/workflows/docker-build.yml Automated CI/CD pipeline
README.md / Deployment guide.md Documentation updates

Key Features

1. Multi-Stage Dockerfile

  • Uses python:3.11-slim base image
  • Builder stage compiles dependencies, production stage is minimal
  • Creates proper directory structure (logs/, oauth_creds/)
  • Exposes port 8000 with sensible defaults

2. Docker Compose Files

  • Production (docker-compose.yml): Pulls from ghcr.io/mirrowel/llm-api-key-proxy:latest
  • Development (docker-compose.dev.yml): Builds locally for testing
  • Both include:
    • Volume mounts for .env, oauth_creds/, logs/, key_usage.json
    • Automatic restart policy (unless-stopped)
    • Log rotation (10MB, 3 files)
    • SKIP_OAUTH_INIT_CHECK=true for non-interactive container startup

3. CI/CD Workflow (docker-build.yml)

  • Triggers on pushes to main and dev branches
  • Multi-architecture builds: linux/amd64 and linux/arm64
  • Smart tagging:
    • latest for main branch
    • dev-latest for dev branch
    • Timestamped versions: YYYYMMDD-HHMMSS-<sha>
  • Artifact attestation for supply chain security
  • Automatic cleanup: keeps 20 most recent images, preserves *latest* tags

4. Documentation

  • Added Docker Quick Start section to README
  • Comprehensive deployment instructions in Deployment guide.md
  • Covers: Docker Compose, manual docker run, OAuth with containers

📊 Merge Readiness

Check Status
Merge conflicts ✅ Resolved
Mergeable state MERGEABLE
CI/CD ⚠️ Blocked (likely awaiting approval or checks)

The PR is technically ready to merge. The BLOCKED status is typically due to branch protection rules requiring review approval.


💡 Previous Review Suggestions (from my Jan 6 review)

For future improvements, consider:

  1. Add touch key_usage.json step to Quick Start (prevents directory creation on bind mount)
  2. Non-root user in Dockerfile for production hardening
  3. Dynamic package name in cleanup job: use ${{ github.event.repository.name }} instead of hardcoded llm-api-key-proxy

These are non-blocking quality improvements that can be addressed in a follow-up PR.


This analysis and conflict resolution was performed by an AI assistant.

@Mirrowel
Copy link
Owner

Mirrowel commented Jan 8, 2026

@mirrobot-agent check this docker build against the existing build workflow. Logically, a docker build should closely mirror executable build workflow, publishing builds for different branches just like build does.

@mirrobot-agent
Copy link
Contributor

mirrobot-agent bot commented Jan 8, 2026

@Mirrowel, I'm comparing the Docker build workflow against the existing executable build workflow. I'll analyze:

  1. Branch handling and trigger conditions
  2. Publishing/tagging strategies for different branches
  3. Overall parity between the two workflows

Starting the analysis now.

@mirrobot-agent
Copy link
Contributor

mirrobot-agent bot commented Jan 8, 2026

@Mirrowel, I've completed my comparison of the Docker build workflow against the existing executable build workflow.


📊 Comparison Analysis

Aspect Executable Build (build.yml) Docker Build (docker-build.yml) Parity?
Branch Triggers All branches (unrestricted) Only main and dev ❌ No
Path Filters src/proxy_app/**, src/rotator_library/**, workflow file, cliff.toml Same paths + Dockerfile, requirements.txt ✅ Yes
Platforms Windows, Linux, macOS linux/amd64, linux/arm64 ✅ Appropriate
Version Format YYYYMMDD-BUILD_NUMBER-SHA YYYYMMDD-HHMMSS-SHA ⚠️ Slightly different
Branch-based Tagging {branch}/build-{version} latest (main) / {branch}-latest (others) ⚠️ Different scheme
Prerelease Handling Non-whitelisted branches → --prerelease + experimental warning None ❌ No
Latest Flag Only main gets --latest Only main gets latest tag ✅ Yes
Cleanup/Retention Smart pruning with daily snapshots Keep 20 versions, ignore *latest* ⚠️ Different strategy

🔍 Key Findings

1. Branch Restriction Mismatch ⚠️

Critical: The executable workflow runs on all branches, publishing releases for any branch with the appropriate prerelease/experimental flags. The Docker workflow is hardcoded to only main and dev:

# docker-build.yml (current)
on:
  push:
    branches: ["main", "dev"]
# build.yml (for comparison) - no branch restriction
on:
  push:
    paths:
      - 'src/proxy_app/**'
      ...

If you want parity, the Docker workflow should either:

  • Remove the branch restriction entirely, OR
  • Use a whitelist approach similar to the executable workflow's WHITELISTED_BRANCHES pattern

2. Missing Prerelease/Experimental Handling ⚠️

The executable workflow explicitly marks non-whitelisted branches as --prerelease and adds an experimental warning. The Docker workflow has no equivalent—all images are treated equally regardless of branch stability.

Recommendation: Add metadata labels or tag suffixes (like dev-unstable or experimental-) to clearly indicate non-production images.

3. Version Format Inconsistency (Minor)

  • Executable: YYYYMMDD-{build_number}-{sha} (e.g., 20260108-3-abc1234)
  • Docker: YYYYMMDD-{HHMMSS}-{sha} (e.g., 20260108-143025-abc1234)

The Docker format uses timestamp instead of build number, which is fine but differs from the executable pattern.

4. Already Noted: Hardcoded Package Name

My previous review mentioned that package-name: llm-api-key-proxy (line 122) should use ${{ github.event.repository.name }} for consistency with the dynamic IMAGE_NAME.


💡 Recommendations for Parity

If you want the Docker workflow to mirror the executable workflow's branch publishing behavior:

  1. Remove branch restriction (or make it dynamic):

    on:
      push:
        paths:
          - "src/proxy_app/**"
          - "src/rotator_library/**"
          - ".github/workflows/docker-build.yml"
          - "Dockerfile"
          - "requirements.txt"
  2. Add whitelist logic similar to WHITELISTED_BRANCHES:

    env:
      WHITELISTED_BRANCHES: "main"

    Then in the tagging step, add experimental/unstable labels for non-whitelisted branches.

  3. Consider adding prerelease-style metadata to images from non-main branches (e.g., OCI labels like org.opencontainers.image.version with "prerelease" notation).


🎯 Conclusion

The Docker workflow does not fully mirror the executable build workflow. The main gap is:

  • Branch handling: Executable publishes for all branches with prerelease flags; Docker is locked to main/dev only.

If you want full parity, the Docker workflow needs to remove the branch restriction and add prerelease-style handling for non-main branches.

Would you like me to make these changes to bring the Docker workflow into alignment with the executable workflow?

This analysis was generated by an AI assistant.

@Mirrowel
Copy link
Owner

Mirrowel commented Jan 9, 2026

It got closed for some reason when i merged something else. Reopened.
@MasuRii your fault.

@FammasMaz
Copy link

Would it be possible to add HTTPS/TLS support? I think it's essential considering macOS transport policy doesnt allow http connections anymore...

This could be done via:

  1. Adding nginx/Caddy as a reverse proxy
  2. Or adding native TLS support to the FastAPI app with certificate configuration

example on my fork: https://github.com/FammasMaz/LLM-API-Key-Proxy/blob/feature/docker-support/docker-compose.yml

@Mirrowel
Copy link
Owner

Would it be possible to add HTTPS/TLS support? I think it's essential considering macOS transport policy doesnt allow http connections anymore...

This could be done via:

  1. Adding nginx/Caddy as a reverse proxy
  2. Or adding native TLS support to the FastAPI app with certificate configuration

example on my fork: https://github.com/FammasMaz/LLM-API-Key-Proxy/blob/feature/docker-support/docker-compose.yml

I will take any docker PR as long as it is explained to me decently so I can make a decision. This one seems almost perfect and needs readme changes, but idk much about docker hosting - only running on noob level.

Just mostly mirror the build workflow so docker is made with it, same naming more or less.

- Change container name from llm-api-proxy to llm-api-proxy-dev in docker-compose.dev.yml
- Add new docker-compose.tls.yml file for TLS configuration
- Add instructions to create key_usage.json before running Docker Compose
- Include warning about Docker creating directory instead of file if key_usage.json doesn't exist
- Update both README.md and Deployment guide.md with the necessary steps
@SSinist3r
Copy link
Author

Would it be possible to add HTTPS/TLS support? I think it's essential considering macOS transport policy doesnt allow http connections anymore...

This could be done via:

  1. Adding nginx/Caddy as a reverse proxy
  2. Or adding native TLS support to the FastAPI app with certificate configuration

example on my fork: https://github.com/FammasMaz/LLM-API-Key-Proxy/blob/feature/docker-support/docker-compose.yml

added it docker-compose.tls.yml it your compose with just image update

@SSinist3r
Copy link
Author

SSinist3r commented Jan 11, 2026

@Mirrowel
So this pr adds a new github action workflow docker-build.yml

this workflow run on

on:
  push:
    branches: ["main", "dev"]
    paths:
      - "src/proxy_app/**"
      - "src/rotator_library/**"
      - ".github/workflows/docker-build.yml"
      - "Dockerfile"
      - "requirements.txt"

this is similar to build.yml just 2 extra files

  • ".github/workflows/docker-build.yml"
  • "Dockerfile"

this workflow build docker images for linux amd64 and arm64
with these tags

Branch Tags
main latest, YYYYMMDD-HHMMSS-short-sha
dev dev-latest, YYYYMMDD-HHMMSS-short-sha

example
ghcr.io/mirrowel/llm-api-key-proxy:latest
ghcr.io/mirrowel/llm-api-key-proxy:20250111-143052-a1b2c3d
ghcr.io/mirrowel/llm-api-key-proxy:dev-latest

The version tag format is DATE-TIME-SHORTSHA

after all this users can normally follow readme instructions and use desired docker-compose file

@Mirrowel
Copy link
Owner

@SSinist3r I see, thanks.

I see ports for oauth logging in are not routed. Is it even possible to use interactive log in in such a way?

Other than that. @FammasMaz anything else to add? Not a docker expert here, so asking for an opinion.

@kevincojean
Copy link

Personally, the base image I use is : FROM ghcr.io/astral-sh/uv:python3.11-bookworm
This uses UV as a build tool and speeds up downloading dependencies dramatically.

Cheers

@Mirrowel
Copy link
Owner

Personally, the base image I use is : FROM ghcr.io/astral-sh/uv:python3.11-bookworm This uses UV as a build tool and speeds up downloading dependencies dramatically.

Cheers

Not using uv is a crime indeed

@smashah
Copy link

smashah commented Jan 13, 2026

Any ETA on this PR?

@Mirrowel
Copy link
Owner

Any ETA on this PR?

I'll look into merging right now. Though, if docker stuff breaks i can't provide support for it - i don't use it or plan to.

- Add `workflow_dispatch` trigger to `docker-build.yml` to allow manual workflow execution with a configurable git ref.
- Upgrade `actions/checkout` version to v5 in `build.yml`.
@Mirrowel Mirrowel merged commit 088180f into Mirrowel:dev Jan 15, 2026
2 of 3 checks passed
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.

5 participants