Cómo hacer que una carpeta con enlace simbólico aparezca como una carpeta normal

38

Tengo dos aplicaciones Dart que necesito dockerize. Estas dos aplicaciones usan un directorio fuente compartido.
Debido a que Docker evita agregar archivos desde carpetas fuera del directorio de contexto ( project/app1) no puedo agregar archivos desde ../sharedni desde shared(el enlace simbólico dentro projects/app1).

Estoy buscando una manera de engañar a Docker para que lo haga de todos modos.

Mi estructura de proyecto simplificada

- projects
  - app1
   - Dockerfile
   - shared (symlink ../shared)
   - otherSource
  - app2
   - Dockerfile
   - shared (symlink ../shared)
   - otherSource
  - shared
    - source

Podría subir Dockerfileun nivel y ejecutar docker builddesde allí, pero luego necesito dos Dockerfiles (para app1 y app2) en el mismo directorio.

Mi idea actual era que si de alguna manera pudiera ocultar el hecho de que projects/app1/sharedes un enlace simbólico, este problema se resolvería. Verifiqué si puedo compartir projectsusando Samba y volver a montarlo en otro lugar y configurar Samba para tratar los enlaces simbólicos como carpetas normales, pero no he encontrado si esto es compatible (no tengo mucha experiencia con Samba y aún no lo he probado, solo busqué un poco) .

¿Hay alguna otra herramienta o truco que lo permita?

Preferiría no cambiar la estructura del directorio porque esto causaría otros problemas y también no copiaría los archivos.

zoechi
fuente

Respuestas:

35

No tengo mucha experiencia, dockerasí que no puedo prometer que esto funcionará, pero una opción sería montar el directorio en lugar de vincularlo:

$ cd projects/app1
$ mkdir shared
$ sudo mount -o bind ../shared shared/

Que se adhiera ../shareda ./sharedy debe ser totalmente transparente para el sistema. Como se explica en man mount:

La unión se monta.

Desde Linux 2.4.0 es posible volver a montar parte de la jerarquía de archivos en otro lugar. La llamada es:

mount --bind olddir newdir

o usando esta entrada fstab:

/olddir /newdir none bind

Después de esta llamada, se puede acceder a los mismos contenidos en dos lugares.

terdon
fuente
1
@zoechi esto es perfectamente sobre el tema en ambos sitios. Como regla general, publicaría más preguntas técnicas como esta en U&L y más preguntas de espacio de usuario aquí. Sin embargo, la elección es completamente suya. Por un lado, hay más usuarios aquí, por lo que hay más ojos, por otro lado, hay una concentración mucho mayor de personas profesionales * nix en U&L. Solo asegúrese de no publicar la misma pregunta en ambos sitios. Si desea moverlo, elimínelo o marque la atención del mod y solicite que migren.
terdon
2
¡Era obligatorio para mí reiniciar Docker Daemon! De lo contrario, el directorio montado no era visible en el contenedor.
tenue
@dim sí! Traté de hacer que funcione con Capistrano y no funcionó - resulta que monté los directorios compartidos después de que comencé el contenedor
csch
Lamentablemente, esto no funcionará para usuarios de Windows u OS X. El debate sobre este tema ha sido ... animado.
Jason
¿el montaje está 'comprometido' con el control de fuente, por ejemplo, github? o tendría que hacerlo todo el tiempo?
pie6k
23

Este problema ha surgido repetidamente en la comunidad Docker. Básicamente viola el requisito de que Dockerfilesea ​​repetible si lo ejecutas o yo lo ejecuto. Por lo tanto, no esperaría esta capacidad, como se describe en este ticket: el comando Dockerfile ADD no sigue los enlaces simbólicos en el host # 1676 .

Entonces debes concebir un enfoque diferente. Si observa este problema: AGREGAR para admitir enlaces simbólicos en el argumento # 6094 , un amigo nuestro de U&L ( @Patrick aka. Phemmer) proporciona una solución inteligente.

$ tar -czh . | docker build -

Esto le indica tara desreferenciar los enlaces simbólicos del directorio actual y luego canalizarlos al docker build -comando.

extracto de la página del manual de tar
-c, --create
       create a new archive

-h, --dereference
       follow symlinks; archive and dump the files they point to

-z, --gzip, --gunzip --ungzip
slm
fuente
3
¡Esta es una solución EXCELENTE! Entiendo por qué Docker afirma que quieren omitir esta función. Sin embargo, hay una diferencia considerable en el flujo de trabajo que uso al desarrollar mi proyecto de contenedores y en cómo espero que se cree para la producción. En mi máquina local, quiero un circuito de retroalimentación muy ajustado. Mi aplicación tiene 1 repositorio de git y el entorno de compilación para los contenedores tiene un segundo repositorio. Necesito poder hacer ediciones y construir pruebas localmente antes de poder decidir si quiero comprometerme y presionar. No tendré enlaces simbólicos o instrucciones ADD en mi proyecto final.
Bruno Bronosky
66
Los Dockerfiles no son repetibles. Los dockerfiles no pueden hacerse repetibles, porque casi todos tienen apt-get o algo equivalente en la segunda o tercera capa y apt-get no es repetible. Al vincular la estrategia de desarrollo de Docker con un intento equivocado de hacer realidad lo imposible, solo se cargará a Docker con una serie de malas abstracciones que no ayudan a nadie. nathanleclaire.com/blog/2014/09/29/…
Jason
1
Ok, entonces realmente no veo por qué esto es mejor que un cpcomando, ¿puedes explicar por qué es mejor? También creo que la tubería es confusa / demasiado complicada. ¿Por qué no simplemente colocar el comando tar sobre el comando build? Supongo que entonces sobrescribirías el directorio enlazado con el directorio real.
Alexander Mills
1
@AlexanderMills: la mejor manera de ver lo que sucede es probarlo y ver la diferencia. Además, lo anterior es un edificio de un contenedor, no un funcionamiento, por lo que no hay montaje. stackoverflow.com/questions/37328370/… . Le sugiero que pruebe todas estas cosas, tendrá mucho más sentido.
slm
1
Acabo de agregar /bin/cp ../requirements.txt . && docker build ...a un Makefile para construir el Docker, fue más fácil
user5359531