Back End - Docker
Published: 2022-02-14 18:43:43

**Processo de deploy** ou implantação - se uma pessoa desenvolve utilizando uma distribuição 'A' de Linux , outra utiliza Windows, outra utiliza Mac e no servidor roda uma distribuição 'B' de Linux, todas elas estão trabalhando no mesmo projeto, e da mesma forma, estão disponibilizando-o para o ambiente de produção, em um servidor remoto comum.

Por meio do **Docker** , resolvemos o problema de incompatibilidade com outros sistemas

É essencial saber Docker , tanto para se adequar ao mercado como para aproveitar seus benefícios durante o ciclo de vida de nossas aplicações.

=============================================

**Fazendo a instalação do Docker Engine**

No Linux, o Docker não possui uma interface gráfica de utilização (GUI) oficial, contudo, existem várias opções não-oficiais disponíveis, bem como uma extensão oficial da Microsoft para a plataforma no VSCode , que pode ajudar muito no gerenciamento de seus containers .
(https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)

Desinstalando versões anteriores: 

`sudo apt-get remove docker* containerd runc`

Detalhe, o Docker preserva informações sobre imagens, containers , volumes e redes na pasta /var/lib/docker/ . Nesse processo, esses arquivos não são apagados.
Caso nenhum dos pacotes esteja instalado, esse comando retornará um erro E: Impossível encontrar o <nome-do-pacote> , nesse caso, é só prosseguir com a instalação.

(https://docs.docker.com/engine/install/ubuntu/)

**Atualizando os índices dos pacotes do apt:
**
`sudo apt-get update`

ou

`sudo apt-get upgrade`

**Habilitando HTTPS para o apt:**

```
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
```

**Adicionando uma chave de acesso ao repositório remoto:**

`curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg`

Se tudo correr bem, você não deve receber nenhum retorno visual.

**Adicionando o repositório**

`echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null`

Perceba que adicionamos o repositório stable (em $(lsb_release -cs) stable ), isso significa que teremos somente o repositório com as versões estáveis do Docker .
* Em distribuições baseadas no Ubuntu (como o Linux Mint ), talvez você precise alterar o comando $(lsb_release -cs) para uma versão do ubuntu que seja compatível com aquele sistema. Exemplo: Caso você utilize o Linux Mint Tessa , você deve alterar o valor para bionic .

**Instalando Docker Engine**

`sudo apt-get install docker-ce docker-ce-cli containerd.io`

**Adicionando um usuário ao grupo de usuários docker**

⚠️ Atenção ⚠️: Esse procedimento faz com que seu usuário tenha os mesmos privilégios do usuário root (o superusuário no linux) na execução dos comandos Docker *, então use-o com moderação, apenas em ambiente de desenvolvimento.

`sudo groupadd docker`

Caso ocorra uma mensagem: groupadd: grupo 'docker' já existe , é só prosseguir.

`sudo usermod -aG docker $USER`

`newgrp docker`

**Iniciando o Daemon do Docker**

`sudo systemctl status docker`

Esse comando deve retornar algo como um pequeno relatório sobre o serviço, onde consta seu status de funcionamento:

```
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Thu 2021-09-23 11:55:11 -03; 2s ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
    Process: 2034 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=0>
   Main PID: 2034 (code=exited, status=0/SUCCESS
```

Caso o parâmetro Active esteja como stop/waiting ou no nosso caso, como inactive , rode o comando start para iniciá-lo:

`sudo systemctl start docker`

Ao consultar o status novamente, o processo deverá estar como start/ running/ active .

Habilite o daemon do Docker para iniciar durante o boot :

`sudo systemctl enable docker`

Validando a instalação

`docker run hello-world`

![retorno](https://s3.us-east-2.amazonaws.com/assets.app.betrybe.com/back-end/docker/images/introduction/docker-hello-world-2b2270efe59572e16c5029758436dede.gif)

 Quando damos o comando docker run hello-world , estamos pedindo para que ele busque em seu repositório oficial, uma imagem chamada hello-world que é um exemplo simples de um container , esse que ao final, nos retorna uma mensagem de texto

============================

**Desinstalando o Docker Engine**

`sudo apt-get purge docker-ce docker-ce-cli containerd.io`

```
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
```

=========================

**Rodando o sistema operacional Ubuntu em um container**

Os comandos do Docker funcionam no seguinte formato:

`docker <comando> <sub-comando> <parâmetros>`

O formato do comando para rodar um container é o seguinte:

`docker container run <nome-da-imagem>:<tag>`

Em que <tag> representa a versão daquela imagem, caso nenhuma seja passada, ele assumira que é a última versão disponível ( latest ).

======================

**Listando containers**

No Docker , é possível saber quais containers estão ativos com o seguinte comando:

`docker container ls`

ou

`docker container ls -a`

E caso você queira saber somente sobre o último container criado (independente do status dele), você pode usar o parâmetro -l

`docker container ls -l`

Obs: o comando run também cria um novo container para aquela imagem toda vez que é executado.

Significado de cada coluna:

**CONTAINER** ID: Identificador único*;
**IMAGE**: O nome da imagem utilizada para a criação do container ;
**COMMAND**: O comando executado/ em execução dentro do container ;
**CREATED**: Quando foi criado o container ;
**STATUS**: O status atual do mesmo, no nosso caso, encerrado;
**PORT**: A porta que estamos utilizando para nos comunicar com o container**;
**NAMES**: O apelido do container , como não definimos nenhum, foi criado um aleatório.

* Quando executamos algum comando relacionado ao container , podemos nos referenciar tanto pelo campo ID (inteiro ou parte dele), quanto pelo campo NAMES .
** Veremos isso mais adiante, mas o docker pode disponibilizar uma porta de acesso para aplicação.
Para isso, conseguimos fazer uma atribuição de uma porta do sistema hospedeiro, apontando para uma outra porta, no sistema cliente, no formato <porta-do-host>:<porta-do-cliente> .
Exemplo 8080:3000 , em que a porta 8080 do meu sistema representa a porta 3000 do container .

========================

**Rodando um comando adicional antes de terminar o container**

`docker container run <nome-da-imagem>:<tag> <comando> <argumentos-do-comando>`

Exemplo: `docker container run ubuntu echo 'Hello World!'`

================================

**Rodando o container de forma interativa**

* O comando -ti são dois comandos juntos:
-t que indica pro docker que estamos requisitando um terminal no container que consiga imprimir o retorno dos nossos comandos;
-i que estabelece uma interface de comunicação física com esse terminal, no caso, por meio do teclado.

Exemplo: `docker container run -ti ubuntu`

![docker interativo](https://s3.us-east-2.amazonaws.com/assets.app.betrybe.com/back-end/docker/images/introduction/docker-container-run-ti-ubuntu-1530d65dedaf44073151cc0c4008df45.gif)

O domínio do usuário root no terminal do container é o CONTAINER ID do mesmo, nesse caso 65897a6b07fb ( root@65897a6b07fb ) ;
O comando cat /etc/lsb-release retorna os dados da distribuição, no caso, o Ubuntu 20.04 que é a imagem utilizada;
Para sair desse terminal interno do container e retornar ao seu terminal, é só utilizar o comando exit .

====================

**Comandos:**

docker <comando> <subcomando> <parâmetros> é o formato padrão para comandos não-abreviados no CLI;
Utilize o parâmetro --help no <comando> ou <subcomando> para ter a relação completa do que pode ser executado a partir deles;
Exemplo: docker container --help , ou docker container run --help .
Os <parâmetros> são opcionais na execução dos comandos;
O conteúdo faz referência a documentação oficial dos comandos no Docker Docs .
(https://docs.docker.com/engine/reference/commandline/docker/)

**Criar e rodar um container:**

Deve criar um novo container e roda-lo logo em seguida:
`docker container run <parâmetros> <imagem>:<tag>`

O parâmetro --name define um <nome-da-sua-escolha> para aquele container (ao invés de um nome aleatório) :
`docker container run --name <nome-da-sua-escolha> <imagem>:<tag>`

Modo 'Cleanup': O parâmetro --rm deve garantir que o container seja removido ao final da execução (útil para testar imagens sem ficar acumulando containers novos) :
`docker container run --rm <imagem>:<tag>`

O parâmetro -d (de --detach , desacoplado em português) rodará esse container em segundo plano:
`docker container run -d <imagem>:<tag>`

* Trabalhar em segundo plano significa que a aplicação está rodando, porém de forma assíncrona ao comando, ou seja, embora não esteja visível, o processo está lá, funcionando por de trás dos panos. É possível validar isso com o comando `docker ps -a` .

O comando -d em outros aplicativos e serviços também pode estar associado ao conceito de daemon , que também é uma forma de se referenciar aplicativos que estão funcionando em segundo plano.
No exemplo da imagem ubuntu, faz sentido passar o parâmetro `-d` associado ao `-it` como em: 
`docker container run -dit ubuntu` , o que manterá o container ativo em segundo plano, já com um terminal disponível para acesso;

(Comando antigo) * Abreviação do comando docker container run :
`docker run <parâmetros> <imagem>:<tag>`

* Nas versões mais novas, o Docker vem adotando comandos mais verbosos, nos quais identificamos a entidade ( container , image , etc) que estamos trabalhando, antes de realizar o comando (o que o torna mais semântico).

======================================================

**Criar um container sem executá-lo**

Cria um container com a imagem de referência, mas não o executa imediatamente:
`docker container create <parâmetros> <imagem>:<tag>`

O parâmetro -it nesse contexto, deve garantir que ao iniciar o container , ele se mantenha ativo e disponha de um terminal de acesso:
`docker container create -it <imagem>:<tag>`

=======================================================

**Listar containers**

Lista ( ls , list em inglês) todos os **containers ativos**:
`docker container ls`

Lista todos os **containers ativos e inativos** :
`docker container ls -a`

Lista o último **container criado** (independente do seu estado) :
`docker container ls -l`

(Comando antigo) Abreviação do comando docker container ls (que também pode ser chamado como docker container ps ):
`docker ps <parâmetro>`

============================================

**Iniciar, reiniciar, pausar, resumir e parar um container**

Inicia* um container usando referências de sua identificação única (campo CONTAINER ID , parcialmente ou inteiro) , ou pelo nome (campo NAMES ) que foi definido:
`docker container start <CONTAINER ID || NAMES>`

Reinicia um container usando as referências citadas anteriormente:
`docker container restart <CONTAINER ID || NAMES>`

Pausa um container usando as referências citadas anteriormente:
`docker container pause <CONTAINER ID || NAMES>`

Tira um container do modo de pausa usando as referências citadas anteriormente:
`docker container unpause <CONTAINER ID || NAMES>`

Encerra um container usando as referências citadas anteriormente:
`docker container stop <CONTAINER ID || NAMES>`

(Comando antigo) São abreviações para os comandos anteriores:
`docker <start || restart || pause || unpause || stop> <CONTAINER ID || NAMES>`

![docker commands](https://s3.us-east-2.amazonaws.com/assets.app.betrybe.com/back-end/docker/images/introduction/docker-container-start-stop-tip-997e8ec0f472b99e24a1ac70fbff3dd2.gif)

====================================================

**Retomando o acesso a um container interativo rodando em segundo plano**

Caso você tenha iniciado um container em segundo plano utilizando -dit , você pode acessar esse container rodando o comando attach :
`docker container attach <CONTAINER ID || NAMES>`

Abreviação do comando docker container attach <CONTAINER ID || NAMES> :
`docker attach <CONTAINER ID || NAMES>`

**Excluindo containers específicos**

Se o container não estiver ativo, esse comando deve remover o mesmo:
`docker container rm <CONTAINER ID || NAMES>`

Se o container estiver ativo, você deve passar o parâmetro -f (forçar) para parar sua execução e depois efetuar a remoção:
`docker container rm -f <CONTAINER ID || NAMES>`

(Comando antigo) Abreviação do comando docker container rm :
`docker rm <CONTAINER ID || NAMES>`

**Limpando containers que não estão sendo utilizados**

`docker container prune`

============================================

**Monitorando os processos dentro de um container**

O comando top , assim como nos terminais linux, traz as informações sobre os processos que estão sendo rodados, mas dentro daquele container , o que não inclui, por exemplo, serviços que são compartilhados com o sistema hospedeiro. Ele é útil para quando estamos os rodando em segundo plano:
`docker container top <CONTAINER ID || NAMES>`