wake-up-neo.net

Docker - Daten können nicht zwischen Containern innerhalb eines Volumes geteilt werden (Docker-Compose 3)

Ich habe jetzt einige Container für eine Web-App (Nginx, Gunicorn, Postgres und Node, um statische Dateien aus Quell- und einem React-Server-Rendering zu erstellen). In einem Dockerfile für den Node Container habe ich zwei Schritte: build and run ( Dockerfile.node ). Am Ende befinden sich zwei Verzeichnisse in einem Container: bundle_client - ist eine Statik für einen nginx und bundle_server - es wird im Knotencontainer selbst zum Starten eines Express-Servers verwendet.

Dann muss ich einen erstellten statischen Ordner (bundle_client) mit dem Nginx-Container freigeben. Um dies gemäß der Docker-Compose-Referenz in meinem docker-compose.yml zu tun, habe ich die folgenden Dienste (Siehe full docker-compose.yml ):

node:
  volumes:
    - vnode:/usr/src

nginx:
  volumes:
    - vnode:/var/www/tg/static
  depends_on:
    - node

und Bände:

volumes:
  vnode:

Das Ausführen von docker-compose build wird ohne Fehler abgeschlossen. Das Ausführen von docker-compose up läuft alles ok und ich kann localhost:80 öffnen, und es gibt nginx, gunicorn und node express SSR, die alle gut funktionieren und ich kann eine Webseite sehen, aber alle statischen Dateien geben den Fehler 404 zurück.

Wenn ich Volumes mit docker volume ls überprüfe, sehe ich zwei neu erstellte Volumes mit dem Namen tg_vnode (die wir hier betrachten) und tg_vdata (siehe vollständige docker-compose.yml).

Wenn ich mit docker run -ti -v /tmp:/tmp tg_node /bin/bash in einen Nginx-Container gehe, kann ich meinen www/tg/static-Ordner nicht sehen, der meine statischen Dateien vom Knotenvolume zuordnen soll. Ich habe auch versucht, einen leeren /var/www/tg/static-Ordner mit nginx-Container Dockerfile.nginx zu erstellen, der jedoch leer bleibt.

Wenn ich einen bundle_client-Ordner von der Host-Maschine im docker-compose.yml-Abschnitt in einem nginx.volumes-Abschnitt als - ./client/bundle_client:/var/www/tg/static-Ordner abspeichere, funktioniert es in Ordnung und ich kann alle statischen Dateien sehen, die mit nginx im Browser bereitgestellt werden.

Was mache ich falsch und wie kann ich meinen Container dazu bringen, statische Inhalte mit dem nginx-Container gemeinsam zu nutzen?

PS: Ich habe alle Dokumente gelesen, alle github-Probleme und Fragen und Antworten zum Stackoverflow. Wie ich es verstanden habe, muss es funktionieren und es gibt keine Informationen, was zu tun ist, wenn nicht.

UPD: Ergebnis von docker volume inspect vnode:

[
{
    "CreatedAt": "2018-05-18T12:24:38Z",
    "Driver": "local",
    "Labels": {
        "com.docker.compose.project": "tg",
        "com.docker.compose.version": "1.21.1",
        "com.docker.compose.volume": "vnode"
    },
    "Mountpoint": "/var/lib/docker/volumes/tg_vnode/_data",
    "Name": "tg_vnode",
    "Options": null,
    "Scope": "local"
}
]

Dateien: Dockerfile.node , docker-compose.yml

Nginx Dockerfile: Dockerfile.nginx


UPD: Ich habe ein vereinfachtes Repo erstellt, um eine Frage zu reproduzieren: repo (Es gibt einige Warnungen auf npm install, die es installiert und in Ordnung sind). Wenn wir localhost:80 öffnen, sehen wir möglicherweise eine leere Seite und 404-Nachrichten für statische Dateien (vendor.js und app.js) in den Chrome-Entwicklungswerkzeugen. Es sollte jedoch eine von _React app: static loaded erzeugte Nachricht durch das reaktionsskript generiert werden.

7
Max

Zwei Änderungen, die Sie brauchen. In Ihrem Knotendienst d das Volume wie

volumes:
  - vnode:/usr/src/bundle_client

Da Sie /usr/src/bundle_client freigeben möchten, sollten Sie NICHT /usr/src/ verwenden, da dadurch auch der gesamte Ordner und die Struktur freigegeben werden.

Und dann fügen Sie in Ihrem Nginx-Dienst das Volume hinzu

volumes:
  - type: volume
    source: vnode
    target: /var/www/test/static
    volume:
      nocopy: true

Der nocopy: true hält unsere Absicht klar, dass auf der ursprünglichen Karte des Containers der Inhalt des zugeordneten Ordners nicht kopiert werden sollte. Standardmäßig erhält der erste Container, der dem Volume zugeordnet wird, den Inhalt des zugeordneten Ordners. In Ihrem Fall möchten Sie, dass dies der node-Container ist.

Stellen Sie außerdem sicher, dass Sie vor dem Testen den folgenden Befehl ausführen, um die zwischengespeicherten Volumes zu beenden

docker-compose down -v

Sie können während meines Tests sehen, dass der Container die Dateien hatte

 Nginx has files

8
Tarun Lalwani

Erklärung, was Schritt für Schritt geschieht

Dockerfile.node

    ...
    COPY ./client /usr/src
    ...

docker-compose.yml

services:
  ...
  node:
    ...
    volumes:
      - ./server/nginx.conf:/etc/nginx/nginx.conf:ro
      - vnode:/usr/src
  ...
volumes:
  vnode:
  1. docker-compose up erstellt mit diesem Dockerfile.node- und Docker-Compose-Abschnitt ein benanntes Volume mit Daten, die in/usr/src gespeichert sind.

Dockerfile.nginx

FROM nginx:latest

COPY ./server/nginx.conf /etc/nginx/nginx.conf

RUN mkdir -p /var/www/tg/static

EXPOSE 80
EXPOSE 443

CMD ["nginx", "-g", "daemon off;"]
  1. Das erzeugt, dass mit docker-compose erstellte Nginx-Container einen leeren /var/www/tg/static/ haben. 

docker-compose.yml

 ...
 nginx:
    build:
      context: .
      dockerfile: ./Dockerfile.nginx
    container_name: tg_nginx
    restart: always
    volumes:
      - ./server/nginx.conf:/etc/nginx/nginx.conf:ro
      - vnode:/var/www/tg/static
    ports:
      - "80:80"
      - "443:443"
    depends_on:
      - node
      - gunicorn
    networks:
      - nw_web_tg

 volumes:
   vdata:
   vnode:
  1. docker-compose up erzeugt, dass das mit vnode benannte Volume erstellt und mit Daten von /var/www/tg/static (jetzt leer) in den vorhandenen vnode gefüllt wird.

An diesem Punkt - Nginx-Container hat/var/www/tg/static leer, da er leer erstellt wurde (siehe mkdir in Dockerfile.nginx) - Knotencontainer hat/usr/src dir mit der Clientdatei (siehe in Dockerfile.node kopiert) - vnode hat den Inhalt von/usr/src von node und /var/www/tg/static von nginx.

Um Daten aus/usr/src von Ihrem node-Container an /var/www/tg/static in nginx-Container zu übergeben, müssen Sie definitiv etwas tun, das nicht sehr hübsch ist, da Docker noch keinen anderen Weg entwickelt hat: Sie müssen named volume in kombinieren Quellordner mit Bind-Volume im Ziel:

 nginx:
     build:
       context: .
       dockerfile: ./Dockerfile.nginx
     container_name: tg_nginx
     restart: always
     volumes:
       - ./server/nginx.conf:/etc/nginx/nginx.conf:ro
       - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static
     ports:
       - "80:80"
       - "443:443"
     depends_on:
       - node
       - gunicorn
     networks:
       - nw_web_tg

Einfach in Docker-Compose - vnode:/var/www/tg/static um - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static ändern

1
mulg0r