diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2281254 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git/ +.venv/ +dist/ +tests/ +remotes.yaml +ca-bundle.pem +.env +*.log +docker-compose.yml +.woodpecker/ +.tox/ +.ruff_cache/ +.pytest_cache/ +.pre-commit-cache/ +minio_data/ diff --git a/.gitignore b/.gitignore index 7cb3658..50b8125 100644 --- a/.gitignore +++ b/.gitignore @@ -59,5 +59,4 @@ uv.lock minio_data/ # Local configuration overrides -docker-compose.yml ca-bundle.pem diff --git a/.woodpecker/build.yaml b/.woodpecker/build.yaml new file mode 100644 index 0000000..58b86d0 --- /dev/null +++ b/.woodpecker/build.yaml @@ -0,0 +1,9 @@ +when: + - event: pull_request + +steps: + - name: docker-build + image: woodpeckerci/plugin-docker-buildx + settings: + repo: git.unkin.net/unkin/artifactapi + dry_run: true diff --git a/.woodpecker/pre-commit.yaml b/.woodpecker/pre-commit.yaml index 75d1fca..448bd09 100644 --- a/.woodpecker/pre-commit.yaml +++ b/.woodpecker/pre-commit.yaml @@ -6,3 +6,4 @@ steps: image: git.unkin.net/unkin/almalinux9-base:20260308 commands: - uvx pre-commit run --all-files + diff --git a/Dockerfile b/Dockerfile index f259f52..7350c96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,53 +1,23 @@ -# Use Alpine Linux as base image -FROM python:3.11-alpine +FROM git.unkin.net/unkin/almalinux9-base:latest -# Set working directory -WORKDIR /app +ARG VERSION=0.0.0.dev0 -# Install system dependencies -RUN apk add --no-cache \ - gcc \ - musl-dev \ - libffi-dev \ - postgresql-dev \ - curl \ - wget \ - tar +COPY . /build -# Install uv -ARG PACKAGE_VERSION=0.9.21 -RUN wget -O /app/uv-x86_64-unknown-linux-musl.tar.gz https://github.com/astral-sh/uv/releases/download/${PACKAGE_VERSION}/uv-x86_64-unknown-linux-musl.tar.gz && \ - tar xf /app/uv-x86_64-unknown-linux-musl.tar.gz -C /app && \ - mv /app/uv-x86_64-unknown-linux-musl/uv /usr/local/bin/uv && \ - rm -rf /app/uv-x86_64-unknown-linux-musl* && \ - chmod +x /usr/local/bin/uv && \ - uv --version +RUN HATCH_VCS_PRETEND_VERSION=${VERSION} \ + SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} \ + uv build --wheel --directory /build && \ + useradd -m -r -s /bin/sh appuser -# Create non-root user first -RUN adduser -D -s /bin/sh appuser && \ - chown -R appuser:appuser /app - -# Copy dependency files and change ownership -COPY --chown=appuser:appuser pyproject.toml uv.lock README.md ./ - -# Switch to appuser and install Python dependencies USER appuser -ARG VERSION=dev -ENV HATCH_VCS_PRETEND_VERSION=${VERSION} \ - SETUPTOOLS_SCM_PRETEND_VERSION=${VERSION} -RUN uv sync --frozen +RUN uv tool install --from /build/dist/*.whl artifactapi -# Copy application source -COPY --chown=appuser:appuser src/ ./src/ -COPY --chown=appuser:appuser remotes.yaml ./ -COPY --chown=appuser:appuser ca-bundle.pem ./ +USER root +RUN rm -rf /build -# Expose port EXPOSE 8000 - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:8000/health || exit 1 - -# Run the application -CMD ["uv", "run", "python", "-m", "src.artifactapi.main"] \ No newline at end of file +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 CMD curl -f http://localhost:8000/health || exit 1 +USER appuser +ENV PATH="/home/appuser/.local/bin:$PATH" +WORKDIR /app +CMD ["artifactapi"] diff --git a/Makefile b/Makefile index 1142225..5309937 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .PHONY: build install dev clean test lint format pre-commit tox docker-build docker-up docker-down docker-logs docker-rebuild docker-clean docker-restart build: - docker build --no-cache -t artifactapi:latest . + docker build -t artifactapi:dev . install: build diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..1552b8a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,91 @@ +version: '3.8' + +services: + artifactapi: + build: + context: . + dockerfile: Dockerfile + args: + - VERSION=dev + ports: + - "8000:8000" + volumes: + - ./remotes.yaml:/app/remotes.yaml:ro + - ./ca-bundle.pem:/app/ca-bundle.pem:ro + environment: + - CONFIG_PATH=/app/remotes.yaml + - DBHOST=postgres + - DBPORT=5432 + - DBUSER=artifacts + - DBPASS=artifacts123 + - DBNAME=artifacts + - REDIS_URL=redis://redis:6379 + - MINIO_ENDPOINT=minio:9000 + - MINIO_ACCESS_KEY=minioadmin + - MINIO_SECRET_KEY=minioadmin + - MINIO_BUCKET=artifacts + - MINIO_SECURE=false + - REQUESTS_CA_BUNDLE=/app/ca-bundle.pem + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + minio: + condition: service_healthy + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + interval: 30s + timeout: 10s + retries: 3 + + minio: + image: minio/minio:latest + ports: + - "9000:9000" + - "9001:9001" + environment: + MINIO_ROOT_USER: minioadmin + MINIO_ROOT_PASSWORD: minioadmin + command: server /data --console-address ":9001" + volumes: + - minio_data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 30s + timeout: 20s + retries: 3 + + redis: + image: redis:7-alpine + ports: + - "6379:6379" + volumes: + - redis_data:/data + command: redis-server --save 20 1 + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 30s + timeout: 10s + retries: 3 + + postgres: + image: postgres:15-alpine + ports: + - "5432:5432" + environment: + POSTGRES_DB: artifacts + POSTGRES_USER: artifacts + POSTGRES_PASSWORD: artifacts123 + volumes: + - postgres_data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U artifacts -d artifacts"] + interval: 30s + timeout: 10s + retries: 3 + +volumes: + minio_data: + redis_data: + postgres_data: