Usando as Instruções ENTRYPOINT e CMD do Dockerfile

Se você já precisou executar um ou dois comandos em seu contêiner Docker na inicialização, este tutorial é para você. Usando as instruções ENTRYPOINT e CMD do Dockerfile, você pode executar quantos comandos de inicialização desejar.

Neste tutorial, você aprenderá como usar as instruções ENTRYPOINT e CMD para executar comandos de inicialização em um Dockerfile e entender as diferenças entre eles.

Pré-requisitos

Como este tutorial será uma demonstração prática, certifique-se de ter o seguinte em mãos:

  • A Windows 10 PC – Windows 10 v10.0.19042 was used in this tutorial.
  • Docker Desktop – Este tutorial usa o Docker Desktop v3.3.1.

Criando um Dockerfile

Antes de poder executar comandos de inicialização de contêiner Docker, você deve primeiro criar um Dockerfile. Um Dockerfile é um documento de texto que contém uma lista de comandos para construir contêineres, imagens Docker e determina como uma imagem Docker é criada.

1. Primeiro, abra o PowerShell como administrador.

2. Crie uma nova pasta para armazenar o Dockerfile e todos os arquivos associados que este tutorial usará e mude para esse diretório. Este tutorial está usando ~/docker.

mkdir ~/docker
cd docker

3. Agora, crie um arquivo de texto em branco chamado Dockerfile com o seguinte comando.

cd > Dockerfile

Alternativamente, você pode criar um Dockerfile com o seguinte comando se estiver no Linux ou no Mac OS.

touch Dockerfile

4. Por fim, adicione o seguinte conteúdo ao Dockerfile

FROM ubuntu:20.04

Agora você criou um Dockerfile em breve!

Construindo uma Imagem Docker

Agora que você criou seu Dockerfile, você deve construir uma imagem Docker para executar os comandos escritos nas instruções ENTRYPOINT e CMD do seu Dockerfile. Uma maneira de construir uma imagem é usando o build comando.

Enquanto estiver no diretório ~/docker, execute o seguinte comando. O comando abaixo cria uma imagem Docker chamada demo (-t demo) a partir do Dockerfile em ~/docker especificando o diretório de trabalho atual (.).

docker build -t demo .
Building a Docker Image

Executando um Contêiner Docker

Depois de construir a imagem Docker, você precisará de um contêiner para executar a imagem Docker que executará os comandos das instruções ENTRYPOINT e CMD do Dockerfile.

Para executar um contêiner Docker, invoque o comando run para criar uma camada de contêiner gravável sobre a imagem Docker (demo). O exemplo abaixo está utilizando o parâmetro -it para conectar interativamente ao contêiner para que você possa ver a saída de exemplo.

docker run -it demo
Running a Docker Container

Exec vs. Formato Shell

Ao começar a trabalhar com um Dockerfile e descobrir como executar comandos de inicialização, você pode se deparar com dois métodos diferentes de definir esses comandos. Cada método irá invocar comandos, mas o faz de maneira um pouco diferente.

Quando o Docker executa comandos, ele pode fazê-lo diretamente chamando exec ou passando pelo shell do contêiner (/bin/sh -c no Linux ou cmd /S /C no Windows) chamado shell.

Você notará que os comandos executados via exec têm uma instrução seguida pelos executáveis a serem invocados seguidos por um ou mais argumentos de linha de comando, como mostrado abaixo.

ENTRYPOINT ["executables", "parameter1", "parameter2", ...]
CMD ["executables", "parameter1", "parameter2:, ...]

Escrever comandos no formato shell, por outro lado, não requer o envolvimento dos comandos em colchetes, como mostrado abaixo.

ENTRYPOINT <command> "parameter1"
CMD <command> "parameter1"

Se você não especificar um argumento para CMD, o Docker sempre executará o comando no formato exec, por exemplo, CMD <comando>.

Se você está apenas começando, diferenciar entre essas duas invocações de comando não importará muito, mas à medida que você avança, logo verá os benefícios e as desvantagens de cada uma.

Executando Comandos de Inicialização

Vamos agora entrar no cerne deste tutorial e sujar as mãos ao percorrer alguns exemplos de execução de comandos de inicialização dentro de um arquivo Docker ENTRYPOINT e instruções CMD.

1. Abra o arquivo Dockerfile que você criou anteriormente no seu editor de texto preferido.

2. Copie e cole o conteúdo do Dockerfile de exemplo no seu Dockerfile, conforme mostrado abaixo, e salve-o.

Este Dockerfile cria uma camada usando a imagem base ubuntu:20.04. Em seguida, diz ao Docker para invocar o comando echo passando o argumento Hello world para tanto as instruções Dockerfile CMD quanto ENTRYPOINT usando o formulário exec e shell.

FROM ubuntu:20.04
# Instrução CMD
CMD ["echo", "Hello world"] # Exec Form
CMD echo "Hello world"      # Shell Form
# Instrução ENTRYPOINT
ENTRYPOINT ["echo", "Hello world"] # Exec Form
ENTRYPOINT echo "Hello world"      # Shell Form

3. Enquanto estiver no diretório ~/docker, construa a nova imagem executando docker build e chame-a de demo. O comando abaixo tag a imagem como demo e procura um Dockerfile no diretório de trabalho atual (.).

docker build -t demo .
Building a Docker image with docker build

4. Agora, execute um contêiner usando a imagem e, em seguida, execute um contêiner Docker com base na imagem Docker criada anteriormente. Você verá agora que o contêiner retorna Hello world, que veio da instrução CMD fornecida no Dockerfile.

docker run -it demo
Running a Docker container with docker run

Uso de Variáveis em um Dockerfile

Às vezes, você pode não saber antecipadamente os argumentos de linha de comando exatos a serem passados para um comando. Os argumentos que você precisa passar para um comando são expostos apenas em tempo de execução. Em vez de atribuir estaticamente os argumentos do comando, você pode capturá-los e passá-los para comandos com variáveis.

Você só pode usar variáveis do Dockerfile no formulário shell. O Docker não suporta variáveis no comando invocado via exec.

Abra o Dockerfile no seu editor de texto preferido novamente, substitua tudo por esta série de comandos e salve.

Você notará que desta vez o Dockerfile usa variáveis de ambiente e são mostradas usando ENV. No exemplo abaixo, o Dockerfile está definindo uma variável de ambiente chamada name com um valor de friend. Uma vez criada, esta variável de ambiente é referenciada via $name.

Ao executar um contêiner baseado neste Dockerfile, o Docker invocará o comando echo e passará o argumento Bem-vindo, friend.

FROM ubuntu:20.04
ENV name friend

CMD echo "Welcome, $name"
# ou
## ENTRYPOINT echo "Bem-vindo, $name"

Agora, crie a imagem Docker e execute o contêiner novamente, fornecendo opcionalmente um nome de tag shellform. Você notará que o Docker invocou o comando echo e retornou a saída esperada.

Building a Docker Image (shellform) and Running a Docker Container

Combinação das instruções ENTRYPOINT e CMD do Dockerfile

Muito do tempo, você estará invocando comandos de inicialização seja no CMD ou na instrução ENTRYPOINT. Afinal, você pode invocar quantos comandos desejar usando cada método. Mas, também pode invocar um único comando e “adicionar a ele” usando ambas as instruções.

Expandindo os exemplos anteriores, talvez você tenha um Dockerfile que se pareça com o exemplo abaixo. Como está, se você criar uma imagem e executar um contêiner a partir dessa imagem, o Docker invocaria o comando echo e retornaria Hello.

FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]

Talvez você tenha outro argumento que gostaria de passar para o comando echo, mas não imediatamente. Talvez você queira fazer isso mais adiante no Dockerfile. Chamando a instrução CMD sem um comando, você pode fazer isso.

Ao especificar um comando a ser executado via instrução ENTRYPOINT seguido pela instrução CMD, o Docker assume automaticamente que o valor passado para CMD é um argumento; não um comando.

Agora, adicione uma referência à instrução CMD sem um comando, apenas um argumento chamado world, como mostrado abaixo.

FROM ubuntu:20.04
ENTRYPOINT ["echo", "Hello"]
CMD ["world"]

Adicionar instruções sempre deve ser escrito em forma de execução devido ao seu comportamento “semelhante a um array” de especificar valores individualmente separados por vírgulas versus tudo em uma única string.

Após construir a imagem e executar o contêiner a partir da imagem, você verá que, em vez de duas linhas de saída (Hello e world), o Docker retorna apenas uma, o que significa apenas uma única invocação do comando echo.

Building a Docker Image (demo3) and Running a Docker Container

Conclusão

Deves agora ter uma boa compreensão de como executar comandos de inicialização de contentores Docker através das instruções CMD e ENTRYPOINT no ficheiro Dockerfile. Cada instrução é um pouco diferente, mas alcança a mesma tarefa e até pode ser utilizada em conjunto.

Podes imaginar um cenário em que preferirias utilizar CMD em vez de ENTRYPOINT para executar um comando de inicialização?

Source:
https://adamtheautomator.com/dockerfile-entrypoint/