Implementación de tiempo de inactividad cero Node.js Docker

Implementación de tiempo de inactividad cero Node.js Docker

Tengo una aplicación React/Node.js ejecutándose en un único servidor usando Docker-Compose. Estoy intentando lograr una implementación de 0 tiempo de inactividad para mi aplicación de reacción. El proceso en este momento crea un paquete web (reemplaza los archivos en mi carpeta dist) y luego se acopla y se acopla. Todo este proceso dura unos 2-3 minutos. Me di cuenta de que con Docker-Compose puedo escalar mi contenedor hacia arriba o hacia abajo, pero no estoy seguro de cómo enviar mi código solo a 1 de ellos y reconstruir el paquete web. Realmente no quiero usar Kubernetes/Swarm u Openshift ya que es un poco excesivo. Me pregunto si alguien más ha logrado algo similar a esto.

Mi ventana acoplable se ve así:

node:
    build:
        context: ./env/docker/node
        args:
            - PROJECT_ROOT=/var/www/app
    image: react_app:rapp_node
    command: "npm run prod"
    expose:
        - "3333"
    networks:
        - react-net
    volumes_from:
        - volumes_source
    tty: false

nginx:
    env_file:
        - ".env"
    build:
        context: ./env/docker/nginx
    volumes_from:
        - volumes_source
    volumes:
        - ./env/data/logs/nginx/:/var/log/nginx
        - ./env/docker/nginx/sites/node.template:/etc/nginx/node.template
    networks:
        - react-net
        - nginx-proxy
    environment:
        NGINX_HOST: ${NGINX_HOST}
        VIRTUAL_HOST: ${NGINX_VIRTUAL_HOST}
        LETSENCRYPT_HOST: ${NGINX_VIRTUAL_HOST}
        ESC: $$
    links:
        - node:node
    command: /bin/sh -c "envsubst < /etc/nginx/node.template > /etc/nginx/sites-available/node.conf && nginx -g 'daemon off;'"

volumes_source:
    image: tianon/true
    volumes:
        - ./app:/var/www/app

Y mi nginx es algo como esto:

server {
server_name www.${NGINX_HOST};
return 301 ${ESC}scheme://${NGINX_HOST}${ESC}request_uri;
}

server {
listen 80;
server_name ${NGINX_HOST};

root /var/www/app;

location / {
proxy_pass http://node:3333;
proxy_http_version 1.1;
proxy_set_header Upgrade ${ESC}http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host ${ESC}host;
proxy_cache_bypass ${ESC}http_upgrade;
}
}

Respuesta1

Creo que la mejor manera es usar cualquier orquestador para eso, todos ellos tienen soporte para actualizaciones continuas y puedes usar cualquier flujo de actualización estándar.

Pero, si quieres exactamente lo que escribiste (pero esa no es una manera verdaderaen absoluto), puede, como ejemplo, ejecutar un script en el contenedor, que verificará una nueva versión de su aplicación, la compilará y cambiará el enlace simbólico de la versión anterior a la nueva, lo que puede hacer de forma atómica de esta manera: ln -s new current_tmp && mv -Tf current_tmp current.

Entonces, la estructura de directorios será así: /var/www/app - symlink to your current version /var/www/app_v1 - directory with current version, which symlinked to "/var/www/app" /var/www/app_v2 - directory with new version

Ahora, puede ejecutar el comando ln -s /var/www/app_v2 /var/www/app_v2_sym && mv -Tf /var/www/app_v2_sym /var/www/apppara cambiar la versión actual de la aplicación que usa Nginx.

Respuesta2

Recomiendo encarecidamente un enjambre simple de un solo nodo para esto. Es la solución perfecta para casos en los que no necesita tiempo de inactividad durante las actualizaciones pero no puede o no necesita alta disponibilidad de múltiples nodos. Realmente no agrega gastos generales ni más cargas administrativas y utiliza los mismos archivos de redacción.

Sí, realmente deberías crear una nueva versión de tu imagen con tu código en cada confirmación que planees enviar a este servidor. Las herramientas esperan este tipo de flujo de trabajo, por lo que le resultará más fácil si adopta ese flujo de trabajo. Docker Hub admite hacer esto por usted en cada confirmación a una rama (de forma gratuita si es de código abierto, y aún de forma gratuita para un único repositorio privado) de GitHub y BitBucket. Así es como funcionaría en un enjambre de un solo nodo, suponiendo que estuviera creando nuevas imágenes cada vez en Docker Hub:

  1. Suponiendo que tenga la versión estable reciente de Docker (17.12 a partir de esta publicación)
  2. docker swarm inity ahora tienes un enjambre de un solo nodo. Eso es todo. (Si solo puedo tener un servidor para implementar cosas de Docker enSiempre uso un enjambre de un solo nodo y no docker-compose por una lista de buenas razones.
  3. Con algunos cambios, su archivo de redacción se puede utilizar como un archivo de pila paradocker stack deploy -c compose-file.yml stackname
  4. Para garantizar implementaciones sin tiempo de inactividad, querráagregar controles de saluda sus contenedores nodo/nginx para que sepan cuándo la aplicación está realmente "lista para conexiones". Swarm también usa esto durante las actualizaciones del servicio, por lo que es clave.
  5. Si desea que Swarm agregue un nuevo contenedor primero, antes de eliminar el contenedor anterior, agréguelo order: start-firstalhttps://docs.docker.com/compose/compose-file/#update_config.
  6. Luego simplemente cambie las etiquetas de su imagen en el archivo de redacción, tal vez myuser/myrepo:1.0y myuser/myrepo:2.0luego ejecute el mismo comando de implementación de pila nuevamente, y Swarm detectará diferencias y actualizará el servicio con una nueva imagen (reemplazando el contenedor).

Para probar esto, use httping para validar que todavía esté disponible de forma remota durante el proceso de actualización.

información relacionada