Implemente el código directamente en el contenedor acoplable. O cómo no postergar después de cada compromiso

La tarea vino WEB-12982
Cree una rama web-12982 en el repositorio
Mientras la sucursal va, lee tz y bebe café
Proceder directamente al desarrollo

git commit, git push
Mientras la rama se está volviendo a armar
git commit, git push
Mientras se reconstruye la rama, voltear twitter
git commit, git push
...
Usted entrega una rama de revisión con 50 confirmaciones

Usted comprende que 50 confirmaciones son exactamente 50 minutos de tiempo puro, que se recopila en forma de ataques, ya que los intervalos de 1 minuto son demasiado pequeños para hacer otra cosa que no sea la dilación y las necesidades básicas.


¿Es familiar la situación? En mi empresa, la infraestructura de desarrollo está organizada de la siguiente manera:


  • Hitlab tiene muchos repositorios de proyectos
  • Para garantizar la facilidad de desarrollo al crear una nueva sucursal, los dockers crean automáticamente su propio entorno limitado en una dirección única, una copia completa de la sucursal principal con todo el entorno necesario.
  • Todo lo que necesita está listo: solo escriba el código y pruebe, vea y evalúe el resultado después de cada confirmación, ¡es muy conveniente!

Pero, lentamente ... Si esta situación está cerca de ti, bienvenido con el gato.



La esencia del problema


tldr: los cambios realizados en el código requieren volver a ensamblar los contenedores y pasar tiempo (más de un minuto, depende del proyecto, especialmente si CI \ CD está configurado), que de hecho no se puede gastar de manera útil, pero que requiere una parte considerable del tiempo de trabajo del programador.

Problemas similares aparecen periódicamente en todos

Por ejemplo, el mismo liveReload para la interfaz se inventó claramente por una razón


Anteriormente publiqué un artículo sobre un tema relacionado , pero relacionado con el proceso de depuración (Por cierto, gracias por los comentarios informativos y comentarios positivos). Sin embargo, el problema sobre el corte esencialmente no ha desaparecido, también continuamos esperando hasta que la rama se vuelva a ensamblar.


Incluso si omite las etapas adicionales y deja solo build-dev y deploy-dev, el tiempo de espera es insignificante para cualquier acción útil, pero significativamente en el tiempo total empleado, especialmente cuando se trata de CI \ CD, por ejemplo, de Gitlab.


Por supuesto, puede acelerar el proceso ensamblando el proyecto localmente, siempre que el programador tenga una computadora relativamente poderosa, se configure gitlab-runner, se configure el mismo entorno que en el servidor remoto y las etiquetas correspondientes se agreguen a gitlab-ci.yml, pero dudo que la velocidad de compilación será la misma que la implementación automática del código FTP después de las teclas ctrl + s.


Especialmente quemaduras enfurece Es agotador cuando durante el proceso de desarrollo comete errores tipográficos / errores que generalmente no afectan el funcionamiento de la aplicación, pero que no se pueden dejar así y los nota solo cuando mira el resultado después del ensamblaje.


Qué se requiere y opciones de solución


tldr: encuentre una manera de ver el resultado de sus ediciones de la manera más simple y rápida posible. Para no comprometerse cada vez y no esperar a reconstruir la sucursal. Seleccioné rsync de la computadora local a la carpeta del servidor remoto montada con la carpeta del contenedor.

No encontré una solución completa en Internet, pero de hecho hay varias opciones:


  • Configure ftp \ ssh directamente en el contenedor con la base del código, inclúyalo en la imagen, conéctese vía FTP directamente al contenedor mismo
    • Personalmente, esta opción me pareció un poco complicada y demasiado "muleta", aunque aquí todas las opciones son muletas.
  • (para uso local) use docker cp para cargar el código directamente en el contenedor
    • La opción no es adecuada para trabajar con un servidor remoto.
    • docker cp tiene una funcionalidad extremadamente limitada, dadas las carpetas de proveedores que no deben copiarse siempre, y el algoritmo de copia en sí mismo, esto será bastante lento.
  • (para uso remoto \ local) Monte la carpeta del contenedor deseado en la carpeta del host externo. Descargue los archivos locales directamente a la carpeta del host montado. Ya hay muchas opciones de implementación:
    • Utilice docker-machine y específicamente docker-machine scp
      • Nuevamente, debe configurar el entorno, configurar la máquina acoplable, tal vez esto tenga sentido cuando trabaja constantemente con diferentes servidores
    • En el IDE, configure una conexión FTP con la carpeta de host deseada
      • Cada nueva rama requiere crear una nueva conexión o cambiar las asignaciones
    • Use scp o rsync para cargar archivos en la carpeta de host deseada, para esto use un pequeño script bash y cuélguelo en las teclas de acceso rápido
      • Al principio, parece innecesariamente complicado, pero de hecho no lo es. El script en sí es lo más simple posible y es necesario para automatizar el proceso para que no tenga que volver a configurar las asignaciones cada vez

Solución en sí: rsync + volúmenes


tldr:
  • Necesita acceso ssh a un servidor remoto y rsync en la máquina local
  • El servidor remoto debe tener una carpeta de escritura
  • Monte la carpeta del proyecto en el contenedor en la carpeta del host externo
  • Agregue un pequeño script bash a la raíz del proyecto para sincronizar archivos con el servidor remoto
  • Configurar una tecla de acceso rápido para la ejecución del script de sincronización

Vale la pena señalar que la solución proporcionada está excluida para el entorno de desarrollo y prueba


En este caso, veré los entornos docker-compose y gitlab-ci, con docker-compose utilizando variables de entorno de gitlab-ci.


Formamos la ruta a la carpeta de destino en gitlab-ci y exportamos esta ruta a docker-compose.yml:


before_script: - export SHARED_DIR_BASE='/var/www/builds' #    ,      - export SHARED_BRANCH_DIR=${SHARED_DIR_BASE}/${PROJECT_GROUP}/${PROJECT_NAME}/${CI_COMMIT_REF_NAME} #     web-123   my_group/my_project,      /var/shared/my_group/my_project/web-123 Deploy dev: stage: deploy_dev script: #   ,         - mkdir -p ${SHARED_BRANCH_DIR} - rsync -r --exclude-from=.gitignore --exclude-from=.dockerignore . ${SHARED_BRANCH_DIR} - find ${SHARED_BRANCH_DIR} -type d -exec setfacl -d -mo:rwx {} \; - find ${SHARED_BRANCH_DIR} -type d -exec setfacl -mo:rwx {} \; - find ${SHARED_BRANCH_DIR} -type f -exec setfacl -mo:rwx {} \; - envsubst < docker-compose.tmpl > docker-compose.yml #     gitlab-ci.yml  docker-compose.yml,   docker-compose.tmpl - docker-compose up -d 

Luego, necesitamos montar las carpetas del proyecto en la carpeta del host externo en docker-compose, ya que usamos las variables en docker-compose, necesitamos la plantilla docker-compose.tmpl en la que usaremos estas variables.


 version: '2.3' services: web: ... volumes: - ${SHARED_BRANCH_DIR}:/app/:rw #             #        .    ,      ,           .              ,     ,        - /app/protected/vendor/ 

Ya la configuración actual es suficiente, ahora cuando crea la rama en el servidor host, se creará la carpeta / var / www / builds / GROUP_NAME / PROJECT_NAME / BRANCH_NAME y el proyecto se transferirá allí, excepto aquellos archivos y carpetas que se especifiquen en .gitignore y .dockerignore, luego simplemente puede configurar asignaciones FTP, pero iremos un poco más allá y haremos que el proceso sea un poco más automatizado.


De hecho, para sincronizar archivos, necesitamos ejecutar algo como esto:


 rsync -r -u \ --delete-after \ --exclude-from=.gitignore \ --exclude-from=.dockerignore \ . $sshUserName@$sshHost:$sharedBaseDir 

De hecho, en proyectos pequeños y medianos, este comando se ejecutará más rápido de lo que tiene tiempo para confirmar y enviar las ediciones al repositorio. Resta llevar este script a un aspecto más completo y vincular su ejecución a teclas de acceso rápido.


Código de script completo: deploy.sh
 #!/usr/bin/env bash #    while [ -n "$1" ] do case "$1" in --sshUserName=*) sshUserName=${1#*=} ;; --sshHost=*) sshHost=${1#*=} ;; esac shift done #  shared    gitBranch=$(git branch | grep \* | cut -d ' ' -f2) gitProject=$(git config --local remote.origin.url|sed -n 's#.*/\([^.]*\)\.git#\1#p') gitGroup=$(git config --local remote.origin.url|sed -n 's#.*/\([^.]*\)/.*\.git#\1#p') sharedBaseDir=/var/www/builds/$gitGroup/$gitProject/$gitBranch #         rsync -r -u \ --delete-after \ --exclude-from=.gitignore \ --exclude-from=.dockerignore \ . $sshUserName@$sshHost:$sharedBaseDir echo "done" 

Cabe señalar que el script debe ubicarse en la raíz de la carpeta del proyecto del repositorio o indicar en qué directorio debería funcionar.


Solo queda fijar la ejecución de este script a teclas de acceso rápido específicas y establecer los parámetros sshUserName y sshHost (se entiende que ya hay acceso al servidor remoto a través de ssh). Cómo hacer esto, daré un ejemplo de PHPstorm.


  • Vaya a Archivo -> Configuración
  • En la ventana de configuración en el menú de la izquierda, expanda Herramientas , seleccione Herramientas externas
  • Escribimos la ruta al script y especificamos el sshUserName real y sshHost en los argumentos

  • A continuación, vaya a Mapa de teclas y busque el nombre de nuestras Herramientas externas, establezca la combinación necesaria


Eso es todo. Ahora, cuando hace clic en la combinación deseada, todos los archivos del proyecto se sincronizan con la carpeta remota, que se monta con la carpeta del proyecto dentro del contenedor. Es decir, cualquier cambio será visible casi de inmediato.


No pretendo ser "ideal" de esta solución, probablemente haya mejores opciones, me alegraré si las conozco en los comentarios. Gracias

Source: https://habr.com/ru/post/439262/


All Articles