> For the complete documentation index, see [llms.txt](https://aurimrv.gitbook.io/pratica-devops-com-docker-para-machine-learning/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://aurimrv.gitbook.io/pratica-devops-com-docker-para-machine-learning/id-1-introducao/1.6-docker-hub-e-comandos-adicionais.md).

# 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/](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](/files/ZUC669Kk2EqR3V0mPOzw)

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](https://hub.docker.com) 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:

```
$ docker build -t python:sample .
```

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á:

```
$ docker build -t aurimrv/python:sample .
Sending build context to Docker daemon  4.096kB
Step 1/6 : FROM python:3
 ---> ee2a4300ffa2
Step 2/6 : WORKDIR /usr/src/app
 ---> Using cache
 ---> c311c48f19db
Step 3/6 : COPY requirements.txt ./
 ---> Using cache
 ---> ea7e1c3c6991
Step 4/6 : RUN pip install --no-cache-dir -r requirements.txt
 ---> Using cache
 ---> ca94e718b78b
Step 5/6 : COPY . .
 ---> Using cache
 ---> 4fec572aaf81
Step 6/6 : CMD [ "python", "./script.py" ]
 ---> Using cache
 ---> 9862ce240bbe
Successfully built 9862ce240bbe
Successfully tagged aurimrv/python:sample
```

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.

```
$ docker login -u aurimrv
Password: 
WARNING! Your password will be stored unencrypted in /home/auri/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded
```

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

```
$ docker push aurimrv/python:sample
The push refers to repository [docker.io/aurimrv/python]
8f87ebb3c106: Pushed 
9efb950a790c: Pushed 
e8900ae5a74c: Pushed 
9be204ecae2e: Pushed 
50ba39281905: Mounted from library/python 
c4dbdfaeca5a: Mounted from library/python 
a221bc56b147: Mounted from library/python 
7ed1d87a050a: Mounted from library/python 
3ffc178e6d86: Mounted from library/python 
327e42081bbe: Mounted from library/python 
6e632f416458: Mounted from library/python 
e019be289189: Mounted from library/python 
c9a63110150b: Mounted from library/python 
sample: digest: sha256:49a87389f8af762b96318c71942e1ccd9bd3a59203870a93a1452d65aae66972 size: 3050
```

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](/files/3pZS3Q4f1QgmLMA80xIe)

### 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](/files/6LJc47uNDp6IvudC58Ws)

![Página da imagem oficial do Python no Docker Hub](/files/o0zJyEGGoZpYPciB4BGy)

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:

```
$ docker search python
NAME                                     DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
python                                   Python is an interpreted, interactive, objec…   7217      [OK]       
continuumio/anaconda3                    Powerful and flexible python distribution       596                  [OK]
pypy                                     PyPy is a fast, compliant alternative implem…   314       [OK]       
continuumio/anaconda                     Powerful and flexible python distribution       219                  [OK]
circleci/python                          Python is an interpreted, interactive, objec…   48                   
hylang                                   Hy is a Lisp dialect that translates express…   43        [OK]       
amazon/aws-lambda-python                 AWS Lambda base images for Python               41                   
bitnami/python                           Bitnami Python Docker Image                     17                   [OK]
google/guestbook-python-redis            A simple guestbook example written in Python…   4                    
cimg/python                                                                              3                    
appdynamics/python-agent-init            AppDynamics Repository for Python agent inst…   0                    
okteto/python-fastapi                                                                    0                    
pachyderm/python-build                                                                   0                    
ibmcom/python-sybase-ppc64le             Docker image for python-sybase-ppc64le          0                    
ibmcom/python-memcached-ppc64le          Docker image for python-memcached-ppc64le       0                    
bitnami/python-snapshot                                                                  0                    
ibmcom/python-dropbox-ppc64le            Docker image for python-dropbox-ppc64leDocke…   0                    
ibmcom/python-glanceclient-ppc64le       Docker image for python-glanceclient-ppc64le    0                    
ibmcom/python-ceilometerclient-ppc64le   Docker image for python-ceilometerclient-ppc…   0                    
ibmcom/pythonfutures-ppc64le             Docker image for pythonfutures-ppc64le          0                    
okteto/python                                                                            0                    
mirantis/python-operations-api           https://mirantis.jira.com/browse/IT-40189       0                    [OK]
pachyderm/python-evaluate                                                                0                    
okteto/python-job-launcher                                                               0                    
ibmcom/python-semver-ppc64le             Docker image for python-semver-ppc64leDocker…   0                    
```

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.

```
$ docker run --rm aurimrv/python:sample
Basic Image Operations With the Python Pillow Library
Read the full article at https://realpython.com/image-processing-with-the-
```

### 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.

```
$ docker run --rm -p 8080:8080 tomcat
Unable to find image 'tomcat:latest' locally
latest: Pulling from library/tomcat
5492f66d2700: Already exists 
540ff8c0841d: Already exists 
a0bf850a0df0: Already exists 
d751dc38ae51: Already exists 
21fd8f6c2501: Pull complete 
3585e93a38a5: Pull complete 
fca7cf2735d1: Pull complete 
4f339b93865d: Pull complete 
39442253360c: Pull complete 
89db664184b6: Pull complete 
Digest: sha256:09d1da454a73d526264e62f71c63beb62c189a3438606269a2298c0a943b2726
Status: Downloaded newer image for tomcat:latest
NOTE: Picked up JDK_JAVA_OPTIONS:  --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
26-Mar-2022 04:36:13.972 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version name:   Apache Tomcat/10.0.18
26-Mar-2022 04:36:13.974 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:          Mar 9 2022 14:30:15 UTC
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version number: 10.0.18.0
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:               Linux
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:            5.4.0-105-generic
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:          amd64
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:             /usr/local/openjdk-11
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:           11.0.14.1+1
26-Mar-2022 04:36:13.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:            Oracle Corporation
26-Mar-2022 04:36:13.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:         /usr/local/tomcat
26-Mar-2022 04:36:13.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:         /usr/local/tomcat
26-Mar-2022 04:36:13.984 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.lang=ALL-UNNAMED
26-Mar-2022 04:36:13.984 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.io=ALL-UNNAMED
26-Mar-2022 04:36:13.984 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util=ALL-UNNAMED
26-Mar-2022 04:36:13.984 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.base/java.util.concurrent=ALL-UNNAMED
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: --add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djdk.tls.ephemeralDHKeySize=2048
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.protocol.handler.pkgs=org.apache.catalina.webresources
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dorg.apache.catalina.security.SecurityListener.UMASK=0027
26-Mar-2022 04:36:13.985 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dignore.endorsed.dirs=
26-Mar-2022 04:36:13.986 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=/usr/local/tomcat
26-Mar-2022 04:36:13.986 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=/usr/local/tomcat
26-Mar-2022 04:36:13.986 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=/usr/local/tomcat/temp
26-Mar-2022 04:36:13.991 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent Loaded Apache Tomcat Native library [1.2.31] using APR version [1.7.0].
26-Mar-2022 04:36:13.991 INFO [main] org.apache.catalina.core.AprLifecycleListener.lifecycleEvent APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true], UDS [true].
26-Mar-2022 04:36:13.993 INFO [main] org.apache.catalina.core.AprLifecycleListener.initializeSSL OpenSSL successfully initialized [OpenSSL 1.1.1k  25 Mar 2021]
26-Mar-2022 04:36:14.258 INFO [main] org.apache.coyote.AbstractProtocol.init Initializing ProtocolHandler ["http-nio-8080"]
26-Mar-2022 04:36:14.278 INFO [main] org.apache.catalina.startup.Catalina.load Server initialization in [442] milliseconds
26-Mar-2022 04:36:14.318 INFO [main] org.apache.catalina.core.StandardService.startInternal Starting service [Catalina]
26-Mar-2022 04:36:14.318 INFO [main] org.apache.catalina.core.StandardEngine.startInternal Starting Servlet engine: [Apache Tomcat/10.0.18]
26-Mar-2022 04:36:14.325 INFO [main] org.apache.coyote.AbstractProtocol.start Starting ProtocolHandler ["http-nio-8080"]
26-Mar-2022 04:36:14.334 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in [55] milliseconds
```

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.

```
$ docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS         PORTS      NAMES
e579c1e6c9d0   tomcat    "catalina.sh run"   4 minutes ago   Up 4 minutes   8080/tcp   laughing_bhaskara
```

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:

```
$ docker inspect laughing_bhaskara
[
    {
        "Id": "f192b01ab34da76e8e90fd3e0149aeb7b8e2db5c169e6d58eb50059708752b02",
        "Created": "2022-03-26T04:46:38.249343033Z",
        "Path": "catalina.sh",
        "Args": [
            "run"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 886865,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2022-03-26T04:46:38.646300898Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
...
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "82f74a380a231629fdcd91ebfe854233faeabb8325074bf2fa8e677543248517",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "8080/tcp": null
            },
            "SandboxKey": "/var/run/docker/netns/82f74a380a23",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "d90e6190337b57fbbd82dbfe7aea461ad19871727b2775df3dd65dd3dfd70829",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "7c0d6ff2b1c4b28c768e3fcb9e8bff30a1fca54eedd057653392f379d764178a",
                    "EndpointID": "d90e6190337b57fbbd82dbfe7aea461ad19871727b2775df3dd65dd3dfd70829",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

```

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](/files/lnI2PeotEIjsoPgKBSYF)

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.

```
$ docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED         STATUS         PORTS      NAMES
e579c1e6c9d0   tomcat    "catalina.sh run"   4 minutes ago   Up 4 minutes   8080/tcp   laughing_bhaskara

$ docker stop e579c1e6c9d0
e579c1e6c9d0
```

### 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:

```
docker run --rm -p 8888:8080 tomcat
```

![Acesso ao servidor Tomcat via localhost por meio do mapeamento de portas](/files/bpGhEwwh2eQy16uNAfS8)

### 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](https://docs.docker.com/storage/), é 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](https://hub.docker.com/_/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:

```
 docker run --name mysql-mlops-01 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mlops mysql
```

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](https://marketplace.visualstudio.com/items?itemName=cweijan.vscode-mysql-client2). 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:

```
docker run --name mysql-mlops-01 -v datadir:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mlops mysql
```

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:

```
docker inspect datadir
```

A saída será algo como:

```
[
    {
        "CreatedAt": "2025-02-17T13:35:25Z",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/datadir/_data",
        "Name": "datadir",
        "Options": null,
        "Scope": "local"
    }
]
```

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:

```
$ docker ps -a
CONTAINER ID   IMAGE           COMMAND                CREATED         STATUS                   PORTS                                       NAMES
4615bf8ce7f7   tomcat          "catalina.sh run"      4 minutes ago   Up 4 minutes             0.0.0.0:8888->8080/tcp, :::8888->8080/tcp   cool_heisenberg
529d2796888a   python:sample   "python ./script.py"   2 hours ago     Exited (0) 2 hours ago                                               interesting_wescoff
```

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.

```
$ docker stop 4615bf8ce7f7
4615bf8ce7f7

$ docker rm 4615bf8ce7f7 529d2796888a
529d2796888a
Error: No such container: 4615bf8ce7f7
```

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.

```
$ docker image ls -a
REPOSITORY       TAG       IMAGE ID       CREATED        SIZE
<none>           <none>    4fec572aaf81   2 hours ago    929MB
aurimrv/python   sample    9862ce240bbe   2 hours ago    929MB
python           sample    9862ce240bbe   2 hours ago    929MB
<none>           <none>    ca94e718b78b   2 hours ago    929MB
<none>           <none>    c311c48f19db   2 hours ago    919MB
<none>           <none>    ea7e1c3c6991   2 hours ago    919MB
python           3         ee2a4300ffa2   30 hours ago   919MB
python           latest    ee2a4300ffa2   30 hours ago   919MB
tomcat           latest    97f970b9f6d1   5 days ago     680MB
```

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`.

```
$ docker rmi 97f970b9f6d1
Untagged: tomcat:latest
Untagged: tomcat@sha256:09d1da454a73d526264e62f71c63beb62c189a3438606269a2298c0a943b2726
Deleted: sha256:97f970b9f6d1db03eb2ebe7b9982e6466928c9d3acc36c20dc62b66b6229addc
Deleted: sha256:56a4cf9aaee1f131854ac1535eb0d5bdb0763bc7d5bdefa0e0e47791fc00ddb0
Deleted: sha256:ce5b7103f7eb8577cac47b0d345811463682c0d1fd1e6be537f09edbfb3ab95d
Deleted: sha256:cff5340daa127e18f6d1c6267d18f3dd3950a9caf2c4ade0382088b555d94213
Deleted: sha256:0c54b18d5e09cfa580026a6d2e413fd4287cee3f5f0cdf10ecffadfb11c11c42
Deleted: sha256:47ee0d7330dcc3e172fe2f8ead8e4206871099f6b70147f1a8156572e74d91c9
Deleted: sha256:3e8be97af4532cfaa3611fc23206bd4559345acd5d1b4c4ee15b0e4dd9928cde
```

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`.

```
$ docker system prune -a
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all build cache

Are you sure you want to continue? [y/N] y
Deleted Images:
untagged: aurimrv/python:sample
untagged: aurimrv/python@sha256:49a87389f8af762b96318c71942e1ccd9bd3a59203870a93a1452d65aae66972
untagged: python:sample
deleted: sha256:9862ce240bbecce01d5cb7f57a2e3307d1733397122c9905377fbe867b01a88f
deleted: sha256:4fec572aaf81180fcb0689045b281d2b570eb28e3c5064bf433441c5859235cd
deleted: sha256:a4e5524503a0dd9f7386af337b0054861dd5d4779f9ec32da75c39276eb70daf
deleted: sha256:ca94e718b78b7b0d3dc728d3ed8e31fd2ba1e90639e8185d1ab7913b5b1468af
deleted: sha256:f3a02a46be5e804985318f365035fa7edf801bec0e7edaee8f6090886e50ce0f
deleted: sha256:ea7e1c3c6991990656ef58af3807b51fab54d37d35d1ab2cc884aa57b42f8408
deleted: sha256:828d254f82a4ef46769178a9978b65e06d10694e4859a20aa0875063ce5ab4c4
deleted: sha256:c311c48f19dbf0817f480f4d208fc880b80e40a113b8f293dfcdd23eaa1d9f56
deleted: sha256:1316c4822760638f7d7b8b10a7bafcc87504eeafeb550ca63ca93ed4570f22fd
untagged: python:3
untagged: python:latest
untagged: python@sha256:6441e2f0bd2e566de0df6445cb8e7e395ea1a376dd702de908d70401d3700961
deleted: sha256:ee2a4300ffa25463a9e22ec4108dab2e2a80c1007a38c59e5a659c8157d27ca8
deleted: sha256:9b1f782d893e5e62978cd131578743d03695fcd9c671bfc53a02cec42bcd79dc
deleted: sha256:8e2f7234436e79bddbd3fe27ba4ac7ec8a28dc9ecd94736df8cc4ad707e9a6b4
deleted: sha256:e21b4a94be334967a8b4d35c725f6c84b3e841649fd2e0ebe16469493032578c
deleted: sha256:79da52d6547f4a882f3374c89f7fb1719f0a42ce7aa1ee676a1d2b74e3df7e83
deleted: sha256:49ad93c5fd7af64479d03986dffcca005e9978dbae23b0f1af00c4a038891fe6
deleted: sha256:3ba522f21511dd7dc3df1b12d4d74751d35ede46e2a978a2437f5836665746bf
deleted: sha256:a8db7d07f7124d9886940f6d6404b6f7f4ec7f094822f40456670c05796588ca
deleted: sha256:c43bfc7bb5e729f0fb22644eacf0137c53665c5b8758ed35cf90351e29102658
deleted: sha256:c9a63110150bce5ba04ee231fc765e35acb9e6a03d3ec68ae1215883278b03dd

Total reclaimed space: 929MB
```

Mais informações sobre remoção de contêineres, imagens e limpeza do sistema podem ser obtidas no artigo de [Anderson (2020)](https://www.digitalocean.com/community/tutorials/how-to-remove-docker-images-containers-and-volumes-pt).
