Migración Zulip cloud => selfhosted
Aunque Zulip ofrece su propia imagen de Docker, el servidor de zulipchat.com corre con una versión nightly. Esto hace que la imagen oficial no pueda utilizarse para importar datos exportados desde el servicio cloud.
Por ello, el primer paso es crear una imagen de docker actualizada a la versión desplegada en zulipchat.com
Dockerizar Zulip
Fork del repositorio
Podemos realizar un fork del repositorio oficial de Zulip para docker, adaptar el fichero Dockerfile
y utilizar una pipeline de CI/CD en GitLab para generar la imagen y añadirla a un repositorio de Docker Hub.
Analizando tanto el contenido del Dockerfile
como el historial de commits del repositorio oficial se puede deducir que los cambios de versión se traducen en actualizar la referencia de git que hay en la imagen de Docker.
Captura de la actualización a la versión 4.10. El resto de cambios es hacer lo mismo en diferentes ficheros (
README.md
, docker-compose.yml
...
Publicación de la imagen
Gitlab tiene una plantilla para crear una imagen de Docker y añadirla, por defecto, al repositorio privado del proyecto.
Podemos escogerla al crear el archivo .gitlab-ci.yaml
desde la UI de Gitlab.
Este es su contenido:
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
# Build a Docker image with CI/CD and push to the GitLab registry.
# Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
#
# This template uses one generic job with conditional builds
# for the default branch and all other (MR) branches.
docker-build:
# Use the official docker image.
image: docker:latest
stage: build
services:
- docker:dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
# Default branch leaves tag empty (= latest tag)
# All other branches are tagged with the escaped branch name (commit ref slug)
script:
- |
if [[ "$CI_COMMIT_BRANCH" == "$CI_DEFAULT_BRANCH" ]]; then
tag=""
echo "Running on default branch '$CI_DEFAULT_BRANCH': tag = 'latest'"
else
tag=":$CI_COMMIT_REF_SLUG"
echo "Running on branch '$CI_COMMIT_BRANCH': tag = $tag"
fi
- docker build --pull -t "$CI_REGISTRY_IMAGE${tag}" .
- docker push "$CI_REGISTRY_IMAGE${tag}"
# Run this job in a branch where a Dockerfile exists
rules:
- if: $CI_COMMIT_BRANCH
exists:
- Dockerfile
Para adaptarlo y enviar la imagen a un repositorio de Docker Hub en lugar de utilizar el registro privado, debemos eliminar la variable $CI_REGISTRY
en la sección before_script
.
Además, debemos sobreescribir las variables $CI_REGISTRY_USER
con el nombre de usuario de DockerHub y $CI_REGISTRY_PASSWORD
con un token generado desde Docker Hub.
Esto lo podemos hacer desde la sección Variables
en el menú CI/CD
de las Settings
del repositorio (documentación)
Por último, debemos sobreescribir la variable $CI_REGISTRY_IMAGE
. También podemos hacerlo en la sección anterior, pero esto haría que sea estática. Si queremos conseguir que sea dinámica, la podemos establecer en el propio fichero .gitlab-ci.yaml
. Para que sea dinámica, podemos utilizar las variables predefinidas
La ventaja de utilizar DockerHub, además de evitarnos un paso extra de autenticación en los posteriores despliegues, es que el cliente de docker por defecto entiende que el repositorio es DockerHub. Esto hace que podamos prescindir de la variable
CI_REGISTRY
, pero también que el nombre de nuestra imagen sólo deba contener el namespace, el nombre de la imagen y el tag.De utilizar otro registro distinto, al nombre de la imagen se debe anteponer la url de acceso al registro, puerto incluído si no se utilizase el 443.
Modificaciones extra
En este caso concreto, se ha modificado la pipeline de CI/CD para
- Evitar que se ejecute si sólo cambia algún fichero no trascendente
- Hacer que se ejecute sólo cuando un tag coincidente con una expresión regular es asignado a un commit y que utilice este tag también para la imagen.
Despliegue en local
Una vez publicada la imagen, haremos un despliegue en local para comprobar que funciona correctamente.
A tal fin, modificamos el fichero docker-compose.yml
docker-compose.yml
Eliminar la sección build
El docker-compose.yml
tiene una sección que permite cambiar las fuentes de zulip en el momento de su ejecución. Como ya hemos construído la imagen que queremos, borramos esta sección.
Cambiar la imagen de docker
En la sección zulip
del fichero, actualizamos el parámetro image
con el nombre de la imagen que hemos construído en el paso anterior.
Añadir Mailhog
Para poder probar el despliegue es necesario configurar un servidor de correo. Podemos saltarnos este paso utilizando Mailhog
Para añadirlo, sólo debemos añadir estas líneas al fichero:
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
Para decirle a Zulip que utilice Mailhog debemos cambiar los siguientes parámetros de la sección zulip
del fichero:
SETTING_EMAIL_HOST: "mailhog"
SETTING_EMAIL_HOST_USER: "admin" # no necesario
SETTING_EMAIL_PORT: "1025"
SETTING_EMAIL_USE_SSL: "False"
SETTING_EMAIL_USE_TLS: "False"
Importación de datos
Con estos cambios en docker-compose.yml
ya estamos en condiciones de ejecutar docker-compose up
para lanzarlo en local. Si no lo hemos modificado, por defecto escuchará en localhost.localdomain.
Para importar los datos exportados desde la instancia cloud de Zulip, debemos copiar el fichero exportado al container de Docker.
Podemos utilizar el volumen que ya monta el compose del directorio /opt/docker/zulip/zulip
o podemos añadírselo manualmente:
docker cp /tmp/laicoop/zulip-export-jvlz3y9e.tar.gz docker-zulip-zulip-1:/home/zulip
docker exec -i docker-zulip-zulip-1 bash
Al haberlo copiado como root, debemos cambiar los permisos:
cd /home/zulip
chown -R zulip .
exit
Ahora entramos al contenedor con zulip como usuario y ejecutamos el comando que aparece en la documentación oficial:
docker exec -i -u zulip docker-zulip-zulip-1 bash
cd /home/zulip
tar -xf zulip-export-jvlz3y9e.tar.gz
cd deployments/current/
./manage.py import '' /home/zulip/zulip-export-jvlz3y9e
supervisorctl start all # Starts the Zulip server
./manage.py reactivate_realm -r '' # Reactivates the organization
Si no hemos configurado un SSO, las credenciales de los usuarios quedarán inutilizadas en la importación y deben ser regeneradas en la nueva instancia.
Para ello seguimos el flujo normal (accedemos a localhost.localdomain y recuperamos la contraseña).
Aquí entra en juego Mailhog: visitando la url http://localhost:8025/ podemos ver los mails que Zulip ha enviado y recuperar la contraseña para comprobar que la importación se ha realizado con éxito.
Apuntes extras
¿Por qué no utilizar la funcionalidad
build
deldocker-compose.yml
?
Utilizar esta opción requiere que el fichero Dockerfile
esté presente en cada despliegue.
¿Hay alguna otra opción menos compleja?
Es posible. Falta por investigar el comando que aconseja la documentación para actualizar la versión de Zulip en Docker:
/home/zulip/deployments/current/scripts/upgrade-zulip-from-git main