Artigo original: Docker Exec - How to Run a Command Inside a Docker Image or Container

Vou contar a você um segredo do DevOps aqui: o que todas as pessoas do DevOps adoram fazer é construir um sistema supersofisticado e complexo e, em seguida, encontrar uma maneira de lidar com ele como um shell normal. Outra possibilidade é a de se conectar a ele com SSH e tratá-lo como um shell normal.

Com o Docker não é diferente! Você está executando um computador dentro de outro computador. Talvez esse computador seja uma instância do EC2 ou um laptop. Você pode até fazer algo realmente louco e executar uma VM que está executando o Docker.

Na maioria das vezes, quando uso o Docker, eu o uso para empacotar e distribuir uma aplicação. Às vezes, estou usando para algo mais legal, como um projeto de computação distribuída. Muitas vezes, porém lanço um Dockerfile em um repositório do GitHub para não precisar instalar CLIs que sei que, no fim, entrarão em conflito no meu laptop.

Para encurtar a história, você pode dizer ao Docker para executar o comando bash, que o leva a um shell:

docker run -it nome-da-imagem bash
# docker run -it continuumio/miniconda3:latest bash
# docker run -it node:latest bash

Continue lendo para saber mais. 😜

Experimente

Pesquise no Google o Docker da sua linguagem de programação favorita. Para mim, é Python e, especificamente, eu gosto do conda. Em seguida, execute alguns comandos para garantir que você esteja de fato nesse shell.

# A partir do sistema hospedeiro
echo $(pwd)
# Entre no shell do docker
docker run -it continuumio/miniconda3:latest bash
# Agora você está em um shell do docker!
echo $(pwd)
echo $USER

Legal, não é? É perfeito para depurar um contêiner que deveria, com certeza, estar funcionando corretamente. Também é ótimo para o meu caso de uso mais comum: "Não quero instalar isso no meu computador".

Faça a depuração de um Docker Build com Docker Run

Tratar sua imagem do Docker como um shell normal será útil ao tentar depurar compilações do Docker.

Digamos que você tenha um Dockerfile para uma imagem que está tentando criar. Normalmente, o que acontece é que, ao executar docker build -t minha-imagem . (onde -t é para a tag), o Docker executará cada uma das etapas de RUN e parará quando chegar a um comando que não saia corretamente.

Em um shell UNIX, o código de saída 0 (zero) significa que está tudo bem com um comando. Então, para ilustrar esse ponto, fiz nosso Dockerfile ter um comando RUN que sai com 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 minha-imagem .

Isso dará uma saída que se assemelhará a isto:

(base) ➜  docker build -t minha-imagem .
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

Você pode confirmar que sua imagem do Docker não foi criada executando docker images e verificando minha-imagem. Não estará lá porque não foi construído com sucesso.

Agora, o que podemos fazer é comentar o comando RUN problemático do 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

Então, o que você verá é:

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 minha-imagem:latest

Agora, você pode entrar em sua imagem Docker e começar a executar comandos interativamente!

docker run -it minha-imagem bash
# você também pode executar
# docker run -it minha-imagem:latest bash

A partir daqui, um por um, você pode começar a depurar seus comandos RUN para ver o que deu errado. Se você não tem certeza se um comando saiu corretamente ou não, execute $?:

# Primeiro, execute docker run -it minha-imagem bash para obter o shell
# Exibe o texto hello
echo "hello"
# hello
echo $?
# 0

# Executa um comando hello não existente
$(hello)
# bash: hello: command not found
echo $?
# 127

Você pode continuar executando essas etapas, comentando seu Dockerfile, entrando em um shell e descobrindo comandos problemáticos, até que suas imagens do Docker sejam criadas perfeitamente.

Conclusão

Espero ter mostrado a você que usar uma imagem do Docker não é diferente do terminal em seu computador. O uso de imagens do Docker é uma maneira incrível de distribuir aplicações.

Tente pegar sua aplicação de CLI favorita ou o próximo projeto do GitHub e, em vez de criar um script de instalação, empacote-o com o Docker. 😀