249 lines
9.1 KiB
Markdown
249 lines
9.1 KiB
Markdown
# Scripts de despliegue
|
|
|
|
Guía de uso de los scripts de este directorio.
|
|
|
|
## `build-and-push.sh`
|
|
|
|
Construye la imagen nativa de Quarkus y la envía al daemon Docker de un host remoto por SSH, sin usar un registry externo ([unregistry](https://github.com/psviderski/unregistry) / `docker pussh`). Solo se transfieren las capas que el remoto aún no tiene.
|
|
|
|
### Qué hace el flujo
|
|
|
|
1. Toma el nombre de la imagen de la última carpeta de la ubicación del servicio y lee `version` de [`pom.xml`](../pom.xml) para el tag, salvo que uses `--name` o `--tag`. Si no hay `pom.xml`, el tag es `1.0.0-SNAPSHOT`.
|
|
2. Ejecuta `docker build` para la plataforma fija `linux/amd64` (útil si construyes desde un Mac arm64). Con `--type java` (el valor por defecto) usa [`src/main/docker/Dockerfile`](../src/main/docker/Dockerfile). Con `--type web` usa `Dockerfile` en la raíz del servicio.
|
|
3. Ejecuta `docker pussh` hacia el destino SSH indicado.
|
|
4. Comprueba por SSH que la imagen existe en el remoto (salvo `--no-verify`).
|
|
5. Muestra un comando `docker run` sugerido para arrancar el contenedor en el remoto.
|
|
|
|
### Requisitos
|
|
|
|
| Requisito | Descripción |
|
|
|-----------|-------------|
|
|
| Docker local | Daemon en marcha (`docker info` debe responder). |
|
|
| SSH | Acceso al host remoto; en el remoto debe estar instalado y usable Docker. |
|
|
| Plugin `docker pussh` | CLI plugin de unregistry. |
|
|
|
|
Si el plugin no está instalado, el script indica cómo añadirlo:
|
|
|
|
```shell
|
|
mkdir -p ~/.docker/cli-plugins
|
|
curl -fsSL https://raw.githubusercontent.com/psviderski/unregistry/main/docker-pussh \
|
|
-o ~/.docker/cli-plugins/docker-pussh
|
|
chmod +x ~/.docker/cli-plugins/docker-pussh
|
|
```
|
|
|
|
`xmllint` es opcional: si no está en el PATH y existe `pom.xml`, el script obtiene `version` del POM con `grep`/`sed`.
|
|
|
|
### Invocación
|
|
|
|
Puedes ejecutar el script desde cualquier directorio. Por defecto usa como raíz del proyecto el directorio padre de `scripts/` (donde está `pom.xml`).
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote USER@HOST
|
|
```
|
|
|
|
Alternativas para la raíz del proyecto:
|
|
|
|
- `--project-dir /ruta/al/proyecto`
|
|
- variable de entorno `PROJECT_DIR`
|
|
|
|
Ayuda integrada (en inglés):
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --help
|
|
```
|
|
|
|
### Opciones
|
|
|
|
**Destino (obligatorio)**
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--remote TARGET` | Destino SSH: `usuario@host[:puerto]` o un alias definido en `~/.ssh/config` (sin `@`). |
|
|
|
|
**Identidad de la imagen** (el nombre es la última carpeta del servicio; el tag sale de `pom.xml` si existe)
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--name NAME` | Nombre del repositorio de la imagen. |
|
|
| `--tag TAG` | Tag de la imagen. |
|
|
|
|
**Directorio de trabajo**
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--project-dir PATH` | Raíz del servicio. El nombre de la imagen es su última carpeta. |
|
|
| `PROJECT_DIR` | Misma función vía entorno. |
|
|
|
|
**Build**
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--type` | Dónde está el Dockerfile. `java` (por defecto): `src/main/docker/Dockerfile`. `web`: `Dockerfile` en la raíz del servicio. |
|
|
| `--skip-build` | No construye; solo hace `pussh` de una imagen que ya exista en local. La plataforma de build sigue siendo `linux/amd64` cuando no se omite el build. |
|
|
|
|
**SSH** (se reenvían a `docker pussh` y, en la verificación, a `ssh`)
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--ssh-key PATH` | Clave privada; tiene prioridad sobre `IdentityFile` del config SSH. |
|
|
| `--ssh-config PATH` | Archivo de configuración SSH (por defecto `~/.ssh/config`). |
|
|
|
|
**Post-push**
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `--no-verify` | Omite la comprobación `docker images` en el remoto. |
|
|
|
|
**Otros**
|
|
|
|
| Opción | Descripción |
|
|
|--------|-------------|
|
|
| `-h`, `--help` | Muestra la ayuda del script. |
|
|
|
|
### Alias en `~/.ssh/config`
|
|
|
|
Si `--remote` es un alias sin `@`, el script resuelve `HostName`, `User`, `Port` e `IdentityFile` del bloque `Host` correspondiente. `--ssh-key` siempre anula `IdentityFile`.
|
|
|
|
Ejemplo de configuración:
|
|
|
|
```text
|
|
# ~/.ssh/config
|
|
Host prod
|
|
HostName prod.example.com
|
|
User deploy
|
|
Port 22
|
|
IdentityFile ~/.ssh/deploy_ed25519
|
|
```
|
|
|
|
Uso:
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote prod
|
|
# Equivale a deploy@prod.example.com:22 con la clave del bloque Host prod
|
|
```
|
|
|
|
### Ejemplos
|
|
|
|
Destino explícito:
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote deploy@prod.example.com
|
|
```
|
|
|
|
Alias SSH:
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote prod
|
|
```
|
|
|
|
Clave explícita:
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote ubuntu@1.2.3.4 --ssh-key ~/.ssh/deploy_ed25519
|
|
```
|
|
|
|
Solo push (imagen ya construida) con otro tag:
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote deploy@prod --skip-build --tag 2.0.0
|
|
```
|
|
|
|
Ruta absoluta al script:
|
|
|
|
```shell
|
|
/absolute/path/to/test-quarkus/scripts/build-and-push.sh --remote deploy@prod
|
|
```
|
|
|
|
Proyecto en otra ruta:
|
|
|
|
```shell
|
|
PROJECT_DIR=/srv/proj ./scripts/build-and-push.sh --remote deploy@prod --skip-build
|
|
```
|
|
|
|
### Después del push
|
|
|
|
Al terminar con éxito, el script sugiere algo equivalente a:
|
|
|
|
```shell
|
|
ssh deploy@prod.example.com \
|
|
"docker run -d --name <carpeta> --restart unless-stopped -p 8080:8080 <carpeta>:<version>"
|
|
```
|
|
|
|
Sustituye `<carpeta>` por la última carpeta de la ubicación del servicio (o el valor de `--name`) y `<version>` por el tag del build (el de `pom.xml`, `1.0.0-SNAPSHOT` si no hay POM, o el de `--tag`).
|
|
|
|
### Solución de problemas
|
|
|
|
#### `invalid reference format` con saltos de línea en el tag
|
|
|
|
Si `docker build` falla con un tag parecido a `test-quarkus\n1.0.0-SNAPSHOT:test-quarkus\n1.0.0-SNAPSHOT`, el checkout del script es anterior al commit `57af30f`. En hosts sin `xmllint` (por ejemplo vm-compilador), el fallback antiguo de `read_pom` mezclaba `artifactId` y `version` en una sola cadena.
|
|
|
|
En la máquina donde compilas (`~/repo` u otra ruta del proyecto):
|
|
|
|
```shell
|
|
git rev-parse --short HEAD
|
|
grep -n 'head -2' scripts/build-and-push.sh || echo "script actualizado"
|
|
git pull
|
|
git rev-parse --short HEAD # debe ser 57af30f o posterior
|
|
./scripts/build-and-push.sh --remote TU_DESTINO
|
|
```
|
|
|
|
Comprueba que la primera línea del log sea `Image: test-quarkus:1.0.0-SNAPSHOT` (sin saltos de línea).
|
|
|
|
**Atajo** si aún no puedes actualizar el repo: fija nombre y tag explícitos (no usa el fallback roto):
|
|
|
|
```shell
|
|
./scripts/build-and-push.sh --remote TU_DESTINO \
|
|
--name test-quarkus --tag 1.0.0-SNAPSHOT
|
|
```
|
|
|
|
Opcional: instala `xmllint` para que el script lea el POM con XPath (`libxml2-utils` en Debian/Ubuntu).
|
|
|
|
## `deploy-services.sh`
|
|
|
|
Script independiente, en el mismo directorio que `build-and-push.sh`. No lo modifica: lo ejecuta una vez por cada servicio de un archivo de lista. Si un servicio falla, sigue con el resto y al terminar indica cuáles fallaron. El código de salida es `1` si alguno falló.
|
|
|
|
Al terminar el lote, ese resumen queda también en `deploy-YYYYMMDD-HHMMSS.log` en el directorio desde el que se lanzó el script (hora local de inicio). Si ese nombre ya existe, se añade el PID. Si no se puede escribir el archivo, el script avisa y conserva el código de salida del lote.
|
|
|
|
No hay lista por defecto. `--services` es obligatorio, así cada proyecto puede tener su propio archivo.
|
|
|
|
```shell
|
|
./scripts/deploy-services.sh --remote prod --services /srv/proyecto-a/services.txt
|
|
./scripts/deploy-services.sh --remote prod --services /srv/proyecto-b/services.txt --skip-build
|
|
```
|
|
|
|
Formato del archivo: una ruta por línea y, si hace falta, un segundo campo `java` o `web`. Si el tipo falta, es `java`. Se ignoran las líneas vacías y las que empiezan por `#`. Una ruta relativa se resuelve desde el directorio del archivo de lista, no desde el directorio donde lanzas el script.
|
|
|
|
```text
|
|
# /srv/proyecto-a/services.txt
|
|
./api
|
|
./portal web
|
|
```
|
|
|
|
`java` usa `src/main/docker/Dockerfile`. `web` usa `Dockerfile` en la raíz del servicio. El nombre de la imagen es la última carpeta de esa ruta. El tag sale de `pom.xml` si existe; si no, es `1.0.0-SNAPSHOT`.
|
|
|
|
Se reenvían a cada servicio: `--ssh-key`, `--ssh-config`, `--skip-build`, `--no-verify` y `--cleanup`, más el `--type` de esa línea. No se aceptan `--name`, `--tag`, `--project-dir` ni `--type`.
|
|
|
|
Ctrl+C interrumpe el lote. Ayuda: `./scripts/deploy-services.sh --help`.
|
|
|
|
## `update-repos.sh`
|
|
|
|
Actualiza un repositorio git por cada ruta de un archivo de lista. Ejecuta `git pull` en cada uno. Si alguno falla, sigue con el resto y al terminar indica cuáles fallaron. El código de salida es `1` si alguno falló.
|
|
|
|
No hay lista por defecto. `--repos` es obligatorio.
|
|
|
|
```shell
|
|
./scripts/update-repos.sh --repos /srv/proyecto/repos.txt
|
|
```
|
|
|
|
Al arrancar pide `Usuario:` y `Contraseña:` en la terminal, una sola vez para todo el lote. Esas credenciales se usan en los remotos HTTPS. No se leen desde la línea de comandos ni desde el archivo, y no se guardan. Un remoto SSH se actualiza con su acceso habitual (clave), sin esa contraseña.
|
|
|
|
Formato del archivo: una ruta por línea. Se ignoran las líneas vacías y las que empiezan por `#`. Una ruta relativa se resuelve desde el directorio del archivo de lista, no desde el directorio donde lanzas el script. Cada ruta debe ser la raíz de un repositorio git.
|
|
|
|
```text
|
|
# /srv/proyecto/repos.txt
|
|
/srv/repos/api
|
|
./portal
|
|
```
|
|
|
|
Ctrl+C interrumpe el lote. Ayuda: `./scripts/update-repos.sh --help`.
|