Docker Exec: cómo ejecutar un comando dentro de una imagen o contenedor de Docker

Voy a contarles un secreto de DevOps aquí: lo que a toda la gente de DevOpsy le encanta hacer es construir un sistema súper elegante y complejo, y luego encontrar una manera de lidiar con él como un shell normal. O conéctese a él con SSH y luego trátelo como un shell normal.

¡Docker no es diferente! Está ejecutando una computadora dentro de otra computadora. Quizás esa computadora sea una instancia EC2 o una computadora portátil. Incluso puede volverse realmente loco y ejecutar una máquina virtual que luego ejecute Docker.

La mayoría de las veces, cuando uso Docker, lo uso para empaquetar y distribuir una aplicación. A veces lo uso para algo más genial como un proyecto de computación distribuida. Pero muchas veces lanzo un Dockerfile en un repositorio de GitHub para no tener que instalar CLI que sé que eventualmente entrarán en conflicto en mi computadora portátil.

En pocas palabras, puede decirle a Docker que ejecute el comando bash, que lo coloca en un shell:

docker run -it name-of-image bash # docker run -it continuumio/miniconda3:latest bash # docker run -it node:latest bash

Pero sigue leyendo para más. ;-)

Pruébalo

Busca en Google el Docker de tu lenguaje de programación favorito. Para mí esto es Python, y específicamente me gusta conda. Luego ejecute algunos comandos para asegurarse de que de hecho se encuentra en ese shell.

# From Host echo $(pwd) # Drop into docker shell docker run -it continuumio/miniconda3:latest bash # Now you are in the docker shell! echo $(pwd) echo $USER

Genial, ¿eh? Esto es perfecto para depurar un contenedor que debería estar funcionando correctamente. También es ideal para mi caso de uso más común de "No quiero instalar esto en mi computadora".

Depurar una compilación de Docker con Docker Run

Tratar su imagen de Docker como un shell normal será útil cuando intente depurar compilaciones de Docker.

Supongamos que tiene un Dockerfile para una imagen que está intentando crear. Normalmente, lo que sucede es que cuando se ejecuta docker build -t my-image .(-t es para etiqueta), Docker ejecutará cada uno de los pasos de RUN y se detendrá cuando llegue a un comando que no se cierre correctamente.

En un shell de UNIX, el código de salida 0 significa que todo está bien con un comando. Entonces, para ilustrar este punto, hice que nuestro Dockerfile tenga un comando RUN que sale con 1.

FROM continuumio/miniconda3:latest RUN apt-get update -y; \ apt-get upgrade -y; \ apt-get install -y \ vim-tiny vim-athena build-essential RUN conda update conda \ && conda clean --all --yes RUN exit 1
docker build -t my-image .

Esto le dará una salida que se parece a:

(base) ➜ my-image docker build -t my-image . Sending build context to Docker daemon 2.048kB Step 1/4 : FROM continuumio/miniconda3:latest ---> 406f2b43ea59 Step 2/4 : RUN apt-get update -y; apt-get upgrade -y; apt-get install -y vim-tiny vim-athena build-essential ---> Using cache ---> 726af29a48a0 Step 3/4 : RUN conda update conda && conda clean --all --yes ---> Using cache ---> 19478bb3ce67 Step 4/4 : RUN exit 1 ---> Running in 7c98aab6b52c The command '/bin/sh -c exit 1' returned a non-zero code: 1

Puede confirmar que su imagen de Docker no se creó ejecutando docker imagesy comprobando my-image. No estará allí porque no se construyó con éxito.

Ahora lo que podemos hacer es comentar ese problemático comando RUN de Dockerfile.

FROM continuumio/miniconda3:latest RUN apt-get update -y; \ apt-get upgrade -y; \ apt-get install -y \ vim-tiny vim-athena build-essential RUN conda update conda \ && conda clean --all --yes #RUN exit 1

Entonces lo que verá es:

Sending build context to Docker daemon 2.048kB Step 1/3 : FROM continuumio/miniconda3:latest ---> 406f2b43ea59 Step 2/3 : RUN apt-get update -y; apt-get upgrade -y; apt-get install -y vim-tiny vim-athena build-essential ---> Using cache ---> 726af29a48a0 Step 3/3 : RUN conda update conda && conda clean --all --yes ---> Using cache ---> 19478bb3ce67 Successfully built 19478bb3ce67 Successfully tagged my-image:latest 

¡Ahora puede acceder a su imagen de Docker y comenzar a ejecutar comandos de forma interactiva!

docker run -it my-image bash # you can also run # docker run -it my-image:latest bash

Desde aquí, uno por uno, puede comenzar a depurar sus comandos RUN para ver qué salió mal. Si no está seguro de si un comando salió correctamente o no, ejecute $?:

# First run docker run -it my-image bash to get to the shell # Print the string hello echo "hello" # hello echo $? # 0 # Run a non existant command hello $(hello) # bash: hello: command not found echo $? # 127

Puede seguir ejecutando estos pasos, comentando su Dockerfile, colocándolo en un shell y descubriendo comandos problemáticos, hasta que sus imágenes de Docker se compilen perfectamente.

Envolver

Espero haberle mostrado que usar una imagen de Docker no es diferente del terminal de su computadora. El uso de imágenes de Docker es una forma increíble de distribuir aplicaciones.

Intente tomar su aplicación CLI favorita o el próximo proyecto de GitHub, y en lugar de crear un script de instalación, empaquételo con Docker. ;-)