Bereitstellung von Node.js Docker ohne Ausfallzeiten

Bereitstellung von Node.js Docker ohne Ausfallzeiten

Ich habe eine React/Node.js-Anwendung, die auf einem einzelnen Server mit Docker-Compose läuft. Ich versuche, eine Bereitstellung ohne Ausfallzeiten für meine React-App zu erreichen. Der aktuelle Prozess führt ein Webpack-Build durch (ersetzt die Dateien in meinem Dist-Ordner) und führt dann Docker Down und Docker Up durch. Dieser gesamte Prozess dauert etwa 2–3 Minuten. Mir ist aufgefallen, dass ich mit Docker-Compose meinen Container hoch-/herunterskalieren kann, aber ich bin mir nicht sicher, wie ich meinen Code nur auf einen davon pushen und das Webpack neu erstellen kann. Ich möchte wirklich nicht Kubernetes/Swarm oder Openshift verwenden, da das ein bisschen übertrieben ist. Ich frage mich, ob jemand anderes etwas Ähnliches erreicht hat.

Mein Docker-Compose sieht folgendermaßen aus:

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

Und mein Nginx sieht ungefähr so ​​aus:

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;
}
}

Antwort1

Ich glaube, die bessere Methode besteht darin, hierfür einen beliebigen Orchestrator zu verwenden. Alle unterstützen Rolling Update und Sie können jeden beliebigen Standardaktualisierungsablauf verwenden.

Wenn Sie jedoch genau das wollen, was Sie geschrieben haben (aber das ist kein wahrer Wegüberhaupt), können Sie beispielsweise ein Skript im Container ausführen, das eine neue Version Ihrer Anwendung auscheckt, sie erstellt und den symbolischen Link von der alten auf die neue Version umstellt. Dies können Sie atomar wie folgt tun: ln -s new current_tmp && mv -Tf current_tmp current.

Die Verzeichnisstruktur sieht also folgendermaßen aus: /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

Sie können jetzt einen Befehl ausführen, ln -s /var/www/app_v2 /var/www/app_v2_sym && mv -Tf /var/www/app_v2_sym /var/www/appum die aktuelle Version der Anwendung zu wechseln, die Nginx verwendet.

Antwort2

Ich empfehle hierfür dringend einen einfachen Single-Node-Swarm. Dies ist die perfekte Lösung für Fälle, in denen Sie während der Aktualisierung keine Ausfallzeiten benötigen, aber keine Multi-Node-Hochverfügbarkeit benötigen oder können. Es verursacht wirklich keinen zusätzlichen Overhead oder zusätzlichen Verwaltungsaufwand und verwendet dieselben Compose-Dateien.

Ja, Sie sollten wirklich bei jedem Commit, das Sie an diesen Server senden möchten, eine neue Version Ihres Images mit Ihrem Code erstellen. Die Tools erwarten diese Art von Workflow, daher wird es Ihnen leichter fallen, wenn Sie diesen Workflow übernehmen. Docker Hub unterstützt dies bei jedem Commit an einen Zweig (kostenlos, wenn Open Source, und weiterhin kostenlos für ein einzelnes privates Repo) von GitHub und BitBucket. So würde es in einem Single-Node-Swarm funktionieren, vorausgesetzt, Sie erstellen jedes Mal neue Images auf Docker Hub:

  1. Vorausgesetzt, Sie verwenden die aktuelle stabile Docker-Version (zum Zeitpunkt dieses Beitrags 17.12)
  2. docker swarm initund Sie haben jetzt einen Single-Node-Schwarm. Das ist alles. (Wenn ich nur einen Server haben kann, auf dem ich Docker-Sachen bereitstellen kannIch verwende aus einer Reihe guter Gründe immer einen Single-Node-Swarm und nicht Docker-Compose.
  3. Mit ein paar Änderungen kann Ihre Compose-Datei als Stack-Datei verwendet werden fürdocker stack deploy -c compose-file.yml stackname
  4. Um eine Bereitstellung ohne Ausfallzeiten zu gewährleisten, sollten SieGesundheitschecks hinzufügenzu Ihren Node/Nginx-Containern, damit diese wissen, wann die App wirklich „bereit für Verbindungen“ ist. Swarm verwendet dies auch bei Service-Updates, es ist also entscheidend.
  5. Wenn Sie möchten, dass Swarm zuerst einen neuen Container hinzufügt, bevor Sie Ihren alten Container entfernen, fügen Sie order: start-firstdemhttps://docs.docker.com/compose/compose-file/#update_config.
  6. Ändern Sie dann einfach Ihre Image-Tags in der Compose-Datei, beispielsweise myuser/myrepo:1.0in myuser/myrepo:2.0, und führen Sie dann denselben Stack-Deploy-Befehl erneut aus. Swarm erkennt die Unterschiede und aktualisiert den Dienst mit einem neuen Image (indem der Container ersetzt wird).

Um dies zu testen, überprüfen Sie per httping, ob es während des Aktualisierungsvorgangs noch remote verfügbar ist.

verwandte Informationen