Moby: Restablecer propiedades heredadas de la imagen principal

Creado en 6 ene. 2014  ·  153Comentarios  ·  Fuente: moby/moby

Al crear una imagen, es posible que desee restablecer algunas de sus propiedades en lugar de heredarlas de la imagen principal. Tiene sentido heredar todas las propiedades de forma predeterminada, pero debería haber una forma de restablecerlas de forma explícita y selectiva cuando tenga sentido.

Esta es una solución más genérica para # 2210 que solo se dirige a expose .

arebuilder kinenhancement statuneeds-attention

Comentario más útil

Definitivamente me gustaría tener alguna forma de eliminar los puntos de VOLUMEN heredados de las imágenes principales.

Por ejemplo, supongamos que tuviera una imagen principal para una aplicación que usaba un punto de montaje externo para datos persistentes, pero también quería una imagen basada en ella que se rellenara previamente con datos de prueba. Tal como está, no puedo hacer eso si la imagen principal usó VOLUMEN porque los cambios / adiciones a esos directorios, incluso si esos cambios son durante una compilación de Docker, se pierden en la confirmación.

Todos 153 comentarios

Se aceptan sugerencias para la sintaxis.

Lo mejor que se me ocurre son los comandos correspondientes como UNVOLUME o más genéricamente -VOLUME (pero eso agregaría más confusión y potencialmente incluso crearía la idea errónea de que +VOLUME debería funcionar, y debería funcionar de manera diferente a solo VOLUME ).

Definitivamente quiero tal cosa (especialmente para VOLUMES). También es un poco desorientador que cosas como VOLUMEN se apliquen a las siguientes líneas de RUN, pero cosas como ENTRYPOINT no. A veces eso es muy útil, ya veces no lo es, pero una "desactivación de la instrucción X previa" genérica podría resolver los problemas en torno a eso bastante bien.

¿Hay alguna solución para esto mientras tanto? Estoy ampliando una imagen con un ENTRYPOINT (https://github.com/jagregory/pandoc-docker/blob/master/Dockerfile) y necesito desarmar el punto de entrada. Intenté usar lo siguiente en mi Dockerfile:

FROM jagregory/pandoc
ENTRYPOINT [] # this basically gets ignored (bug?)

FROM jagregory/pandoc
ENTRYPOINT [""] # this will make docker try to exec '' (the empty string)

FROM jagregory/pandoc
ENTRYPOINT ["/bin/sh", "-c"] 
# this will only work if docker run args are quoted:
#   docker run dergachev/pandoc "echo a b c"

¡Gracias!

Definitivamente me gustaría tener alguna forma de eliminar los puntos de VOLUMEN heredados de las imágenes principales.

Por ejemplo, supongamos que tuviera una imagen principal para una aplicación que usaba un punto de montaje externo para datos persistentes, pero también quería una imagen basada en ella que se rellenara previamente con datos de prueba. Tal como está, no puedo hacer eso si la imagen principal usó VOLUMEN porque los cambios / adiciones a esos directorios, incluso si esos cambios son durante una compilación de Docker, se pierden en la confirmación.

Solo para actualizar desde el comentario de CMD [] y ENTRYPOINT [] estaban funcionando la última vez que los probé recientemente y aún deberían estar funcionando (cualquier otra cosa estaría lista para la presentación de errores).

Puede restablecer todos los comandos de opción única a través de

ENTRYPOINT []
CMD []
USER 0
WORKDIR /

Esto debería dejar los metadatos restantes que no se pueden restablecer como ENV , VOLUME , EXPOSE y tal vez ONBUILD .

(Esto viene del # 8709)

Si expuse los sockets 9000-9002 en el padre, pero necesitaba eliminar 9001 en el hijo, entonces tendría que escribir en el estilo de "desarmar"

EXPONER
EXPONER 9000
EXPONER 9002

que funcionaria pero

UNEXPONER 9001

se ve mejor.

Una ventaja es que no afecta a ninguna EXPOSICIÓN de más arriba en la cadena de herencia, lo que podría querer agregar más adelante.

+1 @ codeon-nat

Esto se ha discutido en el n. ° 8177, cerramos esto por falta de casos de uso del mundo real.

¿Por qué se cierra esto? Había 9 personas comentando aquí. Creo que sería muy útil tener esto. Los casos de uso del mundo real se pueden construir sobre imágenes existentes con facilidad. A veces desea agregar una propiedad, a veces desea eliminarla. Esto es normal.

Estoy de acuerdo, por ejemplo, estoy ampliando la imagen nginx para un descargador SSL y quiero UNEXPOSE 80 pero dejo 443 .

Ser capaz de no exponer puertos es bastante crítico si desea ejecutar varias instancias de, por ejemplo, nginx.

No importa, esta fue solo una mala configuración de mi lado.

(15 de abril: "No hay casos de uso del mundo real", me sorprende que no puedas imaginar al menos uno y cerré esto)

Tengo una imagen base que expone volúmenes o puertos para software opcional, luego DESDE eso en otro Dockerfile para hacer una imagen que no debería exponer nada que no quiera, o incluso cosas que haya desinstalado del antepasado. ¿Por qué NO querríamos poder eliminar estas configuraciones?

También tengo un caso de uso para esto. Quiero poder crear una imagen que contenga una instantánea de la base de datos, pero todos los paquetes mysql tienen VOLUME /var/lib/mysql set. Sería bueno poder apagar el volumen, los cambios en la base de datos realizados en mi Dockerfile se quedarán con la imagen.

La única otra opción es recrear completamente una imagen mysql personalizada, pero eso de alguna manera parece un desperdicio ya que muchas otras personas ya han creado mejores servidores mysql predeterminados que yo.

Agregando un caso de uso adicional: estoy heredando de la imagen oficial de RabbitMQ, pero solo quiero exponer los puertos websocket (80 y 443) y no el puerto AMQP predeterminado (5672). ¿Parece que esto debería ser algo bastante razonable para querer hacer?

Añadiendo otro caso de uso. Quiero crear un entorno de prueba de git utilizando la imagen de gogs, pero es tedioso que los datos persistan, ya que están todos almacenados en un volumen. Sería genial si pudiera simplemente DESVOLUMINAR el volumen y construir mi imagen después de configurar el entorno.

+1

heredando del php oficial y desea usar sockets en lugar de puertos, por lo que es necesario eliminar el puerto 9000 expuesto

Cualquiera que haya usado Docker en una capacidad no trivial habrá encontrado estas limitaciones con los contenedores heredados.

@shykes @icecrime ¿cómo es esto ahora cerrado? ¿Es demasiado difícil de resolver con la sintaxis actual y se necesita compatibilidad con versiones anteriores? ¿Cuál es el plan?

+1: caso de uso del mundo real para la anulación EXPOSE aquí.

Teniendo en cuenta que esto ha estado sucediendo durante más de 3 años (problema encontrado que se remonta a 2013), ¿cuándo podremos eliminar los puertos expuestos?

+1. necesita poder "DESINEXPONER" los puertos nginx predeterminados 80 y 443.

Para aquellas personas aquí que piden UNEXPOSE ; la instrucción EXPOSE solo da una pista de qué puertos están expuestos por el contenedor, pero en realidad no _expone_ esos puertos; necesita _publicar_ esos puertos ( -p / -P ) para exponerlos en el host. En otras palabras; omitir la instrucción EXPOSE de un Dockerfile no tiene un efecto directo _no_ en la imagen (aún puede, por ejemplo, alcanzar el "puerto 80" del contenedor).

Además, si desea exponer puertos adicionales, simplemente haga que el servicio en el contenedor se ejecute en esos puertos, y esto funcionará.

Es cierto, pero si usa -P (para exponer todos los puertos) y su imagen base expone un puerto que ya no desea exponer, entonces está atascado. Debería cambiar para usar -p y enumerar todos los demás puertos.

@thaJeztah eso es bueno saberlo. Sin embargo, ¿cuál es el daño de agregar UNEXPOSE? También sería útil para mí, incluso si eso es solo para tener contenedores mejor documentados.

@kgx no daña (aparte de la posible hinchazón de funciones), pero quería explicar que no poder "eliminar" no es un problema de seguridad (algunas personas tienen esa impresión). UNVOLUME (o UNSET VOLUME ) todavía está en mi lista de deseos personal. :-)

Me divierte haber encontrado este problema en las primeras 72 horas después de probar la ventana acoplable. Cada configuración o lenguaje para cualquier otra herramienta importante que uso que tenga algún tipo de herencia tiene un tipo de capacidad de "anular el padre".

Aquí hay un caso de uso: estoy usando la imagen de la ventana acoplable predeterminada para go-ethereum, y necesito poder configurar una versión de prueba que nunca se conectará al mundo exterior. Necesito poder conectarme desde el host y otros contenedores. La forma más segura de hacer esto es cambiar los puertos porque el programa intenta ansiosamente conectarse a sus pares. También necesito poder anular CMD y ENTRYPOINT para crear una versión de "configurar la base de datos" de la imagen que ejecuto una vez para crear el volumen adecuado. Todos estos son extremadamente difíciles de ejecutar en el Dockerfile.

Puede asignarlo a otra dirección IP ... O vincular un puerto de host diferente. Lo último sobre sobrepasar el punto de entrada y cmd es simplemente redefinirlos.

--- Enviado desde Boxer | http://getboxer.com

El 20 de febrero de 2016 a las 08:57:00 GMT, barkthins [email protected] escribió: Este es un caso de uso: estoy usando la imagen de la ventana acoplable predeterminada para go-ethereum y necesito poder configurar una prueba versión que absolutamente nunca se conectará al mundo exterior. Necesito poder conectarme desde el host y otros contenedores. La forma más segura de hacer esto es cambiar los puertos porque el programa intenta ansiosamente conectarse a sus pares. También necesito poder anular CMD y ENTRYPOINT para crear una versión de "configurar la base de datos" de la imagen que ejecuto una vez para crear el volumen adecuado. Todos estos son extremadamente difíciles de ejecutar en el Dockerfile. —Responda a este correo electrónico directamente o véalo en GitHub.

CMD y ENTRYPOINT pueden anularse en tiempo de ejecución; docker run --entrypoint=foo myimage mycmd . La pregunta aquí es si es útil tener una imagen diferente, con un punto de entrada / cmd diferente durante la prueba, ya que no estará _probando_ la imagen real que se ejecutará en producción. (solo una nota al margen)

a partir de estas respuestas, parece que el archivo dockerfile se está desaprobando en favor de las opciones de la línea de comandos al menos en lo que respecta al punto de entrada, cmd, exponer y probablemente algunos otros. La línea de comando ya hace cosas que el Dockerfile no puede hacer, así que esa parece ser la dirección. Si esa es la intención, moveré la mayor cantidad de información de Dockerfile al tiempo de instalación como sea posible solo para reducir la confusión. ¿Esa es la intención?

@barkthins no, el Dockerfile no está en desuso. El uso de un Dockerfile sigue siendo la forma habitual de producir una imagen. Además, puede anular CMD y ENTRYPOINT en imágenes heredadas. Mi ejemplo fue mostrar que en ciertos casos (por ejemplo, ejecutando un comando alternativo en su imagen), puede anularlos en tiempo de ejecución.

Desde la página de manual de Dockerfile:

     -- EXPOSE <port> [<port>...]
     The EXPOSE instruction informs Docker that the container listens

sobre el
puertos de red especificados en tiempo de ejecución. Docker usa esta información para
interconectar contenedores usando enlaces y _para configurar el puerto
redirección en el host_

  • sistema.*
    [...]
    HISTORIA
    * Mayo de 2014, compilado por Zac Dover (zdover en redhat dot com) basado
    en docker.com documentación de Dockerfile. * Febrero de 2015, actualizado por Brian Goff (
    [email protected])
    para legibilidad * Septiembre de 2015, actualizado por Sally O'Malley (
    [email protected])

[mi cursiva] parece engañoso (o al menos ambiguo) si lo que dices es
verdadero.

El jueves 28 de enero de 2016 a las 6:43 a. M., Sebastiaan van Stijn <
[email protected]> escribió:

Para aquellas personas aquí pidiendo UNEXPOSE; la declaración EXPOSE solamente
da una _pista_ qué puertos están expuestos por el contenedor, pero no
en realidad _exponer_ esos puertos; necesitas _publicar_ esos puertos (-p / -P)
para exponerlos en el host. En otras palabras; omitiendo la declaración EXPOSE
de un Dockerfile tiene _no_ efecto directo en la imagen (puede
aún, por ejemplo, alcanzar el "puerto 80" del contenedor).

Además, si desea exponer puertos adicionales, simplemente haga
el servicio en el contenedor se ejecuta en esos puertos, y esto funcionará.

-
Responda a este correo electrónico directamente o véalo en GitHub
https://github.com/docker/docker/issues/3465#issuecomment -176012915.

Actualmente es coautor de un libro en Docker: obtenga un 39% de descuento con el código 39miell
http://manning.com/miell/?a_aid=zwischenzugs&a_bid=e0d48f62

thaJeztah Mi punto y creo que el punto de este hilo es que la herencia es inconsistente. Sí, puede anular ENTRYPOINT y CMD, pero EXPOSE agrega exposición, no puede reemplazar la exposición de los padres excepto en la línea de comando. No he examinado otros comandos para ver si hay un tercer comportamiento. Tampoco está documentado qué comandos extienden o reemplazan el comando de un padre.

@thaJeztah necesitamos UNEXPOSE

Hay varias soluciones que leen los metadatos del contenedor y brindan una configuración ascendente adicional. Por ejemplo; con HAPROXY tengo que configurar EXCLUDE_PORTS=8080 para bloquearlo tratando de proporcionar acceso dinámicamente a ese puerto en mis aplicaciones Tomcat.

Los desarrolladores miran los puertos expuestos y hacen suposiciones sobre el comportamiento del contenedor. Por ejemplo, tengo una imagen base que extiende Tomcat (EXPOSE 8080) pero la imagen usa un puerto diferente al predeterminado (EXPOSE 8888). Si agrega un servidor web en una imagen compuesta (por ejemplo, ejecutando NGINX y Tomcat), ofrece contenido a través de HTTP (EXPOSE 80 y EXPOSE 443).

En el último ejemplo, puede terminar con una imagen que se documenta como exponiendo 8080, 8888, 80 y 443 donde solo 80/443 es relevante.

Estos son problemas reales como lo demuestra el hecho de que tengo que seguir explicando cosas a los desarrolladores de nuestra comunidad a pesar de la documentación muy específica; ¿Quién necesita documentación cuando solo puedes mirar la imagen? <- todo el mundo cuando la imagen está autodocumentando algo incorrecto.

Existen soluciones para este problema, pero son soluciones. ¿Es este un problema arquitectónico importante? ¿Por qué Docker no puede considerar una solución más elegante a este problema real?

¿Cuál es el estado de esto?

El estado de

@modius @BillBrower aunque está cerrado, las cosas siempre se pueden reconsiderar; Básicamente, "no es temporal", pero "sí es para siempre" al fusionar / implementar funciones, por lo que si hay dudas sobre una función, la opción correcta para los encargados del mantenimiento es decir "no".

El RP que implementó esto se cerró porque había mantenedores que no estaban seguros acerca de la función y buscaban ejemplos más reales para su uso; https://github.com/docker/docker/pull/8177#issuecomment -93587164

Estamos cerrando esto porque en su mayoría no estamos de acuerdo, pero siéntase libre de demostrar que estamos equivocados en los comentarios y podemos reconsiderarlo.

Eso fue hace más de un año, por lo que posiblemente las cosas hayan cambiado; Reabriré este problema y lo mencionaré en la próxima sesión de mantenedores. (Tenga en cuenta que debido a DockerCon y la versión pendiente 1.12, esto puede tardar un poco más de lo habitual)

Gracias, @thaJeztah. Eso tiene mucho sentido. Le agradezco que me explique el fundamento de la decisión original y que describa lo que necesita ver si queremos que esto suceda.

Un caso de uso para la solicitud _UNVOLUME_

Especialmente porque actualmente, cuando usa un controlador de volumen personalizado, se aplica a TODO el volumen del contenedor dado.

Tuve el caso con un controlador de volumen EFS: funciona bien cuando especifico el enlace de volumen al inicio. Si no establezco ningún enlace, falla porque intenta montar el recurso compartido NFS desde un UUID generado automáticamente. Esto significa que debo proporcionar un enlace a todos mis volúmenes, incluso al que no me importa, creado por una imagen principal, por ejemplo.

La única solución alternativa en este momento es unir al inicio todo el volumen que no necesito a una subcarpeta vacía de basura del mismo recurso compartido de EFS.

Nota: No puedo usar el comando de volumen de la ventana acoplable porque todo eso lo inicia Marathon y debería poder usarse en un solo comando de ejecución de la ventana acoplable.

+1 UNEXPOSE requerido

+1 para UNEXPOSE

+1 para UNEXPOSE

+1 para UNEXPOSE

+100 por UNEXPOSE

+9000 para UNEXPOSE

+ ∞
Por ejemplo, uso el repositorio oficial nginx (FROM nginx: estable) , que contiene en Dockerfile:

EXPOSE 80 443

Pero quiero quitarlo en otra capa, el puerto 80. Por ejemplo:

UNEXPOSE 80

¡Por favor!
¡Agregue esta característica!

@frekele , si yo fuera tu madre o tu padre, no lo conseguirías. de ninguna manera.

DESEXPONER +++
Característica muy necesaria!

Por favor, no necesita enviar spam a todos los demás con notificaciones por correo electrónico y definitivamente no necesita saturar la discusión con todos estos comentarios "+1". Puede simplemente reaccionar con 👍 a la descripción del problema para expresar su acuerdo.

@underyx esto es fuera de tema, pero morderé porque sigo viendo a la gente decir esto. Tiene más matices de lo que piensas. Para muchos equipos más grandes, la cantidad de comentarios sobre un tema es la única forma de medir la participación, ya que las reacciones están diseñadas como una característica social, no como un mecanismo de votación y, por lo tanto, no son una forma confiable de ejecutar informes a través de la API de GH (p. Ej. no clasificable, entre otras cosas). Además, agregar un comentario automáticamente me suscribe al hilo, que es en la mayoría de los casos lo que quiero; de lo contrario, tendría que hacer clic en 👍 _y_ también hacer clic en "Suscribirse".
Consulte https://github.com/isaacs/github/issues/9#issuecomment -195120703 (todo el hilo es bueno, pero es el momento en que GH agregó reacciones).
Ahora no abarrotemos la discusión;)
/offtopic .

Discutimos este tema en la reunión de mantenedores y, en general, estamos bien para comenzar a trabajar en esto nuevamente.

@duglin , ¿quizás estás interesado en trabajar en esto?

No sé si tengo tiempo todavía, pero solo para resumir ... según los comentarios anteriores, creo que el requisito es asegurarse de que las personas puedan borrar / desarmar lo siguiente:

EXPOSE  (all or specific one)
ENV  (specific - not sure we need to clear all yet)
LABEL  (ditto)
VOLUME  (all or just specific paths? probably both)
CMD  (possible but only using the json format)
ENTRYPOINT  (possible with json format)

¿Yo me perdí algo?

+10000 para UNVOLUME

@duglin Creo que comenzar con los que actualmente _no_ son posibles, y los más solicitados serían los mejores ( EXPOSE , VOLUME ). No he visto muchas solicitudes para los demás (pero no en contra).

El PR original usó UNSET <SOMETHING> , pero luego se cambió a UN<SOMETHING> . A _personalmente_ me gustó el primero más (más genérico), pero @shykes prefirió UN<SOMETHING> , no estoy seguro de si eso ha cambiado.

UNVOLUME estaría bien.

Mi caso de uso: estoy usando la imagen mysql y quiero enviar mi base de datos contenida en el directorio /var/lib/mysql a una nueva imagen, pero no puedo porque está declarada como un volumen en el Dockerfile principal.

@thaJeztah Encuentro UNSET <something> más fácil de leer y no tan extraño; no hay necesidad de empezar a inventar palabras. También es familiar para las personas que escriben guiones. También se podría hacer

UNSET  EXPOSE VOLUME LABEL

Mi ejemplo

Estoy configurando una instalación de dokuwiki. La imagen que elegí exponía todos los volúmenes de configuración potenciales. Lo que me gustaría hacer es personalizar mi instalación a partir de esta imagen base. Como los volúmenes están expuestos, no puedo modificar los archivos de configuración de PHP en el momento de la construcción de la imagen.

Puedo modificar la imagen base para DESVOLUMINAR esos volúmenes, pero luego tendré que mantener esa imagen para siempre ... la magia de usar "último" se ha ido :(

+1 para UNEXPOSE :)

+1 para UNVOLUME o mejor aún, UNSET VOLUME.

+1 para UNVOLUME. Esto podría serme útil ahora mismo. También podría ser útil en escenarios universitarios donde los estudiantes giran sin preocuparse por tener que montar volúmenes.

sin preocuparse por tener que montar volúmenes.

No creo que sea necesario para eso; una definición de VOLUME en un Dockerfile crea automáticamente un volumen "anónimo" del contenido en esa ubicación en la imagen.

@duglin , ¿ya estás trabajando en esto? Si no, lo cogería y empezaría con el más solicitado (VOLUMEN y EXPONER). Hágamelo saber.

@runcom, adelante, todavía no he podido encontrar el tiempo.

Como recordatorio, tenga en cuenta que un comando UNENV aún sería útil para desarmar las variables de entorno de forma selectiva (por ejemplo, para hacer coincidir con un volumen que es UNVOLUME d al mismo tiempo). Una variable no configurada no es lo mismo que una variable configurada en blanco, particularmente cuando se usa con set -ue en shell.

Sería posible eliminar VOLUME y EXPOSE de las imágenes oficiales si
son un problema.

El 28 de enero de 2017 a las 21:23, "henryptung" [email protected] escribió:

Como recordatorio, quisiera señalar que un comando UNENV aún sería útil para
desarmar variables de entorno de forma selectiva (por ejemplo, para hacer coincidir con un
volumen que está SIN VOLUMEN al mismo tiempo). Una variable no definida no es la
Lo mismo que una variable establecida en blanco, particularmente cuando se usa con el conjunto -ue en
cáscara.

-
Estás recibiendo esto porque estás suscrito a este hilo.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/docker/docker/issues/3465#issuecomment-275875623 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AAdcPAKP1tii706MY-8MxVPSFLTFme8Dks5rW7HggaJpZM4BXt2-
.

+1 para UNVOLUME

+1 para UNVOLUME

Mi caso de uso para UNVOLUME:

Usando la imagen de la biblioteca / worpress en un escenario S2I donde la fuente del sitio web se copia en / var / www / html

VOLUME aplasta eso montando un FS vacío en la imagen resultante. -> biblioteca / wordpress no se puede utilizar.

@groulot En realidad, si no monta un volumen explícitamente con --volume encima, el contenido de la imagen se copiará en el volumen en la creación del contenedor.

El comando docker run inicializa el volumen recién creado con cualquier dato que exista en la ubicación especificada dentro de la imagen base.

https://docs.docker.com/engine/reference/builder/#/volume

Hay una solución alternativa hacky al usar Docker save / load, consulte http://stackoverflow.com/q/42316614/808723

+1 para UNVOLUME

Quiero hacerme eco del @modius para poder docker ps para ver qué sucede con sus contenedores. Verán el puerto estándar listado como disponible. Los desarrolladores están acostumbrados a los puertos estándar para cosas de sus entornos locales o de prueba que han configurado en un mundo anterior a Docker, por lo que presentar Docker es difícil porque ven el puerto estándar y piensan que funcionará, pero de hecho lo están no se conecta al contenedor de la ventana acoplable.

+1 para UNVOLUME, UNEXPOSE, UNENV, ...

Parece que esto ha estado abierto por un tiempo. ¿Alguna tracción aquí?
También quiero usar la imagen oficial PHP fpm alpine y los sockets UNIX en lugar del puerto TCP 9000.
No se puede anular EXPOSE del padre, y preferiría no crear esa imagen solo para deshacerse de EXPOSE.

+1

+1

Me encantaría tener la capacidad de desactivar un comando de VOLUMEN. La imagen oficial de Wordpress vierte a la fuerza su código base completo en un volumen; preferiría tener solo un volumen para el directorio wp-content / uploads para que el resto del código base pueda integrarse en la imagen.

Al implementar una imagen en el clúster de kubernetes que restringe el acceso raíz, no se puede acceder a los directorios VOLUME, la solución sería sobrescribir los volúmenes definidos en la imagen principal

+1 de mi parte

Caso de uso para UNEXPOSE

Supongamos que tengo cuatro hosts de la ventana acoplable y quiero ejecutar 16 contenedores maven tomcat, todos predeterminados en el puerto interno 8080.

Ahora imagina que estoy usando el registrador con el ranchero CNI, lo que me bloquea en el puerto interno.
https://github.com/gliderlabs/registrator/issues/541#issuecomment -305012416
Esto significa que solo puedo ejecutar un puerto interno 8080 por host. (Ya que tengo que hacer asignaciones de puertos 8080: 8080)

En esta situación, el mapeo de puertos interno-> externo de docker no es suficiente para resolver mi problema. De hecho, necesito anular la asignación de puertos internos, preferiblemente sin reconstruir el contenedor original.

Julian, no sé cómo tienes un mapeo 1 a 1. Para mi registrador como
nada que ver con el tráfico de enrutamiento, solo registra y cancela el registro
Ejecución de contenedores. Por ejemplo, lo uso de una manera que Registrator mantendrá
una instancia de Etcd colocando la IP asignada a Docker y el puerto expuesto en
allí. Luego, al usar confd, verá una instancia de Etcd y actualizará el nginx
config en su propio contenedor.
El sábado 17 de junio de 2017 a las 04:06, Julian Gamble [email protected]
escribió:

Caso de uso para UNEXPOSE

Supongamos que tengo cuatro hosts de la ventana acoplable y quiero ejecutar 16 maven tomcat
contenedores que, de forma predeterminada, tienen el puerto interno 8080.

Ahora imagina que estoy usando el registrador con el ranchero CNI, lo que me bloquea
al puerto interno.
gliderlabs / registrator # 541 (comentario)
https://github.com/gliderlabs/registrator/issues/541#issuecomment-305012416
Esto significa que solo puedo ejecutar un puerto interno 8080 por host. (Ya que tengo
para hacer asignaciones de puertos 8080: 8080)

En esta situación, el mapeo de puertos interno-> externo de Docker no es suficiente
para solucionar mi problema. De hecho, necesito anular la asignación de puertos internos,
preferiblemente sin reconstruir el contenedor original.

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/moby/moby/issues/3465#issuecomment-309189149 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/ABrq2QGgY81wbePOBKbkTSjpUSoPIocuks5sE0LCgaJpZM4BXt2-
.

Hola Bradley,

Gracias por mirar esto. Estoy usando registrator en combinación con ipsecurity que está integrado en Rancher. Como puede ver en el enlace aquí:
https://github.com/gliderlabs/registrator/issues/541#issuecomment -305012416
Se restringió la capacidad de ver los puertos externos en el registrador en los contenedores programados por los rancheros. Esto significaba que solo podía usar puertos internos.

Puede ver que hay usuarios que se angustian buscando una solución aquí:
https://forums.rancher.com/t/do-you-kill-registrator/5152

Y una solución propuesta aquí:
https://github.com/cabrinoob/rancher-registrator
(Lo que no fue factible para algunas personas).

Puede encontrar más si busca en Google "registrador ranchero".

Recomiendan que ejecute el registrador en un modo 'interno', donde mapee sus puertos internos 1: 1 a sus puertos externos. Esto conduce al problema con UNEXPOSE : quedarse sin puertos internos rápidamente.

Mi punto es que la ipsecurity utilizada para la red de contenedores de la ventana acoplable dentro del host puede llevar a un caso de uso en el que está bloqueado en puertos internos asignados 1: 1 a puertos externos en la ventana acoplable. Para esto, necesita tener un comando UNEXPOSE .

Gracias por mirar esto.

Salud
Julian

¿Han pasado 3,5 años y no hay avances en este tema? ...

+10086 para UNEXPOSE. a veces, la imagen principal puede no ser oficial, utiliza puertos no oficiales, deberíamos tener la capacidad de sobrescribir los puertos.

@ pumba-lt
Apuesto a que la razón por la que esto no ve una solución es que no saben cómo hacerlo técnicamente.

También agrega complejidad al lenguaje Dockerfile cuando hay soluciones claras. No inserte tanta configuración en el Dockerfile principal y déjelo para las imágenes heredadas. (también conocido como: dejar de obtener imágenes aleatorias en Docker Hub: D)

Desde la ventana acoplable 17.05, también hay una nueva forma de realizar compilaciones en varias etapas que elimina la mayor parte de la necesidad de este problema (este es un solo Dockerfile ):

# First import the original image
FROM nginx AS source-image

# Second step of the build, start with an empty image
FROM scratch
# Copy the data from the original image
COPY --from=source-image / /
# Re-define all the config
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

EDITAR: Olvidé decir, la segunda solución aplasta todas las capas anteriores. No creo que sea gran cosa, pero es bueno saberlo.

@zimbatm - ¡Eso es increíble!

Apuesto a que la razón por la que esto no ve una solución es que no saben cómo hacerlo técnicamente.

El cambio en sí no es demasiado complicado; se puede encontrar una implementación en este RP; https://github.com/moby/moby/pull/8177. No hubo consenso en ese momento, pero si sigue mi comentario de enero; https://github.com/moby/moby/issues/3465#issuecomment -247405438, las cosas cambiaron y (a menos que la gente haya cambiado de opinión desde entonces), aceptaríamos una contribución para implementar esto.

En cuanto a por qué aún no está allí; simplemente porque nadie ha tenido tiempo de empezar a trabajar en él, pero si alguien está interesado, lo más probable es que sea aceptado.

@zimbatm sí, su ejemplo resolvería el problema directo, solo tenga en cuenta que también crea una capa diferente y aplana todas las capas de la imagen. Aunque esto puede en algunos casos reducir el tamaño de la imagen, también da como resultado que esas capas ya no se compartan con imágenes que usan nginx como su padre, por lo que puede resultar en la necesidad de descargar más imágenes. Por ejemplo;

La imagen original de nginx:

$ docker inspect nginx -f '{{json .RootFS.Layers}}' | jq .

[
  "sha256:54522c622682789028c72c5ba0b081d42a962b406cbc1eb35f3175c646ebf4dc",
  "sha256:1c3fae42c5007fd0e70309b5b964eb5d49046562bd425424da734784098894e7",
  "sha256:87823f21b7939eac6e099fa878871a806c1904a7698793edb63bf6e5f5371e1f"
]

Y la imagen nginx que creaste;

$ docker inspect nginx2 -f '{{json .RootFS.Layers}}' | jq .
[
  "sha256:9a71ba430225d4f24e0d57837a71b6b2b68bf88ca7530c0a89c98783c98531b5"
]

Gracias por la actualización @thaJeztah

¿Puedo repetir mi sugerencia de usar

UNSET XXXX

en lugar de inventar palabras de vocabulario nuevas y extrañas (por ejemplo: UNVOLUME).

También podríamos desarmar varias propiedades en una línea de esa manera.

UNSET VOLUME EXPOSE LABEL

Personalmente, estoy de acuerdo con hacer UNSET hacer uno u otro probablemente no será un gran cambio, así que lo dejaré para el proceso de revisión cuando llegue un PR.

Hola, incluso si uso FROM por segunda vez, ¿cómo conservo todo de la imagen principal, excepto para no exponer algunos de los puertos expuestos en la imagen de la ventana acoplable principal? ¿Hay alguna resolución oficial sobre esto? Aceptemos esto y trabajemos o rechacemos

Aceptemos esto y trabajemos o rechacemos

@rajiff ver mi comentario anterior https://github.com/moby/moby/issues/3465#issuecomment -313549657 contribuciones son bienvenidas

El cambio en sí no es demasiado complicado; se puede encontrar una implementación en este RP; # 8177. No hubo consenso en ese momento, pero si sigue mi comentario de enero; # 3465 (comentario), las cosas cambiaron y (a menos que la gente cambie de opinión desde entonces), aceptaríamos una contribución para implementar esto.

Entonces, si el consenso pudo haber cambiado, ¿por qué no reabrir el # 8177 ?

Entonces, si el consenso pudo haber cambiado, ¿por qué no reabrir el # 8177?

Ese PR se abrió hace más de tres años; el código ya no se aplica

En lugar de tener que usar específicamente un comando UNsomething,
¿Por qué no mejorar el comando FROM y hacer posible enumerar lo que realmente queremos heredar?

Podríamos usar algo como:
DESDE la imagen base (VOLUMEN, EXPONER, PUERTO, ..)
o si realmente lo quieres con negación:
DESDE baseimage (*, -VOLUME, -EXPOSE)
o tener una mejor sintaxis;)

Me parece que todo esto debería ser parte del comando FROM en primer lugar.

Cambiar el volumen desde dentro del Dockerfile: si algún paso de compilación cambia los datos dentro del volumen después de que se haya declarado, esos cambios se descartarán.

Eso no parece del todo cierto. Todavía puedes hacer esto:

VOLUME /avolume/subdir
WORKDIR /avolume
COPY ./Dockerfile /avolume/subdir

Sin embargo, no sé si podría usarse para deshacer un volumen.

Anular la imagen principal / contenedor ENTRYPOINT no funciona en las últimas versiones.

17.09.1-ce versión

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

desde 17.10.0-ce versión

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[/bin/bash]

UNSET ENTRYPOINT tampoco funciona.
¿Es un error?

@ alexey-igrychev, ¿puedes abrir una edición separada para eso? El problema que está comentando es una _ solicitud de función_ para implementar instrucciones UNSET xx en el Dockerfile. (La instrucción UNSET aún no está implementada, por lo que se espera).

Como solución para ese problema, parece que funciona el uso de [""] lugar de [] para el punto de entrada;

IMAGE=$(docker commit -c "ENTRYPOINT [\"\"]" experiment)
docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

También necesito una forma de desarmar el volumen, para poder crear una imagen de base de datos precargada con tablas y datos.
Desafortunadamente, la imagen base es privada (Oracle) y, por lo tanto, ni siquiera puedo copiar el archivo docker base ya que no tengo acceso a él. Solo puedo ampliar la imagen.
Este problema tiene toneladas de +1 y casos de uso del mundo real enumerados, y se han realizado múltiples relaciones públicas para ello, y sin embargo, las relaciones públicas se han cerrado. Entonces, ¿qué debemos hacer para obtener esta función?

@veqryn desde que reabrió este problema, nadie comenzó a trabajar en una solicitud de extracción; la solicitud de extracción existente ya no se aplicaba limpiamente en la base del código, por lo que se debe abrir una nueva; si alguien está interesado en trabajar en esto, entonces las cosas pueden volver a ponerse en marcha.

Vea mis comentarios anteriores; https://github.com/moby/moby/issues/3465#issuecomment -247405438

Discutimos este tema en la reunión de mantenedores y, en general, estamos bien para comenzar a trabajar en esto nuevamente.

@duglin , ¿quizás estás interesado en trabajar en esto?

Y https://github.com/moby/moby/issues/3465#issuecomment -313549657

En cuanto a por qué aún no está allí; simplemente porque nadie ha tenido tiempo de empezar a trabajar en él, pero si alguien está interesado, lo más probable es que sea aceptado.

Mi caso de uso proviene de docker-compose.yaml: me gustaría tener un archivo de composición para desarrollo con anulaciones para producción que agregue un proxy inverso TLS, repositorio Maven, toma el PORT 80/443, no expone los puertos 80 y 5432 que el archivo de composición de desarrollo expone. O un archivo de redacción para producción con anulación de desarrollo.

La naturaleza de solo agregar archivos de composición en capas heredados de Dockerfiles complica el diseño del sistema. Sería realmente genial si algunos parámetros pudieran retirarse, o si simplemente obtuviera un contenedor diferente construido con anulaciones activas. No soy quisquilloso con cómo funciona bajo el capó wrt docker-compose.

Gracias @thaJeztah , ¿podría indicarnos la línea de código que, en su opinión, es el lugar para comenzar a leer para solucionar este problema con una solicitud de extracción?

No he trabajado mucho en el código del constructor, pero es probable que los cambios se realicen en el paquete https://github.com/moby/moby/tree/master/builder .

¡Este número tiene 3 años! ¿Es tan difícil ponerse de acuerdo en una característica tan básica o me estoy perdiendo algo?

@caruccio sí, te falta algo: desplázate hacia arriba 4 comentarios https://github.com/moby/moby/issues/3465#issuecomment -356988520

También tengo un par de casos de uso (uno es un proyecto personal y el segundo un proyecto de trabajo) donde deseo sobrecargar una declaración VOLUME , EXPOSE y ENTRYPOINT de una imagen de los padres.

Si bien tengo una solución para ENTRYPOINT simplemente estableciendo un nuevo punto de entrada vacío con ENTRYPOINT [] , y probablemente pueda aprender a vivir ignorando EXPOSE , ... me quedo rascando mi cabeza sobre cómo no heredar VOLUME definiciones.

Acabo de encontrarme con este problema en mi base de código donde la imagen principal tenía un VOLUMEN, lo que significa que todos mis cambios en este volumen en una imagen secundaria se desecharon. Pensé que me estaba volviendo loco durante 2 días hasta que finalmente encontré el camino a este problema. Por favor, ¿podría alguien implementar esto?

Hay una SOLUCIÓN ALTERNATIVA.

Siempre puede docker save image -o image.tar , descomprimir ese archivo, editar los metadatos y volver a empaquetarlo por docker load -i image2.tar . De esa manera, uno puede hacer una imagen2 que no tenga ninguna de las declaraciones de VOLUMEN anteriores.

Como tengo que seguir esos pasos con bastante regularidad, he creado un pequeño script para ayudar con la tarea de limpiar una imagen de terceros. Eche un vistazo a docker-copyedit

¡Fantástico trabajo @gdraheim ! Una solución viable en <250 líneas de python.

@gdraheim wow, ¡esto es genial! Desde el archivo README:

El deseo de ELIMINAR TODOS LOS VOLÚMENES provino del hecho de que quería descargar una imagen probada para pruebas locales donde la parte de datos también debe estar comprometida con el historial para devolver tanto el programa como los datos a un estado definido para que otro La prueba de funcionamiento comenzará exactamente en el mismo punto de control.

Este también es nuestro caso de uso.

He expandido docker-copyedit para cubrir todas las entradas de metadatos de una imagen, por lo que puede funcionar en todas las propiedades heredadas incluso más allá de los casos problemáticos de las listas EXPOSE y VOLUME. Eso sería usuario, directorio de trabajo, etiquetas, configuraciones de entorno para las cosas que se ven a menudo. Copiar ENTRYPOINT a CMD también es una modificación que hago con bastante regularidad. Ya no es necesario realizar un paso intermedio de compilación de la ventana acoplable, solo elija la ventana acoplable-copyedit . ;)

El tiempo empleado por el equipo de Docker para rastrear e ignorar repetidamente este problema probablemente hubiera sido suficiente para solucionarlo.

¿Podemos ahora reabrir esto después de que, obviamente, una tonelada de usuarios soliciten esto ...
o al menos dar un argumento razonable en su contra, no solo ignorando todos los casos de uso (también quiero no exponer un puerto y solo para obtener una salida de docker ps más limpia sin joder (80/80 / tcp) antes de construir mi propia imagen ... .. (que es más difícil para Dockerfiles que no son de código abierto)

El tema sigue abierto; Es de código abierto; las contribuciones son bienvenidas https://github.com/moby/moby/issues/3465#issuecomment -356988520

¿Estoy en lo cierto pensando que esto se arreglaría en moby / buildkit ahora? Veo la mayor parte de la infraestructura de comandos de Dockerfile allí.

También soy fan de UNSET , como

UNSET EXPOSE 9000

o

UNSET LABEL foo

Entonces, estoy viendo comandos que tienen formas de subcomando, como la forma HEALTHCHECK CMD y me doy cuenta de que HEALTHCHECK ya tiene una forma no definida ...

HEALTHCHECK NONE

Esta es una opción interesante, pero HEALTHCHECK también solo define 1 configuración (y anula con la más nueva), no permite definir múltiples, como LABEL , EXPOSE , y VOLUME hacer.

Me pregunto cómo deberían interactuar o si hay algún otro tipo de formulario NONE que podría funcionar.

Realmente se necesita alguna forma de eliminar los puertos expuestos para controlar lo que está expuesto cuando se utilizan redes de host.

+1 EXPONER []

Entonces ... durante los 5 años que el equipo de Docker no pudo implementar el operador UNSET, fantástico

Como dijo @AnthonyMastrean , ¿deberíamos mover este problema al proyecto moby/buildkit ?

También hay un PR, bien documentado y probado pero que no se fusiona, ¿deberíamos mover / reajustar este PR también?

Esta característica sería muy apreciada y abordaría un problema con las imágenes basadas en nginx en Azure.

UNSET , CLEAR , RESET , OVERRIDE , IGNORE estaría bien - evitaría UNxxx porque eso Duplicaría la lista de claves reservadas para respaldar y documentar.

También se podría especificar qué ignorar / restablecer al usar FROM , por ejemplo

FROM nginx:1.13 IGNORE EXPOSE, ENTRYPOINT

Sugiero una solución alternativa más, utilizando compilaciones de varias etapas.
Copiará todos los archivos de la imagen original a la nueva imagen, pero sin metadatos.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

No puedo creer que no hubiera pensado en eso. Eso es bastante bueno @kotofos. Pierde las capas del contenedor aguas arriba, pero eso no es una gran pérdida.

@kotofos ¿ FROM scratch as postgres ?

@farcaller buena captura. scratch definitivamente sería mejor ya que está sobrescribiendo todo el sistema de archivos

La última vez que lo probé, COPY --from=xxx ... no preservaría el sistema de archivos
propiedad, por lo que es posible que desee tener cuidado con esa solución.

@tianon Tiene razón, aunque para los contenedores de un solo proceso esto no debería ser un problema, ya que puede usar la bandera --chown para configurar el usuario que está ejecutando como en el contenedor

https://docs.docker.com/engine/reference/builder/#copy

Esto se remonta a 2014. Han pasado 5 años y parece que no habrá un "desarmado" o "restablecido" genérico para todas las propiedades en un futuro próximo. También estoy a favor de un enfoque genérico, pero hay muchas cosas a considerar y, en realidad, no sucederá pronto.

Entonces: ¿podemos al menos obtener un "UNEXPOSE" para cerrar todos esos puertos abiertos u obtener al menos el mismo comportamiento que para CMD y ENTRYPOINT (el último gana)? Es la propiedad "no configurada" más solicitada y un riesgo de seguridad potencial para los usuarios que desconocen el comportamiento (no intuitivo), considerando el comportamiento "el último gana" de otros comandos.

Sugiero una solución alternativa más, utilizando compilaciones de varias etapas.
Copiará todos los archivos de la imagen original a la nueva imagen, pero sin metadatos.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

Quería ignorar el volumen de la ventana acoplable al que apunta PGDATA para poder tener su contenido incluido con la imagen y no como un volumen.
Una solución más ligera para mí fue simplemente cambiar el valor de PGDATA :

FROM postgres:11.2-alpine
ENV PGDATA /var/lib/postgresql/test-data

# stuff that will create all my schemas
COPY create-scripts /docker-entrypoint-initdb.d/

# a weird way to trigger the entrypoint script to run the stuff in docker-entrypoint-initdb.d but not hang after starting postgres
RUN /docker-entrypoint.sh postgres --version

¿Existe algún beneficio en tener EXPOSE y VOLUME en archivos docker? Después de todo, puede definirlos fácilmente en docker run (y en docker-compose archivos), con --expose (o -p ) y volúmenes con nombre o montajes de enlace. Fui mordido por ellos más de una vez y no hay forma de restablecerlos (crear un nuevo archivo docker no es muy viable, especialmente cuando se extienden imágenes oficiales o imágenes creadas con archivos MAKE). Los veo como un anti-patrón y creo que sería mejor desaprobarlos .

@lucasbasquerotto EXPOSE es utilizado por herramientas como gitlab-runner para detectar si los puertos declarados expuestos por la imagen están realmente abiertos o no. Estoy de acuerdo en que esto debería ser más un deber de HEALTHCHECK para detectar si el contenedor está listo o no, pero tener una lista de puertos declarados puede ser útil para la automatización.
VOLUME es necesario para proporcionar la experiencia fácil de usar de detener / iniciar un contenedor y hacer que los datos se conserven automáticamente. Nuevamente, creo que esto se puede resolver de alguna otra manera, pero tener los datos inspeccionables es bueno para las herramientas (y también para los humanos en este caso).

ps no defendiendo la sintaxis de Dockerfile, solo estoy señalando que los anti-patrones no son causados ​​por las palabras clave en sí mismas, sino porque el ecosistema no está avanzando para resolver problemas que pueden surgir en casos de uso común como este, o como proporcionar una imagen con un volumen declarado y algunos datos iniciales en el volumen (por ejemplo, una imagen mysql con un esquema precargado)

@zarelit No sé exactamente cómo funciona gitlab-runner , pero creo que debería haber una manera de especificar los puertos que se verificarán fuera del Dockerfile (encontré un problema que probablemente se deba a eso, porque MySQL expone 2 puertos, pero debe verificar solo el puerto 3306: https://gitlab.com/gitlab-org/gitlab-runner/issues/4143). Por lo que veo, también solo usa el puerto expuesto del último Dockerfile.

Aproximadamente VOLUME , puede conservar los datos con estado utilizando volúmenes con nombre o montarlos con -v en un directorio existente (si desea conservar los datos al recrear un contenedor). También creo que sería mejor usar este enfoque porque el VOLUME dentro del dockerfile es un poco oscuro para quien extienda ese dockerfile, y si no sabe que está allí, podría pensar que su contenedor es reproducible en diferentes entornos y que puede cambiar de versión sin efectos secundarios, solo para ser mordido más tarde porque está usando datos persistentes bajo el capó.

Tampoco le permite mover archivos a ese directorio durante la compilación (asumiendo que no desea usarlo como un volumen, pero hereda un Dockerfile que define el directorio como un volumen, como wordpress que define /var/www/html/ como VOLUMEN, y necesitaba usar algunos trucos para usar otro directorio).

Usando -v declaras explícitamente que quieres el volumen y evitas sorpresas indeseables debido a la magia negra de VOLUME en el Dockerfile.

Además, puede terminar creando muchos volúmenes anónimos:

La definición de un volumen dentro de la imagen le dice a Docker que almacene estos datos por separado del resto del contenedor, incluso si no define el volumen cuando gira el contenedor. La forma de Docker de almacenar estos datos es crear un volumen local sin nombre. El nombre en sí es una cadena de identificación larga y única que no contiene ninguna referencia a la imagen o al contenedor al que está adjunto. Y a menos que le indique explícitamente a Docker que elimine los volúmenes cuando elimine el contenedor, estos volúmenes permanecen, es poco probable que se vuelvan a utilizar.

Fuente: https://boxboat.com/2017/01/23/volumes-and-dockerfiles-dont-mix/

@lucasbasquerotto Estoy mayormente de acuerdo con usted, hay todos los problemas de larga data, creo que una desaprobación debe seguir un camino en el que no se vuelvan inválidos, se vuelven informativos como ... caminos sugeridos que podría convertir en un volumen, puertos sugeridos que un servidor podría estar escuchando.

Creo que la buena parte del viaje de Docker ahora se ha extraído al estándar OCI y, por lo tanto, deberíamos escribir nuevas herramientas que no tengan todo este legado sobre el hombro.

Para cualquiera que lo encuentre útil, no dude en utilizar las imágenes de la https://github.com/TugboatQA/images

¿Existe algún beneficio en tener EXPOSE y VOLUME en archivos docker? Después de todo, puede definirlos fácilmente en docker run (y en docker-compose archivos), con --expose (o -p ) y volúmenes con nombre o montajes de enlace. Fui mordido por ellos más de una vez y no hay forma de restablecerlos (crear un nuevo archivo docker no es muy viable, especialmente cuando se extienden imágenes oficiales o imágenes creadas con archivos MAKE). Los veo como un anti-patrón y creo que sería mejor desaprobarlos .

Hoy en día, muchos proveedores proporcionan sus aplicaciones como una imagen de contenedor simple y proporcionan archivos docker junto con ella.
Tener EXPOSE y VOLUME en esos archivos permite el uso de aplicaciones simples con un simple docker run en el directorio de la aplicación. No necesita saber nada sobre los parámetros que espera la aplicación, funciona con todos los valores predeterminados proporcionados en el dockerfile.
Así que sí: si bien tenemos armas mejores y más grandes como compose o k8s para aplicaciones complejas para aplicaciones simples, los archivos dockerfiles siguen siendo una excelente opción. Y tener valores predeterminados que simplemente funcionan hace que el uso sea conveniente.

@ m451 Una ejecución de la

En lugar de docker run some_image , puede ejecutar fácilmente docker run --expose 3000 -v my_volume:/container/dir some_image y tener una comprensión clara de los puertos expuestos al host y los volúmenes que persistirán incluso después de que se destruya el contenedor.

Además, esto es algo trivial , y usted expone y mapea volúmenes solo cuando lo necesita (tal vez no necesite todos los puertos expuestos en el dockerfile, ni todos los volúmenes definidos. Si realmente es importante exponer algún puerto o use algún volumen, es mejor documentarlo en el repositorio para que la gente no sepa solo lo que necesita ser expuesto o mapeado, sino por qué, después de todo, esto es algo que afectará el exterior del contenedor y puede persistir después el contenedor está destruido).

Si está en el archivo docker, en realidad podría dificultar saber qué está sucediendo y causar sorpresas inesperadas a largo plazo cuando un volumen persiste y no lo sabe (especialmente si un archivo docker se hereda de otro, es posible que no lo sepa) de antemano que un volumen está definido a menos que inspeccione más profundamente lo que hace). Por lo tanto, consideraría que VOLUME y EXPOSE son malos incluso si este problema se resuelve.

Además, si bien este problema no se resuelve (y no tengo una idea de cuántos años tomará resolverlo, considerando que está abierto por más de 5 años y medio), simplemente NO TENGO FORMA de restablecerlo. ellos .

¿Existe algún beneficio en tener EXPOSE y VOLUME en archivos docker? Después de todo, puede definirlos fácilmente en docker run (y en docker-compose archivos), con --expose (o -p ) y volúmenes con nombre o montajes de enlace. Fui mordido por ellos más de una vez y no hay forma de restablecerlos (crear un nuevo archivo docker no es muy viable, especialmente cuando se extienden imágenes oficiales o imágenes creadas con archivos MAKE). Los veo como un anti-patrón y creo que sería mejor desaprobarlos .

Hoy en día, muchos proveedores proporcionan sus aplicaciones como una imagen de contenedor simple y proporcionan archivos docker junto con ella.
Tener EXPOSE y VOLUME en esos archivos permite el uso de aplicaciones simples con un simple docker run en el directorio de la aplicación. No necesita saber nada sobre los parámetros que espera la aplicación, funciona con todos los valores predeterminados proporcionados en el dockerfile.
Así que sí: si bien tenemos armas mejores y más grandes como compose o k8s para aplicaciones complejas para aplicaciones simples, los archivos dockerfiles siguen siendo una excelente opción. Y tener valores predeterminados que simplemente funcionan hace que el uso sea conveniente.

Yo diría que los proveedores que hacen eso, lo hacen por ignorancia. No comprender los problemas que esto causa a las personas que desean utilizar su producto en un entorno de producción. Seguro que facilita que alguien realice una prueba / demostración del producto. Pero ahora, si quiero ejecutarlo de verdad, tengo que clonar / sedizar su Dockerfile o crear el mío solo para obtener una imagen funcional.

@ m451 Una ejecución de la

En lugar de docker run some_image , puede ejecutar fácilmente docker run --expose 3000 -v my_volume:/container/dir some_image y tener una comprensión clara de los puertos expuestos al host y los volúmenes que persistirán incluso después de que se destruya el contenedor.

Además, esto es algo trivial , y usted expone y mapea volúmenes solo cuando lo necesita (tal vez no necesite todos los puertos expuestos en el dockerfile, ni todos los volúmenes definidos. Si realmente es importante exponer algún puerto o use algún volumen, es mejor documentarlo en el repositorio para que la gente no sepa solo lo que necesita ser expuesto o mapeado, sino por qué, después de todo, esto es algo que afectará el exterior del contenedor y puede persistir después el contenedor está destruido).

Si está en el archivo docker, en realidad podría dificultar saber qué está sucediendo y causar sorpresas inesperadas a largo plazo cuando un volumen persiste y no lo sabe (especialmente si un archivo docker se hereda de otro, es posible que no lo sepa) de antemano que un volumen está definido a menos que inspeccione más profundamente lo que hace). Por lo tanto, consideraría que VOLUME y EXPOSE son malos incluso si este problema se resuelve.

Además, si bien este problema no se resuelve (y no tengo una idea de cuántos años tomará resolverlo, considerando que está abierto por más de 5 años y medio), simplemente NO TENGO FORMA de restablecerlo. ellos .

Acordado. Así que definamos una forma estándar de comunicar qué parámetros se requieren.
Si no hay ninguno, acabaremos con el mismo lío que tuvimos en las aplicaciones heredadas: documentos y formatos de documentación específicos del proveedor. Algunos te dicen qué puertos abrir, otros no. Algunos solo te dicen la mitad, otros te dicen los puertos equivocados. Algunos solo le dicen el número de puerto pero no el protocolo, etc.

Los archivos Dockerfiles han sido una excelente manera de estandarizar ese desorden.

@ m451 Estoy de acuerdo contigo en eso, pero es bueno considerar que solo exponer un puerto no transmite información útil. ¿Qué tipo de datos / conexiones espera el puerto expuesto? Si hay varios puertos, ¿qué hace cada puerto?

Si desea conservar los datos, desea que se monten en un volumen con nombre o en alguna ubicación en el host, VOLUME no ayuda con eso. Si desea que los datos temporales se almacenen con más rendimiento, VOLUME le ayudará (este es el único caso en el que VOLUME podría ser útil). La escritura en el contenedor es más lenta porque utiliza la estrategia de copia sobre escritura . Pero nuevamente, mapear el volumen en la ejecución de la ventana acoplable también evita CoW (no necesita VOLUMEN), el único inconveniente es que su instrucción es más larga y necesita conocer la ruta (pero esto es solo si tiene un rendimiento degradado debido a CoW).

Usar VOLUME y EXPOSE como un tipo de documentación no justifica la mala (o la falta de una) documentación . Y también puede (y probablemente lo hará) dañar a algunos consumidores de la imagen.

@ m451 Estoy de acuerdo contigo en eso, pero es bueno considerar que solo exponer un puerto no transmite información útil. ¿Qué tipo de datos / conexiones espera el puerto expuesto? Si hay varios puertos, ¿qué hace cada puerto?

Correcto. La idea del agujero de los puertos de un segundo. La perspectiva está desactualizada. Sin embargo: aquí estamos tratando de definir qué puertos deben abrirse y qué puertos pueden permanecer cerrados y comprender qué datos se intercambian en cada puerto. HTTPS se ha convertido en un contenedor para casi todo hoy en día y, además del autor del código, normalmente no hay nadie que sepa exactamente qué datos se transfieren a través de un puerto en particular. E incluso entonces, puede cambiar con cada actualización.

En RL, no le importa qué datos / información se transporta a través de qué puerto, además de terminar molestando a la aplicación. Decides confiar en la aplicación. Entonces, si la aplicación abre los puertos X e Y, entonces confía en eso también.
Para las operaciones diarias estándar, es bueno simplemente iniciar una aplicación y funciona de inmediato (se asumen valores predeterminados seguros).
Los contenedores se han convertido en una forma de aplicaciones de empaquetado para que funcionen desde el primer momento.

Dicho esto, estoy de acuerdo en que los buenos doctores son importantes. Sin embargo, en RL nadie quiere leer documentos durante horas solo para saber qué puertos abrir. No aporta ningún beneficio para las tareas de operaciones diarias.

Mi pedazo del pastel.

Usar VOLUME en el Dockerfile es inútil . Si un usuario necesita persistencia, se asegurará de proporcionar un mapeo de volumen cuando ejecute el contenedor especificado. Fue muy difícil rastrear que mi problema de no poder establecer la propiedad de un directorio (/ var / lib / influxdb) se debió a la declaración VOLUME en el Dockerfile de InfluxDB. Sin un tipo de opción UNVOLUME , o sin deshacerme de él por completo , no puedo cambiar _cualquier cosa_ relacionada con la carpeta especificada. Esto es menos que ideal, especialmente cuando está consciente de la seguridad y desea especificar un determinado UID, la imagen debe ejecutarse , para evitar que un usuario aleatorio, con más permisos de los necesarios, ejecute software en su host.

Debería haber una forma de anular estas directivas VOLUME al extender imágenes para la personalización del usuario. Mi única solución en este momento es recrear completamente la imagen yo mismo, dejando inútil toda la dinámica _Dockerfile FROM_.

DESDE nginx: último
después de implementar en heroku, el puerto 80 fue expuesto por nginx, pero eso no lo permitirá heroku, entonces, ¿qué puedo hacer? copiar todo el dockerfile de nginx y eliminar EXPOSE 80?

No escribiré nada nuevo ... pero sería muy bueno anular la directiva EXPOSE.

Compartiendo esto: https://github.com/gdraheim/docker-copyedit/blob/master/docker-copyedit.py (no es mi creación, para ser claros, ¡gracias @gdraheim!)

Esto me ayudó a eliminar un volumen de un contenedor de postgres que se configuró en el dockerfile con el comando:

python docker-copyedit.py FROM postgres:11.5-alpine INTO postgres:11.5-alpine remove volume /var/lib/postgresql/data

Parece haber hecho el trabajo sin dañar el contenedor, tomó la imagen original, la adaptó, creó una nueva imagen sin el volumen (de acuerdo con la ejecución docker inspect en un contenedor creado a partir de la imagen ajustada), no lo usé para cualquier otra cosa, pero el README de git permite una variedad de operaciones, es decir

 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     REMOVE PORT 4444
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove port ldap and rm port ldaps
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove all ports
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     add port ldap and add port ldaps

LABEL es otra 'propiedad' (aún no mencionada) que podría usar la capacidad de 'desarmar'

Como se menciona en esta publicación SO: https://stackoverflow.com/questions/50978051/how-do-i-unset-a-docker-image-label

Otro caso de uso para restablecer / eliminar VOLUME de las imágenes ascendentes:

Estoy trabajando para extender una imagen de base de datos de Oracle, pero tiene un volumen en /opt/oracle/oradata . En la imagen predeterminada de Oracle, la base de datos se crea al iniciar el contenedor y escribe en ese volumen. Pero eso hace que el recipiente necesite 25 minutos para comenzar por primera vez, lo que no es aceptable. Entonces estoy trabajando en una imagen donde la base de datos se crea en la construcción de la imagen, pero por lo tanto necesito eliminar VOLUME /opt/oracle/oradata porque mi base de datos se crea pero cuando inicio el contenedor, el sistema /opt/oracle/oradata archivos

Estoy trabajando para extender una imagen de base de datos de Oracle, pero tiene un volumen en /opt/oracle/oradata .

Exactamente mi caso de uso también. Me gustaría generar una base de datos conectable preasignada que otros puedan extraer de nuestro registro de Docker privado ... pero falta el volumen. Tendré que profundizar más y decidir por la solución menos fea.

Lo he resuelto de la siguiente manera:

He usado docker-copyedit para eliminar el volumen, luego escribí un script bash para crear la base de datos (puede ver los scripts de inicio de Oracle para ver cómo se hace). Ahora, con la PDB preconfigurada, solo se necesitan 25 segundos para iniciar un contenedor desde la imagen. Pero la imagen se vuelve realmente grande.

¿Sería un mejor enfoque extender la especificación de la ventana acoplable existente para incluir un concepto de variables de env pegajosas / opción de anulación, como;

por ejemplo, mi proyecto basado en la imagen de tomcat ascendente:

--ENV CATALINA_HOME / algunos / otros / ruta
DE tomcat: 8.5.54-jdk8-openjdk
...

Cuando se declara un ENV con, debe elevarse a un estado fijo y conservar el valor declarado / anular cualquier valor encontrado para esta variable más adelante en la cadena de procesamiento del Dockerfile.

--ENV = desde este punto en adelante en el Dockerfile.

Por lo tanto, esto podría usarse al comienzo de un Dockerfile si desea que tenga prioridad sobre cualquier encuentro posterior de la misma variable, como en compilaciones de varias etapas. También permitiría flexibilidad dependiendo de dónde se colocó en el Dockerfile para que las referencias más altas en el archivo sean independientes.

No necesitaría UNVOLUME entonces, ya que el enfoque correcto sería que VOLUME se declarara con una referencia ENV que otra persona podría anular.

p.ej

ENV PROJ_VOL / algunos / ruta
VOLUME $ PROJ_VOL

Parece que ENTRYPOINT [] y ENTRYPOINT [""] invalidan el caché en cada compilación cuando no se usa BuildKit. Dockerfile simples para demostrar:

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT []

RUN echo "HERE!"

Los pasos 2 y 3 _nunca_ usarán la caché. Esta es mi solución:

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT ["/usr/bin/env"]

RUN echo "HERE!"

No puedo reproducir una falla de caché en su primer patrón:: confuso:

$ cat Dockerfile
FROM alpine:3.12
ENTRYPOINT []
RUN echo 'HERE!'

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Running in d921be2e563d
Removing intermediate container d921be2e563d
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Running in 9e2ca2cf1f9f
HERE!
Removing intermediate container 9e2ca2cf1f9f
 ---> d398fdd442b1
Successfully built d398fdd442b1

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Using cache
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Using cache
 ---> d398fdd442b1
Successfully built d398fdd442b1

Creo que debes usar una imagen que defina ENTRYPOINT . Intenta usar la imagen que hice o mysql .

Oh, interesante, puedo reproducir usando mysql:8.0 . ¡Error sólido! : +1:

¿Fue útil esta página
0 / 5 - 0 calificaciones