web-dev-qa-db-fra.com

Docker - Impossible de partager des données entre les conteneurs d'un même volume (docker-compose 3)

J'ai quelques conteneurs pour une application web pour le moment (nginx, gunicorn, postgres et node pour construire des fichiers statiques à partir de la source et un rendu côté serveur React). Dans un fichier Docker pour le conteneur de nœuds, j’ai deux étapes: construire et exécuter ( Dockerfile.node ). Il se termine avec deux répertoires à l'intérieur d'un conteneur: bundle_client - est un statique pour un nginx et bundle_server - utilisé dans le conteneur de nœud lui-même pour démarrer un serveur express.

Ensuite, je dois partager un dossier statique construit (bundle_client) avec le conteneur nginx. Pour ce faire, conformément à la référence de docker-compose dans mon docker-compose.yml, j’ai les services suivants (voir complet docker-compose.yml ):

node:
  volumes:
    - vnode:/usr/src

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

et volumes:

volumes:
  vnode:

L'exécution de docker-compose build se termine sans erreur. Exécuter docker-compose up fonctionne correctement et je peux ouvrir localhost:80 et il y a nginx, gunicorn et node express SSR tout fonctionne très bien et je peux voir une page Web mais tous les fichiers statiques retournent une erreur 404 non trouvée.

Si je vérifie les volumes avec docker volume ls, je peux voir deux volumes nouvellement créés nommés tg_vnode (que nous considérons ici) et tg_vdata (voir full docker-compose.yml)

Si je vais dans un conteneur nginx avec docker run -ti -v /tmp:/tmp tg_node /bin/bash, je ne pourrai pas voir mon dossier www/tg/static qui mappera mes fichiers statiques à partir du volume du noeud. De plus, j'ai essayé de créer un dossier /var/www/tg/static vide avec le conteneur nginx Dockerfile.nginx mais il reste vide.

Si je mappe un dossier bundle_client à partir de la machine hôte dans le docker-compose.yml dans une section nginx.volumes en tant que - ./client/bundle_client:/var/www/tg/static, cela fonctionne bien et je peux voir tous les fichiers statiques servis avec nginx dans le navigateur.

Qu'est-ce que je fais de mal et comment faire en sorte que mon conteneur partage le contenu statique construit avec le conteneur nginx?

PS: J'ai lu tous les docs, tous les problèmes de github et les questions et réponses de stackoverflow et, si j'ai bien compris, il doit fonctionner et il n'y a aucune information à propos de ce qu'il faut faire quand ne l'est pas.

UPD: Résultat de 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"
}
]

Fichiers: Dockerfile.node , docker-compose.yml

Nginx dockerfile: Dockerfile.nginx


UPD: J'ai créé un référentiel simplifié pour reproduire une question: repo (Il y a des avertissements sur npm install que rien ne s'installera et que l'on construira correctement). Lorsque nous ouvrons localhost:80, nous voyons finalement une page vide et 404 messages pour les fichiers statiques (vendor.js et app.js) dans les outils de développement de Chrome, mais il devrait y avoir un message React app: static loaded généré par le script react.

7
Max

Deux changements dont vous avez besoin. Dans votre service de nœud et le volume comme

volumes:
  - vnode:/usr/src/bundle_client

Puisque vous voulez partager /usr/src/bundle_client, vous ne devez PAS utiliser /usr/src/ car cela partagera également le dossier complet et la structure.

Et puis dans votre service nginx, ajoutez le volume comme

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

Le nocopy: true indique clairement que sur la carte initiale du conteneur, le contenu du dossier mappé ne doit pas être copié. Et par défaut, le premier conteneur mappé sur le volume obtiendra le contenu du dossier mappé. Dans votre cas, vous souhaitez que ce soit le conteneur node.

De même, avant de procéder aux tests, assurez-vous d’exécuter la commande ci-dessous pour supprimer les volumes mis en cache.

docker-compose down -v

Vous pouvez voir pendant le test que le conteneur contenait les fichiers

 Nginx has files

8
Tarun Lalwani

Explication de ce qui se passe étape par étape

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 crée avec ce Dockerfile.node et la section docker-compose un volume nommé avec les données enregistrées dans/usr/src.

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. Cela produit que les conteneurs nginx créés avec docker-compose auront un /var/www/tg/static/ vide 

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 produira que le volume vnode nommé est créé et rempli avec les données de /var/www/tg/static (vide à présent) dans un vnode existant.

Donc, à ce stade, - Le conteneur nginx a/var/www/tg/static vide car il a été créé vide (voir mkdir dans Dockerfile.nginx) - Le conteneur de noeud a/usr/src dir avec le fichier client (voir ce qui a été copié dans Dockerfile.node) - vnode a le contenu de/usr/src de node et /var/www/tg/static de nginx.

En définitive, pour passer des données de/usr/src de votre conteneur node à /var/www/tg/static dans un conteneur nginx, vous devez faire quelque chose qui n’est pas très joli car Docker n’a pas encore développé une autre méthode: vous devez combiner nommé volume in dossier source avec bind volume in destination:

 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

Il suffit de changer docker-composer - vnode:/var/www/tg/static par - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static

1
mulg0r