Esta guia es la lista de ejecucion para instalar, actualizar y recuperar el despliegue de produccion. Los comandos generados son reutilizables. Antes de la aprobacion, el responsable debe registrar las entradas de despliegue indicadas abajo con valores o referencias institucionales verificadas.
- Requisitos
- Estructura de directorios en los servidores
- Preparar checkout y backup
- Actualizar codigo
- Configurar los ajustes de produccion
- Preparar directorios persistentes del host
- Backup antes de actualizar
- Ejecutar la actualizacion
- Comprobaciones posteriores
- Rollback
- Reparar permisos
- Operaciones utiles
- Notas de permisos
- Podman rootless y un proveedor de Compose funcionales.
- El mismo usuario sin privilegios para el instalador y Podman.
Entradas de despliegue que deben quedar registradas antes de ejecutar:
| Entrada | Evidencia requerida |
|---|---|
| Revision aprobada | Tag o commit inmutable y aprobacion asociada |
| Exposicion publica | URL, DNS, propietario de TLS y reglas de proxy |
| Dependencias | Base de datos, almacenamiento, correo e identidad aplicables |
| Operacion | Responsable del servicio y contacto de escalado |
| Recuperacion | RPO, RTO, retencion y ubicacion de backups |
podman info
podman compose version || podman-compose --versionNo ejecutar container_install.sh con sudo. Podman rootless, el proveedor de
Compose y el instalador deben usar siempre la misma cuenta. Los ejemplos usan
podman compose; si el host proporciona podman-compose, sustituir ese prefijo
completo. La libreria compartida detecta ambos proveedores automaticamente.
Todos los despliegues usan esta estructura institucional. El despliegue separa sus fuentes, binds, logs y backups; un servicio externo puede conservar un namespace distinto, definido por sus rutas protegidas. Podman administra su propio storage y no debe modificarse manualmente.
/opt/containers_apps/
└── iskylims/
├── backup/ # Backups locales opcionales
└── iskylims/ # Clone Git y configuracion protegida
/srv/containers/
├── backup/
│ └── iskylims/ # Backup central recomendado
├── bind/
│ └── <namespace-configurado>/
│ └── settings/ # settings.py renderizado por servicio
├── shared/ # Datos compartidos entre aplicaciones
└── storage/
└── <usuario-podman>/ # Storage rootless gestionado por Podman
/var/log/local/
└── <namespace-configurado>/
├── apache/
└── apps/
Persistencia declarada por el despliegue:
| Activo | Ubicacion de produccion | Requisito de recuperacion |
|---|---|---|
iskylims database |
External production database | Database backup before migration |
iskylims documents |
iskylims_documents named volume |
Volume backup |
iskylims static |
iskylims_static named volume |
Replaceable through collectstatic |
iskylims logs |
Host bind configured by HOST_LOG_PATH in iskylims_production_settings.txt |
Retain/rotate per institutional log policy |
iskylims rendered settings |
Host bind configured by DJANGO_SETTINGS_PATH in iskylims_production_settings.txt |
Protected configuration backup |
| Apache logs | /var/log/local/iskylims/apache host bind |
Retain/rotate per institutional log policy |
| Rendered Apache configuration | APACHE_CONF_PATH (or deployment/apache/ when empty) |
Rebuildable; preserve reviewed source configuration |
| Samba test data | samba_test_data named volume |
Disposable test/demo files |
Crear solo las ubicaciones necesarias para obtener el codigo y guardar backups.
Sustituir <usuario-podman> por la cuenta que ejecutara siempre Podman y el
instalador; normalmente es la cuenta de la sesion actual. Los binds y logs se
crean mas adelante, despues de completar los ajustes protegidos.
sudo mkdir -p /opt/containers_apps/iskylims
sudo mkdir -p /srv/containers/backup/iskylims
sudo chown -R <usuario-podman>:<usuario-podman> \
/opt/containers_apps/iskylims \
/srv/containers/backup/iskylimsPara las instalaciones ISCIII, usar el repositorio institucional de GitLab. Para un checkout nuevo:
cd /opt/containers_apps/iskylims
git clone https://gitlab.isciii.es/bu-isciii/iSkyLIMS.git iskylims
cd iskylims
git checkout <revision-aprobada>En un checkout existente, verificar con git status --short que no haya cambios
locales antes de continuar. Configurar el remoto institucional y obtener las
revisiones disponibles:
cd /opt/containers_apps/iskylims/iskylims
git remote set-url origin https://gitlab.isciii.es/bu-isciii/iSkyLIMS.git
git fetch origin --tags
git checkout <revision-aprobada>Si la revision aprobada es la rama main, actualizarla sin crear commits de
merge locales:
git switch main
git pull --ff-only origin mainPara una etiqueta o un commit aprobado, no ejecutar git pull; el checkout ya
selecciona esa revision exacta. Registrar el commit desplegado con
git rev-parse HEAD.
Este codigo va a crear un fichero ignorado y con modo 0600 por servicio a partir de su
conf/docker_production_settings.txt. Resolver todos los CHANGE_ME y revisar
la matriz conf/INSTALL_SETTINGS.md. El instalador
genera .env.production.file con valores runtime, incluidos secretos copiados
desde estos ficheros protegidos. Mantenerlo con modo 0600, fuera de Git y
dentro del backup protegido de configuracion. Ninguno de estos ficheros se
copia en las capas de las imagenes.
install -d -m 0700 deployment/settings
install -m 0600 conf/docker_production_settings.txt deployment/settings/iskylims_production_settings.txt
install -m 0600 conf/apache/apache_production_settings.txt deployment/settings/apache_production_settings.txt
install -m 0600 conf/samba/samba_production_settings.txt deployment/settings/samba_production_settings.txtValores que requieren decision del responsable de la aplicacion:
- hostnames publicos, TLS y proxy;
- base de datos y credenciales de minimo privilegio;
- rutas persistentes, UID/GID, SELinux y politica de backup;
- correo, identidad, almacenamiento y ajustes propios de la aplicacion;
- administrador inicial y transferencia segura de sus credenciales.
Editar unicamente las copias bajo deployment/settings/, completar todas esas
decisiones y resolver cada CHANGE_ME antes de continuar. Los comandos de
instalacion y actualizacion usan estas rutas protegidas.
Las actualizaciones Django conservan automaticamente SECRET_KEY del fichero
de settings existente en el host, indicado por DJANGO_SETTINGS_PATH. No hace
falta configurar la clave manualmente. Si el fichero no existe, el instalador
genera una clave nueva. Al restaurar o mover el despliegue a otra ruta de
settings, restaurar alli el fichero antiguo antes de instalar si se necesita
conservar la clave de firma original.
Solo despues de completar y revisar todos los ajustes, crear los binds
exactamente donde indica cada servicio. Los ficheros se cargan como el usuario
actual dentro de subshells; solo install -d usa privilegios. Esto incluye
servicios con un namespace de host distinto al despliegue principal.
PODMAN_USER='<usuario-podman>'
(
source deployment/settings/iskylims_production_settings.txt
: "${HOST_LOG_PATH:?HOST_LOG_PATH is required for iskylims}"
: "${DJANGO_SETTINGS_PATH:?DJANGO_SETTINGS_PATH is required for iskylims}"
sudo install -d -o "$PODMAN_USER" -g "$PODMAN_USER" \
"$HOST_LOG_PATH" "$(dirname "$DJANGO_SETTINGS_PATH")"
)
(
source deployment/settings/apache_production_settings.txt
: "${APACHE_LOG_PATH:?APACHE_LOG_PATH is required for apache}"
sudo install -d -o "$PODMAN_USER" -g "$PODMAN_USER" \
"$APACHE_LOG_PATH"
)Revisar las rutas resueltas antes de ejecutar. No usar valores procedentes de
una configuracion no revisada y no ejecutar los ficheros completos con sudo.
Aplicar despues UID/GID internos, modos y etiquetas SELinux mediante el
instalador. No modificar /srv/containers/storage/ manualmente.
bash container_install.sh --action fix-permissions --engine podman \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txtNo se han definido procedimientos adicionales propios de iSkyLIMS antes del backup o de la primera instalacion de produccion.
Crear un directorio identificado y registrar el estado desplegado:
BACKUP_DIR="/srv/containers/backup/iskylims/$(date +%Y%m%d_%H%M%S)"
mkdir -p "$BACKUP_DIR"
git rev-parse HEAD > "$BACKUP_DIR/git-revision.txt"
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
images > "$BACKUP_DIR/images.txt"
cp .env.production.file "$BACKUP_DIR/"
cp deployment/settings/iskylims_production_settings.txt "$BACKUP_DIR/"
cp deployment/settings/apache_production_settings.txt "$BACKUP_DIR/"
cp deployment/settings/samba_production_settings.txt "$BACKUP_DIR/"
chmod -R go-rwx "$BACKUP_DIR"Para cada base gestionada por Compose, exportar un dump logico desde su servicio; para cada base externa, exportarlo desde un punto coherente:
# Base gestionada por Compose:
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec -T <servicio>-db sh -c 'exec mysqldump --single-transaction --routines --triggers -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE"' \
> "$BACKUP_DIR/<servicio>-database.sql"
# Base externa:
mysqldump --single-transaction --routines --triggers \
--host=<db-host> --port=<db-port> --user=<db-user> --password \
<db-name> > "$BACKUP_DIR/database.sql"Localizar y exportar cada volumen no reconstruible declarado en la tabla:
podman volume ls | grep 'iskylims'
podman volume export <volumen-documents> > "$BACKUP_DIR/documents.tar"
podman volume export <volumen-static> > "$BACKUP_DIR/static.tar"
Exportar documents y static por cada servicio Django que los declare;
omitir esos comandos para perfiles sin dichos volumenes. Aunque static puede
regenerarse con collectstatic, conservarlo permite una restauracion exacta.
Guardar tambien los bind mounts persistentes. Los logs se conservan segun su politica de retencion; la configuracion protegida debe incluirse siempre.
tar -C /srv/containers/bind -czf "$BACKUP_DIR/bind-mounts.tar.gz" iskylims
tar -C /var/log/local -czf "$BACKUP_DIR/logs.tar.gz" iskylims
sha256sum "$BACKUP_DIR"/* > "$BACKUP_DIR/SHA256SUMS"No continuar hasta verificar los ficheros, espacio disponible y procedimiento de restauracion.
Ejecutar el comando de instalación/upgrade:
bash container_install.sh --action upgrade --engine podman \
--git_revision <nueva-revision-aprobada> \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txt 2>&1 | tee "$(date +%Y%m%d_%H%M%S)_prod_install.log"Durante --action upgrade, container_install.sh:
- valida opciones, configuraciones protegidas y Compose antes de modificar el despliegue;
- genera
.env.production.filey las configuraciones runtime protegidas; - prepara bind mounts, propietarios, modos y etiquetas SELinux;
- construye las imagenes desde la revision aprobada;
- recrea la topologia conservando volumenes y bind mounts persistentes;
- espera readiness y repara los volumenes desde los contenedores en ejecucion;
- ejecuta el bootstrap requerido por cada perfil —checks, migraciones,
scripts/fixtures y
collectstaticpara Django—; - ejecuta el smoke test y solo entonces declara completada la actualizacion.
Seguir ademas la guia especifica de la version cuando exista. Detenerse ante cualquier fallo de build, readiness, bootstrap, migracion o smoke test.
Con los contenedores levantados despues de una instalacion o actualizacion, repetir la reparacion para aplicar propietarios y modos dentro de todos los volumenes montados:
bash container_install.sh --action fix-permissions --engine podman \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txtpodman compose --env-file .env.production.file -f docker-compose.prod.yml ps
podman compose --env-file .env.production.file -f docker-compose.prod.yml logs --tail 200
bash scripts/smoke_test.sh --engine podman --env_file .env.production.fileCompletar las comprobaciones que corresponden a la topologia seleccionada:
iskylims: confirmar su endpoint/health/y un flujo representativo de lectura.- Apache: confirmar la URL publica registrada, DNS/TLS, proxy, cabeceras reenviadas y el endpoint restringido de server-status.
- Samba: en cada modo habilitado, confirmar acceso autenticado y un flujo representativo de lectura/escritura desde un cliente aprobado.
Verificar tambien correo, tareas programadas y los flujos propios documentados por la aplicacion. Registrar URL y resultados junto con estado, imagenes y revision desplegada.
Si el esquema y los formatos persistentes siguen siendo compatibles, desplegar la revision anterior registrada y repetir las pruebas:
bash container_install.sh --action upgrade --engine podman \
--git_revision <revision-anterior> \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txtSi no son compatibles, detener escrituras y restaurar el punto completo:
podman compose --env-file .env.production.file -f docker-compose.prod.yml down
# Restaurar directamente las bases externas. Para una base gestionada por
# Compose, arrancar <servicio>-db, esperar su healthcheck e importar desde él.
mysql --host=<db-host> --port=<db-port> --user=<db-user> --password \
<db-name> < "$BACKUP_DIR/database.sql"
podman volume import <volumen-documents> "$BACKUP_DIR/documents.tar"
podman volume import <volumen-static> "$BACKUP_DIR/static.tar"
tar -C /srv/containers/bind -xzf "$BACKUP_DIR/bind-mounts.tar.gz"
install -d -m 0700 deployment/settings
install -m 0600 "$BACKUP_DIR/iskylims_production_settings.txt" deployment/settings/iskylims_production_settings.txt
install -m 0600 "$BACKUP_DIR/apache_production_settings.txt" deployment/settings/apache_production_settings.txt
install -m 0600 "$BACKUP_DIR/samba_production_settings.txt" deployment/settings/samba_production_settings.txt
bash container_install.sh --action fix-permissions --engine podman \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txt
Restaurar todos los ficheros de ajustes protegidos y desplegar la revision
anotada en git-revision.txt. fix-permissions regenera
.env.production.file antes de cualquier restauracion gestionada por un
add-on. Arrancar y validar antes de reabrir el servicio. Los volumenes deben
existir y estar vacios antes de podman volume import; recrearlos con Compose
cuando sea necesario.
Ejecutar esta accion cuando:
- se hayan creado o restaurado bind mounts o volumenes;
- se hayan recreado contenedores manualmente;
- hayan cambiado
APP_UID,APP_GIDo el usuario rootless; - existan errores de escritura en logs, documentos, static o configuracion;
- SELinux rechace un bind mount revisado;
- Apache o la aplicacion fallen por propietarios/modos incorrectos.
Primera fase, incluso con los contenedores detenidos:
bash container_install.sh --action fix-permissions --engine podman \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txtEsta accion no construye imagenes, no migra la base de datos y no borra datos. Con los contenedores detenidos repara los bind mounts accesibles desde el host. Arrancar y repetirla para reparar tambien los volumenes montados:
podman compose --env-file .env.production.file -f docker-compose.prod.yml up -d
bash container_install.sh --action fix-permissions --engine podman \
--install_conf_map iskylims,deployment/settings/iskylims_production_settings.txt --install_conf_map apache,deployment/settings/apache_production_settings.txt --install_conf_map samba,deployment/settings/samba_production_settings.txtpodman compose --env-file .env.production.file -f docker-compose.prod.yml ps
podman compose --env-file .env.production.file -f docker-compose.prod.yml logs --tail 200
podman compose --env-file .env.production.file -f docker-compose.prod.yml up -d
podman compose --env-file .env.production.file -f docker-compose.prod.yml restart
podman compose --env-file .env.production.file -f docker-compose.prod.yml down# Logs separados del servicio.
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
logs --tail 200 iskylims
# Entrar al contenedor.
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec iskylims bash
# Regenerar static sin ejecutar migraciones.
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec iskylims bash -lc \
'cd "$INSTALL_PATH" && source virtualenv/bin/activate && python manage.py collectstatic --noinput'
# Diagnostico previo a una recuperacion de bootstrap.
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec iskylims bash -lc \
'cd "$INSTALL_PATH" && source virtualenv/bin/activate && python manage.py check --deploy && python manage.py showmigrations --plan'La recuperacion preferida es corregir la causa y repetir
container_install.sh --action install|upgrade con la misma revision y
configuracion protegida. Si el instalador no puede completarse y el responsable
autoriza un bootstrap manual despues del backup:
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec iskylims bash -lc \
'cd "$INSTALL_PATH" && source virtualenv/bin/activate && python manage.py migrate --noinput && python manage.py collectstatic --noinput'Registrar este procedimiento excepcional y ejecutar despues el smoke test.
# Logs separados de Apache y validacion de configuracion.
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
logs --tail 200 iskylims-apache
podman compose --env-file .env.production.file -f docker-compose.prod.yml \
exec iskylims-apache httpd -t
# Estado restringido; usar valores del fichero protegido.
APACHE_PORT='CHANGE_ME'
SERVER_STATUS_SERVER_NAME='localhost'
curl --fail --show-error \
--header "Host: $SERVER_STATUS_SERVER_NAME" \
"http://127.0.0.1:$APACHE_PORT/server-status?auto"Para diagnosticos SELinux y ModSecurity, comprobar el bind de logs antes de reiniciar:
ls -ldZ /var/log/local/iskylims/apacheSi aparece ModSecurity: Failed to open debug log file, conservar el fichero
para diagnostico, ejecutar fix-permissions y reiniciar. Si hay que sustituir
el inode, moverlo primero a un backup en vez de borrarlo.
- Ejecutar siempre Podman y el instalador con el mismo usuario rootless.
- No usar
sudo container_install.shni cambiar propietarios dentro del storage de Podman. - Mantener estables los UID/GID de runtime entre actualizaciones.
- Revisar etiquetas SELinux y propietarios de bind mounts mediante
fix-permissions. - Preservar evidencias y backups antes de cualquier recuperacion destructiva.