Subida del docker a producción

This commit is contained in:
David Arranz 2026-01-30 11:36:16 +01:00
parent b0c04bbe42
commit e7aea83bdb
7 changed files with 286 additions and 10 deletions

View File

@ -1,12 +1,59 @@
.venv
__pycache__
# ----------------------------
# Python
# ----------------------------
__pycache__/
*.pyc
*.pyo
*.pyd
.pytest_cache
.mypy_cache
.ruff_cache
.git
*.py[cod]
*.egg-info/
.eggs/
.pytest_cache/
.mypy_cache/
# Virtual environments (local only)
.venv/
venv/
env/
# ----------------------------
# Environment & secrets
# ----------------------------
.env
.env.*
*.pem
*.key
*.crt
*.pfx
*.p12
# ----------------------------
# Git
# ----------------------------
.git/
.gitignore
tests
*.log
# ----------------------------
# Docker
# ----------------------------
Dockerfile
docker-compose.yml
# ----------------------------
# Editor / OS junk
# ----------------------------
.vscode/
.idea/
.DS_Store
Thumbs.db
# ----------------------------
# Docs & local files
# ----------------------------
docs/
*.md
# ----------------------------
# Tests & tooling (si no se usan en runtime)
# ----------------------------
tests/

View File

@ -3,11 +3,19 @@
# Copy this file to `.env` and fill the real values
# ============================================================
# --------------------
# UVICORN
# --------------------
UVICORN_RELOAD=false
UVICORN_WORKERS=2
# --------------------
# Application
# --------------------
APP_ENV=local # local | prod
LOG_LEVEL=INFO
STATE_PATH = ./
LOCAL_TZ = Europe/Madrid
# --------------------
# Secret manager

View File

@ -0,0 +1,59 @@
# ---------- Base image ----------
FROM python:3.12-slim AS base
# Evita pyc, mejora logs
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
# Dependencias del sistema necesarias para crypto / PDFs
RUN apt-get update && apt-get install -y \
build-essential \
libssl-dev \
libffi-dev \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
# ---------- Dependencies ----------
FROM base AS deps
# Copiamos solo metadatos para aprovechar cache
COPY ./pyproject.toml ./
# Instalamos dependencias
RUN pip install --upgrade pip \
&& pip install .
# ---------- Runtime ----------
FROM base AS runtime
# Copiamos dependencias instaladas
COPY --from=deps /usr/local /usr/local
# Copiamos código fuente
COPY src/ ./
# Puerto FastAPI
EXPOSE 8000
# Usuario no-root (buena práctica)
RUN useradd -m appuser
USER appuser
# Comando de arranque
CMD ["sh", "-c", "\
if [ \"$UVICORN_RELOAD\" = \"true\" ]; then \
uvicorn signing_service.main:app --host 0.0.0.0 --port 8000 --reload; \
else \
uvicorn signing_service.main:app --host 0.0.0.0 --port 8000 --workers ${UVICORN_WORKERS:-1}; \
fi"]
# Healthcheck
#RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
#HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
# CMD curl -f http://127.0.0.1:8000/health || exit 1

22
docker-compose.yml Normal file
View File

@ -0,0 +1,22 @@
services:
signing-service:
image: factuges-document-signing-service:latest
container_name: factuges-document-signing-service
restart: unless-stopped
env_file:
- .env
ports:
- "8000:8000"
networks:
- internal
- edge
volumes:
- ./volumes:/var/log
networks:
edge:
name: edge
external: true
internal:
name: factuges_rodax_internal
external: true

140
scripts/build-docker.sh Executable file
View File

@ -0,0 +1,140 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_VERSION="0.0.3"
# =====================================================
# FACTUGES Document Signing Service Build Script
# -----------------------------------------------------
# Build + Subida a producción de la imagen Docker
# =====================================================
# Uso:
# ./build_docker.sh <company> [--load]
#
# =====================================================
# --- Configuración base ---
COMPANY=""
LOAD=false
# --- Validar que el primer argumento existe y no es un flag ---
if [[ $# -eq 0 || "$1" == --* ]]; then
echo "❌ ERROR: Falta el parámetro <company>"
echo "Uso: ./build_docker.sh <company> [--load]"
echo "Ejemplos:"
echo " ./build_docker.sh acme --load"
exit 1
fi
COMPANY="$1"
SSH_USER="rodax"
SSH_HOST="vps-2.rodax-software.com"
SSH_PORT="49152"
# Override por compañía específica
if [[ "$COMPANY" == "rodax" ]]; then
SSH_USER="rodax"
SSH_HOST="factuges.rodax-software.local"
SSH_PORT="22"
fi
# --- Parseo de flags ---
shift # quitamos el <company>, ahora solo quedan flags
for arg in "$@"; do
case "$arg" in
--load) LOAD=true ;;
*) echo "⚠️ Argumento desconocido: $arg" ;;
esac
done
# --- Paths base ---
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(realpath "${SCRIPT_DIR}/..")"
OUT_DIR="${PROJECT_DIR}/build/"
if [[ -z "$COMPANY" ]]; then
echo "❌ Error: debes indicar la compañía. Ejemplo: ./build_docker.sh acme [--load]"
exit 1
fi
if [[ $COMPANY =~ --.* ]]; then
echo "❌ Error: debes indicar la compañía. Ejemplo: ./build_docker.sh acme [--load]"
exit 1
fi
# --- Detectar nombre y versión de la API ---
IMAGE_NAME=$(node -p "require('${PROJECT_DIR}/setup.cfg').name" 2>/dev/null || echo "factuges-document-signing-service")
IMAGE_VERSION=$(node -p "require('${PROJECT_DIR}/setup.cfg').version" 2>/dev/null || echo "0.1.2")
PORT="8000" # valor por defecto
# --- 3. Etiquetas e información ---
DATE=$(date +'%Y%m%d-%H%M%S')
ISO_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
USER_NAME=$(whoami)
GIT_HASH=$(git -C "$PROJECT_DIR" rev-parse --short HEAD 2>/dev/null || echo "unknown")
GIT_BRANCH=$(git -C "$PROJECT_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
IMAGE_TAG_V="${IMAGE_NAME}:v${IMAGE_VERSION}"
IMAGE_TAG_LATEST="${IMAGE_NAME}:latest"
mkdir -p "$OUT_DIR"
rm -rf "${OUT_DIR:?}/"*
echo ""
echo "-------------------------------------------------------"
echo " FACTUGES Document Signing Service Build Script v${SCRIPT_VERSION}"
echo " Compañía: ${COMPANY}"
echo " Proyecto: ${IMAGE_NAME}"
echo " Versión: ${IMAGE_VERSION}"
echo " Puerto: ${PORT}"
echo " Etiquetas: ${IMAGE_TAG_V}, ${IMAGE_TAG_LATEST}"
echo " Dir. out: ${OUT_DIR}"
echo " Cargar: ${LOAD}"
echo "-------------------------------------------------------"
cd "${PROJECT_DIR}"
echo "🐳 Construyendo imagen Docker..."
docker build \
-t "${IMAGE_TAG_V}" -t "${IMAGE_TAG_LATEST}" \
--build-arg PORT="${PORT}" \
-f "${PROJECT_DIR}/Dockerfile" "${PROJECT_DIR}"
echo "✅ Imagen Docker construida correctamente"
TAR_FILE_V="${OUT_DIR}/${IMAGE_NAME}-v${IMAGE_VERSION}-${DATE}.tar"
echo "🐳 Guardando imagen Docker ${TAR_FILE_V} ..."
docker save "${IMAGE_TAG_V}" "${IMAGE_TAG_LATEST}" -o "${TAR_FILE_V}"
echo "📦 Imagen guardada:"
echo " ${TAR_FILE_V}"
if [[ "$LOAD" == true ]]; then
echo "📥 Cargando imagen en producción ${SSH_HOST}..."
scp -r -P "${SSH_PORT}" "${OUT_DIR}" "${SSH_USER}@${SSH_HOST}:/opt/factuges-document-signing-service/"
RESULT=$(ssh -p "${SSH_PORT}" "${SSH_USER}@${SSH_HOST}" \
"docker load -i /opt/factuges-document-signing-service/build/$(basename "${TAR_FILE_V}") && \
docker tag ${IMAGE_TAG_V} ${IMAGE_TAG_LATEST} " 2>&1)
echo "${RESULT}"
echo "✅ Imagen cargada en producción"
fi
# =====================================================
# 3⃣ Resumen
# =====================================================
echo "-------------------------------------------------------"
echo "🎯 Resultado final para '${COMPANY}'"
echo " 🐳 v${IMAGE_VERSION}${OUT_DIR}"
echo "🧩 Script version: ${SCRIPT_VERSION} - FIN"
echo "-------------------------------------------------------"
echo ""
echo ""
echo ""

View File

@ -1,7 +1,7 @@
[metadata]
name = "factuges-document-signing-service"
version = "0.1.1"
version = "0.1.2"
description = "FastAPI service for signing PDF documents using external secret managers"
author = Rodax Software
author_email = info@rodax-software.com

View File

@ -19,7 +19,7 @@ local_tz = tz.gettz(settings.local_tz)
state_path = Path(settings.state_path)
# Logging
log_dir = state_path / "logs"
log_dir = state_path
log_dir.mkdir(parents=True, exist_ok=True)
logger = create_logger(
name="factuges-document-signing-service",