1.6 Docker Hub e Comandos Adicionais

Como vimos na seção anterior, o Docker é uma importante ferramenta e possui uma gama de comandos para a criação de imagens e manipulação de contêineres. Para informações detalhadas das diversas opções pode-se utilizar o comando docker --help ou até mesmo consultar a documentação on-line disponível em https://docs.docker.com/.

Nesta seção falaremos um pouco mais sobre o registry público do Docker, denominado Docker Hub. Sugerimos fortemente que você crie uma conta no Docker Hub e gere um Token de Acesso que irá permitir a você armazenar imagens no Docker Hub, conforme veremos a seguir. Uma vez logado em sua conta, a criação do token de acesso pode ser feita no menu "Account Settings/Security", conforme ilustrado na tela a seguir.

Opção para geração do token de acesso ao Docker Hub

Ao gerar o Token de Acesso, copie e cole o número gerado pois ele será necessário em cada nova conexão ao Docker Hub realizada via linha de comando quando se desejar armazenar uma imagem no registry público do Docker.

Registrando nova imagem no Docker Hub

Por exemplo, na Seção 1.5, construímos uma imagem, denominada python:sample que ficou armazenada no registry local. Para isso, utilizamos o comando abaixo:

Se desejarmos que essa imagem possa ser compartilhada via Hub Docker, inicialmente, precisamos mudar o seu nome de modo a incluir, prescendendo o mesmo, o DOCKER_ID do usuário do Hub Docker. No exemplo aqui apresentado, esse DOCKER_ID é aurimrv. como pode ser observado na figura acima. Desse modo, o comando de construção a ser utilizado será:

Observa-se no final da execução (linha 21) que a imagem passou a ser rotulada como aurimrv/python:sample.

Ao final desse processo temos uma imagem denominada aurimrv/python:sample, criada e armazenada localmente. Agora vamos enviá-la para o Docker Hub. Para isso você precisa saber o seu DOCKER_ID e o seu DOCKER_TOKEN. Ambos serão utilizados no processo. Ao ser solicitada a Password, simplesmente copie e cole o seu token de acesso de desenvolvedor gerado na plataforma Docker Hub.

Em seguida, o comando docker push permite submeter uma nova imagem para o registry do Docker Hub, conforme ilustrado abaixo:

Ao consultar a respectiva conta no Docker Hub, observa-se que essa imagem aparece disponível para ser utilizada por qualquer outro usuário. A figura a seguir ilustra a presença dessa imagem.

Imagem local registrada no Docker Hub

Consultando por imagens existentes

Como apresentado acima, o Docker Hub é um grande repositório de imagens que estão disponíveis para serem utilizadas para uso direto ou como base para o desenvolvimento de novas imagens como fizemos no exemplo apresento. Pelo campo de busca do Docker Hub você pode pesquisar por imagens de interesse. A tela a seguir, por exemplo, ilustra a pesquisa feita por Python.

Como pode ser observao, existe uma grande variedade de imagens contento Python no nome em alguma parte da descrição de uma imagem, basta localizar a desejada e utilizar. No nosso exemplo, utilizamos a imagem oficial do Python com a Tag 3.8.

Uso do Docker Hub na busca por imagens de Python
Página da imagem oficial do Python no Docker Hub

Existe também a opção de procurar por imagens utilizando-se o comando docker search via linha de comando. Por exemplo a busca realizada acima no Docker Hub via linha de comando ficaria conforme abaixo:

Entretanto, certamente a documentação encontrada no Docker Hub referente as imagens é mais detalhada e merece ser lida para viabilizar a correta utilização das mesmas.

Executando a imagem registrada

Para executar a imagem registrada utiliza-se o comando docker run mas, agora, passando o nome da imagem registrada remotamente.

Parando a execução de um contêiner

Suponha que tenha se iniciado a execução de um contêiner contendo uma instância do Apache Tomcat. Por exemplo, o comando abaixo colocaria tal contêiner em execução.

No caso específico desse contêiner, como o Tomcat permanece em execução, o prompt não é liberado. É possível, inclusive, conectar nessa instância do Tomcat e verificar que o mesmo está em execução no endereço. Entretanto, da forma como o comando docker run foi executado acima, para se conectar à instância do Tomcat em execução no contêiner é necessário se saber o endereço IP que o contêiner está utilizando. Para isso pode-se utilizar o comando docker ps para se obter o ID ou nome do contêiner e, em seguida, o docker inspect para obter informações sobre o status da execução do contêiner, incluíndo o endereço IP utilizado.

Por exemplo, o comando acima identificou que o ID do contêiner é e579c1e6c9d0 e seu nome é laughing_bhaskara. Utilizando qualquer desses identificadores podemos inspecionar o contêiner com o comando abaixo:

Observa-se pelo comando acima que o endereço IP utilizado pelo contêiner é o 172.17.0.2. Desse modo, é possível se conectar a essa instância do Tomcat utilizando-se o endereço http://localhost:8080 que irá produzir como saída um erro 404 uma vez que no contêiner não há qualquer aplicação instalada.

Conexão na instância do Tomcat em execução no contêiner

Para parar o contêiner é necessário abrir um outro prompt de comando e executar os comandos docker ps para se decobrir o ID ou nome do contêiner e, em seguida, o comando docker stop com a identificação do contêiner que se deseja interromper a execução.

Redirecionamento de portas

No caso do Tomcat e outros serviços que fazem uso de portas, o docker run oferece um parâmetro que permite realizar o mapeamento de portas utilizadas no contêiner para portas na máquina hospedeira, executando os contêineres. Por exemplo, considerando o exemplo do Tomcat acima, se o executássemos conforme abaixo, a porta 8080 utilizada pelo contêiner no endereço 172.17.0.2 seria mapeada para a porta 8888 na máquina local, ou seja, em http://localhost:8888, como pode ser observado na figura abaixo:

Acesso ao servidor Tomcat via localhost por meio do mapeamento de portas

Compartilhamento de volumes

Outra característica interessante dos contêineres é que eles executam em um espaço de dados separado da máquina local no qual executa. Desse modo, caso existam dados que sejam produzidos pelo contêiner que precisam ser repassados para a máquina local ou vice versa, a solução para isso, recomendada pelo Docker, é por meio de volumes. O exemplo a seguir ilustra esse cenário. Para isso, será utilizada uma imagem do servidor de banco de dados MySQL.

O Docker Hub oferece uma documentação detalhada de como fazer uso da imagem para a criação de contêineres executando o MySQL. O problema que desejamos demonstrar é que, ao utilizar um banco de dados para o armazenamento de dados de uma aplicação, quando o contêiner encerra sua execução ou é destruído, os dados armazenados internamente no banco de dados se perdem, caso não sejam compartilhados com a máquina local. Uma das formas de fazer isso é pode meio de volumes que basicamente mapeiam um diretório ou arquivo na máquina local com um diretório ou arquivo dentro do contêiner.

Para demonstrar o problema, execute o seguinte comando:

Observamos que na instrução do docker run temos alguns parâmetros novos. O primeiro é o parâmetro --name que permite atribuirmos um nome para nosso contêiner que entrará em execução. No caso, atribuímos a ele o nome mysql-mlops-01 e podemos utilizar esse nome para referência-lo nos demais comandos que faremos uso.

Finalmente, o parâmetro -e permite definir uma variável de ambiente que é utilizada pelo contêiner. Uma das variáveis que o contêiner do MySQL permite ser especificada é a MYSQL_ROOT_PASSWORD que indica a senha de administrador (root) no banco de dados. Em nosso caso, definimos essa senha como mlops. Essa senha será utilizada para que possamos conectar ao banco de dados e executar instruções em SQL.

Utilize alguma ferramenta de comunicação com o MySQL, como por exemplo essa extensão para o VSCode. Crie um banco de dados, uma tabela, alguns dados, e encerre o contêiner. Depois execute-o novamente, e veja como os dados permanecem salvos.

Agora, se o contêiner for destruído (experimente removê-lo e iniciá-lo novamente) os dados são perdidos.

Porém, se o contêiner for executado com um volume associado, os dados do volume não ficam dentro do contêiner, e sim na máquina host. Assim:

O novo parâmetro é o -v que permite o compartilhamento de um diretório local com um diretório dentro do contêiner. No caso, o diretório local é representado por datadir , que é um volume armazenado na máquina host, e que ficará associado ao diretório var/lib/mysql dentro do contêiner. Sempre que o contâiner criar novos dados nessa pasta, na realidade eles estarão sendo salvos no diretório local. Assim, se o mesmo for destruído, os dados permanecerão intactos.

Experimente rodar os mesmos testes novamente, criando um banco de dados/tabela, depois destrua o contêiner e rode um novo. Veja como os dados foram preservados.

O volume no diretório local pode ser inspecionado pelo comando:

A saída será algo como:

O item "Mountpoint" indica a localização da pasta na máquina host. Se estiver usando Windows, essa pasta corresponde ao local na máquina virtual utilizada pelo Docker para subir os contêiners, o que e normalmente não é facilmente acessível.

Removendo contêineres, imagens ou limpando todo ambiente

À medida que imagens e contêineres são criados, executados e encerrados pode ser que parte dos arquivos utilizados pelos mesmos permaneçam na máquina local e demandem uma limpeza periódica. Para consultar a lista de contêineres disponíveis em execução e/ou encerrados é possível utilizar o comando docker ps -a, conforme ilustrado abaixo:

No exemplo acima observa-se que existem dois contêineres, um em execução e outro cuja execução já se encerrou a duas horas atrás.

Para remover contêineres utiliza-se o comando docker rm fornecendo como parâmetro a identificação do contêiner que se deseja remover. Entretanto, só podem ser removidos contêineres que não estejam em execução. Do contrário, primeiro o mesmo deve ser parado antes de ser removido.

Os comandos a seguir removem todos os contêineres localizados.

Observa-se que, ao tentar executar o docker rm no ID do contêiner do Tomcat foi exibida uma mensagem de erro indicando que o contêiner com ID 4615bf8ce7f7 não existe. Isso porque ao iniciarmos a execução do contêiner utilizamos o parâmetro --rm que remove automaticamente o contêiner assim que o mesmo encerra sua execução, o que foi feito com o comando docker stop.

Já as imagens podem ser consultadas e removidas de maneira similar. Para consultar a lista de imagens utilizamos o comando docker imagens docker image ls -a. Esse comando apresenta a lista de imagens que foram baixadas, incluíndo as camadas de imagem intermediárias.

Para remover uma imagem utiliza-se o comando docker rmi seguido do ID das imagens desejadas.Por exemplo, o comando abaixo remove a imagem do Tomcat com ID 97f970b9f6d1.

Uma opção mais drástica e que permite uma limpeza de todo o sistema seria a execução do comando docker system prune -a.

Mais informações sobre remoção de contêineres, imagens e limpeza do sistema podem ser obtidas no artigo de Anderson (2020).

Last updated