447 votes

Comment monter un seul fichier dans un volume

J'essaie de dockeriser une application PHP. Dans le fichier de docker, je télécharge l'archive, je l'extrais, etc.

Tout fonctionne bien. Cependant, si une nouvelle version est publiée et que je mets à jour le fichier docker, je dois réinstaller l'application, car le fichier config.php est écrasé.

J'ai donc pensé que je pouvais monter le fichier comme un volume, comme je le fais avec la base de données.

Je l'ai essayé de deux façons, avec un volume et un chemin direct.

docker-compose :

version: '2'
services:
  app:
    build: src
    ports:
      - "8080:80"
    depends_on:
      - mysql
    volumes:
      -  app-conf:/var/www/html/upload
      -  app-conf:/var/www/html/config.php
    environment:
      DB_TYPE: mysql
      DB_MANAGER: MysqlManager

  mysql:
    image: mysql:5.6
    container_name: mysql
    volumes:
      - mysqldata:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_ROOT_PASSWORD:
      MYSQL_DATABASE:
      MYSQL_USER:
      MYSQL_PASSWORD:

volumes:
  mysqldata:
  app-conf:

Ce qui entraîne l'erreur :

Et je l'ai essayé avec un chemin donné, comme un volume monté.

/src/docker/myapp/upload:/var/www/html/upload
/src/docker/myapp/upload:/var/www/html/config.php

Cependant, les deux méthodes ne fonctionnent pas. Avec le volume monté, je vois que le téléchargement est créé.

Mais ensuite il échoue avec :

/var/www/html/config.php \" causé \" pas un répertoire \""

Si je l'essaie avec

/src/docker/myapp/upload/config.php:/var/www/html/config.php

Docker crée le dossier de téléchargement et ensuite un dossier config.php. Pas un dossier.

Ou existe-t-il un autre moyen de faire persister la configuration ?

5 votes

Dans mon cas, je l'ai simple pour "toucher" un fichier vide avant de créer le conteneur/volume. Si le fichier n'existait pas, il créait un répertoire.

569voto

BlackStork Points 1497

TL;DR/Notice :

Si vous constatez qu'un répertoire est créé à la place du fichier que vous essayez de monter, vous avez probablement omis de fournir un fichier valide y absolu chemin. Il s'agit d'une erreur courante avec un mode de défaillance silencieux et déroutant.

Les volumes de fichiers se font de cette manière dans docker (exemple de chemin absolu (peut utiliser des variables env), et vous devez mentionner le nom du fichier) :

    volumes:
      - /src/docker/myapp/upload:/var/www/html/upload
      - /src/docker/myapp/upload/config.php:/var/www/html/config.php

Vous pouvez aussi le faire :

    volumes:
      - ${PWD}/upload:/var/www/html/upload
      - ${PWD}/upload/config.php:/var/www/html/config.php

Si vous lancez le docker-compose à partir de /src/docker/myapp dossier

136 votes

Comme je l'ai dit, si j'essaie /src/docker/myapp/upload/config.php:/var/www/html/config.php, Docker crée le dossier upload puis un dossier config.php. Pas un dossier.

13 votes

Dans votre message, vous avez écrit différemment. Si le fichier est là, il devrait être monté en tant que fichier.

0 votes

docs.docker.com/engine/tutorials/dockervolumes/#/ <- devrait être en train de travailler

130voto

SangminKim Points 2531

Je souffrais d'un problème similaire. J'essayais d'importer mon fichier de configuration dans mon conteneur afin de pouvoir le corriger à chaque fois que j'en ai besoin sans avoir à recompiler l'image.

Je pensais que la commande ci-dessous correspondrait $(pwd)/config.py de l'hôte Docker vers /root/app/config.py dans le conteneur sous forme de fichier.

docker run -v $(pwd)/config.py:/root/app/config.py my_docker_image

Cependant, il a toujours créé un répertoire nommé config.py et non un fichier.

alors que je cherchais un indice, j'ai trouvé la raison(de aquí )

Si vous utilisez -v ou --volume pour lier le montage d'un fichier ou d'un répertoire qui n'existe pas encore sur le disque dur de Docker, vous pouvez le faire. n'existe pas encore sur l'hôte Docker, -v créera le point de terminaison pour vous. Il est toujours créé comme un répertoire .

Par conséquent, il est toujours créé en tant que répertoire car mon hôte Docker ne dispose pas de $(pwd)/config.py .

Même si je crée config.py dans l'hôte docker. $(pwd)/config.py juste au-dessus /root/app/config.py ne pas exporter /root/app/config.py .

28 votes

Je viens d'ajouter un touch path/to/file dans le Dockerfile pour que lorsque je monte, ce soit toujours un fichier (pas un répertoire créé).

11 votes

Côté gauche de : doit être un chemin complet. Cela fonctionne de la manière suivante

2 votes

El touch était la réponse, faites-le dans le Dockerfile puis votre montage de volume docker-compose fonctionnera correctement sans créer de répertoire.

76voto

Subbu M Points 21

Utilice mont ( --mount ) au lieu de volume ( -v )

Plus d'informations : https://docs.docker.com/storage/bind-mounts/

Ejemplo:

S'assurer que /tmp/a.txt existe sur l'hôte docker

docker run -it --mount type=bind,source=/tmp/a.txt,target=/root/a.txt alpine sh

0 votes

Merci Subbu, @Jakub Juszczak cette réponse devrait être acceptée, c'est la seule qui réponde à la question, et elle a fonctionné pour moi.

3 votes

Cela ne répond pas vraiment à la question. volumes fonctionnera également (car le problème se situe au niveau du chemin absolu). La seule différence entre --mount y -v est le comportement lorsque la partie hôte du volume n'existe pas encore. Conformément à votre lien : >Si vous utilisez -v ou --volume pour lier le montage d'un fichier ou d'un répertoire qui n'existe pas encore sur l'hôte Docker, -v crée le point de terminaison pour vous. Il est toujours créé en tant que répertoire.

6 votes

Je ne sais pas comment traduire cela dans un docker-compose. Un peu d'aide ?

26voto

Justin Lessard Points 891

Pour tous ceux qui, comme moi, utilisent les conteneurs Windows, sachez que vous NE POUVEZ PAS lier ou monter des fichiers uniques en utilisant les conteneurs Windows.

Les exemples suivants échouent lorsqu'on utilise des conteneurs Windows, car la destination d'un volume ou d'un montage lié à l'intérieur du conteneur doit être l'un des éléments suivants : un répertoire inexistant ou vide ; ou un lecteur autre que C :. Plus loin, la source d'un mount bind doit être un répertoire local, pas un fichier .

net use z: \\remotemachine\share

docker run -v z:\foo:c:\dest ...

docker run -v \\uncpath\to\directory:c:\dest ...

docker run -v c:\foo\somefile.txt:c:\dest ...

docker run -v c:\foo:c: ...

docker run -v c:\foo:c:\existing-directory-with-contents ...

C'est difficile à repérer mais c'est là

Lien vers le problème Github concernant le mappage des fichiers dans le conteneur Windows

2 votes

Savez-vous si c'est toujours le cas en juillet 2020 ?

1 votes

@OvidiuBuligan Oui. Selon un commentaire d'un développeur de docker sur la question, il est préférable de monter le répertoire de toute façon, même sur linux. Ils ont également dit qu'ils ne peuvent pas permettre ce comportement sans une réécriture massive. Donc je doute vraiment que nous verrons cela à court-moyen terme.

0voto

jla Points 1

Pour moi, le problème était que j'avais un lien symbolique brisé sur le fichier que j'essayais de monter dans le conteneur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X