library - docker tag
¿Cómo incluir archivos fuera del contexto de compilación de Docker? (10)
¿Cómo puedo incluir archivos desde fuera del contexto de compilación de Docker usando el comando "AGREGAR" en el archivo Docker?
De la documentación de Docker:
La ruta debe estar dentro del contexto de la compilación; no puede AGREGAR ../something/something, porque el primer paso de una compilación de Docker es enviar el directorio de contexto (y subdirectorios) al demonio de Docker.
No quiero reestructurar todo mi proyecto solo para acomodar a Docker en este asunto. Quiero mantener todos mis archivos Docker en el mismo subdirectorio.
Además, parece que Docker aún no admite (y puede que nunca lo haga ) los enlaces simbólicos: el comando Dockerfile ADD no sigue los enlaces simbólicos en el host # 1676.
Lo único que se me ocurre es incluir un paso previo a la compilación para copiar los archivos en el contexto de compilación de Docker (y configurar mi control de versiones para ignorar esos archivos). ¿Hay una mejor solución para eso?
A menudo me encuentro utilizando la opción
--build-arg
para este propósito.
Por ejemplo, después de poner lo siguiente en el Dockerfile:
ARG SSH_KEY
RUN echo "$SSH_KEY" > /root/.ssh/id_rsa
Solo puedes hacer:
docker build -t some-app --build-arg SSH_KEY="$(cat ~/file/outside/build/context/id_rsa)" .
Pero tenga en cuenta la siguiente advertencia de la documentación de Docker :
Advertencia: no se recomienda usar variables de tiempo de compilación para pasar secretos como claves github, credenciales de usuario, etc. Los valores de las variables de tiempo de compilación son visibles para cualquier usuario de la imagen con el comando docker history.
Creo que la solución más simple sería cambiar el "contexto" en sí.
Entonces, por ejemplo, en lugar de dar:
docker build -t hello-demo-app .
que establece el directorio actual como contexto, digamos que desea el directorio principal como contexto, solo use:
docker build -t hello-demo-app ..
En Linux, puede montar otros directorios en lugar de simularlos
mount --bind olddir newdir
Consulte https://superuser.com/questions/842642 para obtener más detalles.
No sé si hay algo similar disponible para otros sistemas operativos. También intenté usar Samba para compartir una carpeta y volver a montarla en el contexto de Docker, que también funcionó.
La mejor manera de evitar esto es especificar el Dockerfile independientemente del contexto de compilación, usando -f.
Por ejemplo, este comando le dará acceso al comando ADD a cualquier cosa en su directorio actual.
docker build -f docker-files/Dockerfile .
Actualización : Docker ahora permite tener el Dockerfile fuera del contexto de compilación (corregido en 18.03.0-ce, https://github.com/docker/cli/pull/886 ). Entonces también puedes hacer algo como
docker build -f ../Dockerfile .
Pasé un buen rato tratando de descubrir un buen patrón y cómo explicar mejor lo que está sucediendo con esta función de soporte. Me di cuenta de que la mejor manera de explicarlo era la siguiente ...
- Dockerfile: solo verá archivos bajo su propia ruta relativa
- Contexto: un lugar en el "espacio" donde se copiarán los archivos que desea compartir y su Dockerfile
Entonces, dicho esto, aquí hay un ejemplo del Dockerfile que necesita reutilizar un archivo llamado
start.sh
Dockerfile
ALWAYS
se cargará desde su ruta relativa, teniendo el directorio actual de sí mismo como referencia
local
a las rutas que especifique.
COPY start.sh /runtime/start.sh
Archivos
Teniendo en cuenta esta idea, podemos pensar en tener varias copias para los Dockerfiles que compilan elementos específicos, pero todos necesitan acceso a
start.sh
.
./all-services/
/start.sh
/service-X/Dockerfile
/service-Y/Dockerfile
/service-Z/Dockerfile
./docker-compose.yaml
Teniendo en cuenta esta estructura y los archivos anteriores, aquí hay un docker-compose.yml
docker-compose.yaml
-
En este ejemplo, su directorio de contexto
shared
es el directorio deruntime
.-
El mismo modelo mental aquí, piensa que todos los archivos bajo este directorio se mueven al llamado
context
. -
Del mismo modo, solo especifique el Dockerfile que desea copiar en ese mismo directorio.
Puede especificar eso usando
dockerfile
.
-
El mismo modelo mental aquí, piensa que todos los archivos bajo este directorio se mueven al llamado
- el directorio donde se encuentra su contenido principal es el contexto real que se establecerá.
El
docker-compose.yml
es el siguiente
version: "3.3"
services:
service-A
build:
context: ./all-service
dockerfile: ./service-A/Dockerfile
service-B
build:
context: ./all-service
dockerfile: ./service-B/Dockerfile
service-C
build:
context: ./all-service
dockerfile: ./service-C/Dockerfile
-
all-service
se establece como contexto, el archivo compartidostart.sh
se copia allí y el Dockerfile especificado por cadadockerfile
. - ¡Cada uno se construye a su manera, compartiendo el archivo de inicio!
¡Salud!
Si lee la discusión en el número 2745, no solo Docker nunca admitirá enlaces simbólicos, sino que nunca admitirá agregar archivos fuera de su contexto. Parece ser una filosofía de diseño que los archivos que entran en la construcción de Docker deberían ser explícitamente parte de su contexto o ser de una URL donde presumiblemente también se implementa con una versión fija para que la construcción sea repetible con URL o archivos bien conocidos enviados con el contenedor acoplable.
Prefiero construir desde una fuente controlada por versión, es decir, docker build -t stuff http://my.git.org/repo , de lo contrario, estoy construyendo desde algún lugar aleatorio con archivos aleatorios.
fundamentalmente, no ... - SvenDowideit, Docker Inc
Solo es mi opinión, pero creo que debería reestructurarse para separar el código y los repositorios de Docker. De esa manera, los contenedores pueden ser genéricos y extraer cualquier versión del código en tiempo de ejecución en lugar de en tiempo de compilación.
Alternativamente, use docker como su artefacto fundamental de implementación de código y luego coloque el dockerfile en la raíz del repositorio de código. si sigue esta ruta, probablemente tenga sentido tener un contenedor acoplable principal para obtener detalles más generales del nivel del sistema y un contenedor secundario para la configuración específica de su código.
También puede crear un tarball de lo que la imagen necesita primero y usarlo como contexto.
https://docs.docker.com/engine/reference/commandline/build/#/tarball-contexts
Tuve este mismo problema con un proyecto y algunos archivos de datos que no pude mover dentro del contexto de repositorio por razones de HIPPA. Terminé usando 2 Dockerfiles. Uno construye la aplicación principal sin las cosas que necesitaba fuera del contenedor y las publica en un repositorio interno. Luego, un segundo dockerfile extrae esa imagen y agrega los datos y crea una nueva imagen que luego se implementa y nunca se almacena en ningún lugar. No es ideal, pero funcionó para mis propósitos de mantener la información confidencial fuera del repositorio.
Una solución fácil podría ser simplemente montar el volumen (usando el indicador -v o --mount) en el contenedor cuando lo ejecute y acceda a los archivos de esa manera.
ejemplo:
docker run -v /path/to/file/on/host:/desired/path/to/file/in/container/ image_name
para más información, consulte: https://docs.docker.com/storage/volumes/
Usando docker-compose, logré esto creando un servicio que monta los volúmenes que necesito y confirmando la imagen del contenedor.
Luego, en el servicio posterior, confío en la imagen previamente comprometida, que tiene todos los datos almacenados en ubicaciones montadas.
Luego tendrá que copiar estos archivos a su destino final, ya que los directorios montados en el host no se comprometen al ejecutar un comando de
docker commit
No tiene que usar docker-compose para lograr esto, pero hace la vida un poco más fácil
# docker-compose.yml
version: ''3''
services:
stage:
image: alpine
volumes:
- /host/machine/path:/tmp/container/path
command: bash -c "cp -r /tmp/container/path /final/container/path"
setup:
image: stage
# setup.sh
# Start "stage" service
docker-compose up stage
# Commit changes to an image named "stage"
docker commit $(docker-compose ps -q stage) stage
# Start setup service off of stage image
docker-compose up setup