Skip to content

Commit 9321597

Browse files
authored
ci: Add Docker support and deployment workflows (#12)
- Add Dockerfile for containerization - Add GitHub workflow for automated Docker image publishing - Add release workflow for managing releases
1 parent 8e86098 commit 9321597

File tree

3 files changed

+190
-0
lines changed

3 files changed

+190
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Build and Publish Docker Image
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
env:
10+
REGISTRY: ghcr.io
11+
IMAGE_NAME: ${{ github.repository }}
12+
13+
jobs:
14+
build-and-push:
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: read
18+
packages: write
19+
20+
steps:
21+
- name: Checkout repository
22+
uses: actions/checkout@v4
23+
24+
- name: Set up Docker Buildx
25+
uses: docker/setup-buildx-action@v3
26+
27+
- name: Log in to the Container registry
28+
uses: docker/login-action@v3
29+
with:
30+
registry: ${{ env.REGISTRY }}
31+
username: ${{ github.actor }}
32+
password: ${{ secrets.GITHUB_TOKEN }}
33+
34+
- name: Extract metadata (tags, labels) for Docker
35+
id: meta
36+
uses: docker/metadata-action@v5
37+
with:
38+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
39+
tags: |
40+
type=sha,format=short
41+
type=ref,event=branch
42+
type=ref,event=pr
43+
type=semver,pattern={{version}}
44+
type=semver,pattern={{major}}.{{minor}}
45+
type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'main') }}
46+
47+
- name: Build and push Docker image
48+
uses: docker/build-push-action@v5
49+
with:
50+
context: .
51+
push: ${{ github.event_name != 'pull_request' }}
52+
tags: ${{ steps.meta.outputs.tags }}
53+
labels: ${{ steps.meta.outputs.labels }}
54+
cache-from: type=gha
55+
cache-to: type=gha,mode=max

.github/workflows/release.yml

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Create Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version:
7+
description: 'Version to release (e.g., v1.0.0)'
8+
required: true
9+
type: string
10+
11+
jobs:
12+
check-branch:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Check if running on main branch
16+
if: github.ref != 'refs/heads/main'
17+
run: |
18+
echo "This workflow can only be run on the main branch"
19+
exit 1
20+
21+
release:
22+
needs: check-branch
23+
runs-on: ubuntu-latest
24+
permissions:
25+
contents: write
26+
packages: write
27+
28+
steps:
29+
- name: Checkout code
30+
uses: actions/checkout@v4
31+
with:
32+
fetch-depth: 0
33+
34+
- name: Set up Python
35+
uses: actions/setup-python@v5
36+
with:
37+
python-version: '3.12'
38+
39+
- name: Install dependencies
40+
run: |
41+
python -m pip install --upgrade pip
42+
pip install uv
43+
uv pip install -e ".[dev]"
44+
45+
- name: Create GitHub Release
46+
id: create_release
47+
uses: actions/create-release@v1
48+
env:
49+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
50+
with:
51+
tag_name: ${{ github.event.inputs.version }}
52+
release_name: Release ${{ github.event.inputs.version }}
53+
draft: false
54+
prerelease: false
55+
56+
- name: Build and tag Docker image with release version
57+
env:
58+
REGISTRY: ghcr.io
59+
IMAGE_NAME: ${{ github.repository }}
60+
run: |
61+
docker build -t $REGISTRY/$IMAGE_NAME:${{ github.event.inputs.version }} .
62+
docker build -t $REGISTRY/$IMAGE_NAME:latest .
63+
64+
- name: Push Docker image
65+
env:
66+
REGISTRY: ghcr.io
67+
IMAGE_NAME: ${{ github.repository }}
68+
run: |
69+
echo ${{ secrets.GITHUB_TOKEN }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin
70+
docker push $REGISTRY/$IMAGE_NAME:${{ github.event.inputs.version }}
71+
docker push $REGISTRY/$IMAGE_NAME:latest

Dockerfile

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
FROM python:3.12-slim AS builder
2+
3+
# Install uv
4+
RUN pip install uv
5+
6+
# Set work directory
7+
WORKDIR /app
8+
9+
# Copy only what's needed for installation
10+
COPY pyproject.toml uv.lock ./
11+
COPY src/ ./src/
12+
13+
# Install dependencies using uv with --system flag
14+
RUN uv pip install --system --no-cache-dir .
15+
16+
# Create a lightweight runtime image
17+
FROM python:3.12-slim AS runtime
18+
19+
# Set work directory
20+
WORKDIR /app
21+
22+
# Copy only the installed packages and application code
23+
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
24+
COPY --from=builder /usr/local/bin /usr/local/bin
25+
COPY --from=builder /app/src /app/src
26+
27+
# Create log directory
28+
RUN mkdir -p /app/log
29+
30+
# Define build arguments with default values
31+
ARG OPENAI_BASE_URL_INTERNAL=http://localhost:8000
32+
ARG OPENAI_BASE_URL=http://localhost:8080
33+
ARG OPENAI_API_KEY=sk-fakekey
34+
ARG API_ADAPTER_HOST=0.0.0.0
35+
ARG API_ADAPTER_PORT=8080
36+
ARG LOG_LEVEL=INFO
37+
ARG LOG_FILE_PATH=/app/log/api_adapter.log
38+
39+
# Set environment variables from build arguments
40+
ENV PYTHONUNBUFFERED=1 \
41+
PYTHONDONTWRITEBYTECODE=1 \
42+
# OpenAI API Configuration
43+
OPENAI_BASE_URL_INTERNAL=${OPENAI_BASE_URL_INTERNAL} \
44+
OPENAI_BASE_URL=${OPENAI_BASE_URL} \
45+
OPENAI_API_KEY=${OPENAI_API_KEY} \
46+
# Server Configuration
47+
API_ADAPTER_HOST=${API_ADAPTER_HOST} \
48+
API_ADAPTER_PORT=${API_ADAPTER_PORT} \
49+
# Logging Configuration
50+
LOG_LEVEL=${LOG_LEVEL} \
51+
LOG_FILE_PATH=${LOG_FILE_PATH}
52+
53+
# Create entrypoint script for proper environment variable handling
54+
RUN echo '#!/bin/sh\nexec uvicorn openai_responses_server.server:app --host $API_ADAPTER_HOST --port $API_ADAPTER_PORT "$@"' > /app/entrypoint.sh && \
55+
chmod +x /app/entrypoint.sh
56+
57+
# Create non-root user for security and set permissions
58+
RUN adduser --disabled-password --gecos "" appuser && \
59+
chown -R appuser:appuser /app/log && \
60+
chown appuser:appuser /app/entrypoint.sh
61+
USER appuser
62+
63+
# Use JSON array format for CMD with entrypoint script
64+
CMD ["sh", "/app/entrypoint.sh"]

0 commit comments

Comments
 (0)