Cómo editar archivos en el contenedor docker detenido / no iniciado

94

Tratando de corregir errores y depurar problemas con mi aplicación que se divide en varios contenedores, con frecuencia edito archivos en contenedores:

  • o soy totalmente vago e instalo nano y edito directamente en el contenedor o

  • Docker cp el archivo fuera del contenedor, lo edito, lo copio y reinicio el contenedor

Esos son pasos intermedios antes de llegar a un nuevo contenido para la construcción de contenedores, lo que lleva mucho más tiempo que hacer lo anterior (que por supuesto es solo intermedio / jugueteo).

Ahora con frecuencia rompo el programa de inicio del contenedor, que en los casos de ruptura es un script de nodo o un script de servidor web Python, ambos generalmente fallan debido a errores de sintaxis.

¿Hay alguna forma de salvar esos contenedores? Dado que no se inician, no puedo insertar un ejecutivo en ellos y, por lo tanto, los pierdo. Luego voy por la ruta rm / rmi / build / run después de arreglar el archivo ofensivo en la entrada de compilación.

¿Cómo puedo editar archivos en un contenedor detenido, o ejecutarlos o iniciar un shell en un contenedor detenido, cualquier cosa que me permita arreglar este contenedor?

(Parece un poco como trabajar en una computadora remota y romper la configuración de la red: la conexión se pierde "para siempre" de esta manera y uno tiene que usar una alternativa, si existe).

¿Cómo editar archivos de contenedor de Docker desde el host? parece relevante pero está desactualizado.

Andreas Reiff
fuente
Esta también podría ser una solución alternativa stackoverflow.com/a/32353134/586754 , esperando una solución mejor todavía.
Andreas Reiff
1
tal vez debería considerar montar un volumen para poder editar archivos en su host en lugar de dentro del contenedor. Una vez que esté satisfecho con su código, docker cp
podrá acceder
Sí, esto sería un poco tarde si no he configurado las cosas así desde el principio. Esto no funciona para la recuperación, creo.
Andreas Reiff
Muchos lectores solo querrán ver archivos en lugar de editarlos. En estos casos, puede usar el docker commitcomando para romper una nueva imagen. name=$(docker commit); docker run -it $name /bin/shharás lo que quieras.
Att Righ
¿Entonces parece que los sistemas de archivos de los contenedores detenidos son relativamente permanentes al final?
Webwoman

Respuestas:

139

Tuve un problema con un contenedor que no se iniciaba debido a un mal cambio de configuración que hice. Pude copiar el archivo del contenedor detenido y editarlo. algo como:

docker cp docker_web_1:/etc/apache2/sites-enabled/apache2.conf .

(corrige el archivo)

docker cp apache.conf docker_web_1:/etc/apache2/sites-enabled/apache2.conf
tomurie
fuente
22
Esta debe ser la respuesta aceptada. Por alguna razón, no pensé que CP funcionara en contenedores detenidos. ¡Agradable!
Proximo
Perfecto. Copié un archivo del contenedor (conocía su ruta) y luego lo edité, y luego lo volví a copiar al contenedor en la misma ubicación. ¡Trabajó para mi! ¡Gracias!
Nawaz
¿Hay alguna forma de eliminar un archivo?
kodlan
1
@kodlan Solo si solo aparece en el archivo UpperDirque obtiene docker container inspect, tendría que experimentar para ver cómo el sistema de superposición representa los archivos en la estructura subyacente que se han eliminado en la capa superior.
Tim Baverstock
Gracias, esto me ayudó a arreglar mi contenedor MySQL que se ejecuta en Docker en macOS.
mazedlx
60

Respondiendo a mi propia pregunta ... ¡¡Todavía espero una mejor respuesta de una persona más conocedora !!

Hay 2 posibilidades.

1) Edición del sistema de archivos en el host directamente . Esto es algo peligroso y tiene la posibilidad de romper completamente el contenedor, posiblemente otros datos dependiendo de lo que salga mal.

2) Cambiar el script de inicio a algo que nunca falla, como iniciar un bash, hacer las correcciones / ediciones y luego cambiar el programa de inicio nuevamente al deseado (como el nodo o lo que fuera antes).

Más detalles:

1) Utilizando

docker ps

para encontrar los contenedores en ejecución o

docker ps -a

para encontrar todos los contenedores (incluidos los detenidos) y

docker inspect (containername)

busque el "Id", uno de los primeros valores.

Esta es la parte que contiene detalles de implementación y podría cambiar, tenga en cuenta que puede perder su contenedor de esta manera.

Ir

/var/lib/docker/aufs/diff/9bc343a9..(long container id)/

y allí encontrará todos los archivos que se cambiaron hacia la imagen en la que se basa el contenedor. Puede sobrescribir archivos, agregar o editar archivos.

Una vez más, no lo recomendaría.

2) Como se describe en https://stackoverflow.com/a/32353134/586754 , puede encontrar la configuración json config.json en una ruta como

/var/lib/docker/containers/9bc343a99..(long container id)/config.json

Allí puede cambiar los argumentos de, por ejemplo, "nodejs app.js" a "/ bin / bash". Ahora reinicie el servicio Docker e inicie el contenedor (debería ver que ahora se inicia correctamente). Deberías usar

docker start -i (containername)

para asegurarse de que no se detenga de inmediato. Ahora puede trabajar con el contenedor y / o adjuntar posteriormente con

docker exec -ti (containername) /bin/bash

Además, docker cp es bastante útil para copiar archivos que se editaron fuera del contenedor.

Además, solo se debe recurrir a esas medidas si el contenedor está más o menos "perdido" de todos modos, por lo que cualquier cambio sería una mejora.

Andreas Reiff
fuente
Todavía espero una mejor respuesta, así que siéntase libre de dar una, también moveré la etiqueta "ansered".
Andreas Reiff
Usé la segunda forma y tuve que reiniciar el servicio de la ventana acoplable para forzar la sobrescritura de los config.jsonarchivos cada vez que los editaba
Vitaly Isaev
2
Tengo config.v2.json y cada vez que inicio el contenedor zombie, revierte mi actualización de Path / EntryPoint y muere una vez más. El uso de "docker cp" para actualizar el script entrypoint.sh para ejecutar bash lo solucionó.
Curtis Yallop
@CurtisYallop Estoy experimentando lo mismo. ¿Cómo lo resolviste?
Brett McLain
1
@BrettMcLain Usé docker cp en lugar de editarlo en el host. Así: Busque la ubicación del script del punto de entrada: "ventana acoplable inspeccionar nombre_contenedor | entrada grep". Obtener el script: "docker cp container_name: /entrypoint.sh ./". (Edítelo) Vuelva a colocar el script en el contenedor: "docker cp entrypoint.sh nombre_contenedor: /entrypoint.sh". Puede hacer que el punto de entrada ejecute bash o un ciclo de suspensión, por ejemplo, "while:; do sleep 10; done". La primera línea del script debe ser "#! / Bin / bash".
Curtis Yallop
9

Puede editar el sistema de archivos del contenedor directamente, pero no sé si es una buena idea. Primero debe encontrar la ruta del directorio que se usa como raíz de tiempo de ejecución para el contenedor. Corre docker container inspect id/name. Busque la clave UpperDiren la salida JSON.

Ese es tu directorio.

Tejas Sarade
fuente
Encontré el directorio, pero no contenía todos los archivos.
aioobe
Es OverlayFS, por lo que sus archivos deben estar en uno de esos directorios.
Tejas Sarade
El nombre del directorio podría ser diferente a "UpperDir", por ejemplo, en mi caso es Source. ¡Pero funcionó!
Rajni Kewlani
0

Si está intentando reiniciar un contenedor detenido y necesita modificar el contenedor debido a una configuración incorrecta, pero el contenedor no se está iniciando, puede hacer lo siguiente, que funciona con el comando "docker cp" (similar a la sugerencia anterior). Este procedimiento le permite eliminar archivos y realizar cualquier otro cambio necesario. Con suerte, puede omitir muchos de los pasos siguientes.

  1. Use docker inspect para encontrar el punto de entrada (llamado Path en algunas versiones)
  2. Cree un clon de la ventana acoplable using
  3. Ingrese clon usando docker exec -ti bash (si es * contenedor nix)
  4. Ubique la ubicación del archivo de punto de entrada mirando el clon para encontrar
  5. Copie el antiguo script de punto de entrada usando docker cp: ./
  6. Modificar o crear un nuevo script de punto de entrada, por ejemplo

    #!/bin/bash tail -f /etc/hosts

  7. asegúrese de que el script tenga derechos de ejecución
  8. Reemplace el punto de entrada anterior usando docker cp ./:
  9. iniciar el contenedor antiguo usando inicio
  10. Repita los pasos 6-9 hasta que comience
  11. Solucionar problemas en el contenedor
  12. Restaure el punto de entrada si es necesario y vuelva a realizar los pasos 6-9 según sea necesario
  13. Eliminar clon si es necesario
usuario6830669
fuente