Trabalhando com Docker
Gerenciar contêineres Docker envolve uma variedade de tarefas para garantir que eles funcionem corretamente, sejam seguros e eficientes. Para isso é preciso conhecer a ferramenta, como trabalhar com imagens, volumes, redes, e muito mais, para no fim termos containers funcionais.
Docker CLI
O comando docker
é a principal interface de linha de comando (CLI) para interagir com o Docker. Ele permite que os usuários executem uma ampla variedade de operações relacionadas a contêineres, imagens, redes e volumes.
A tabela abaixo representa alguns outros comandos que estão mais relacionados com o
Comando | Descrição |
---|---|
docker ps | Lista todos os contêineres em execução no host. |
docker version | Mostra a versão do Docker. |
docker info | Mostra a versão do Docker, mas resumida. Além de mostrar informações do servidor. |
docker images | Lista todas as imagens disponíveis no host. Similar ao comando docker image ls . |
docker exec CONTAINER | Executa um comando dentro de um contêiner em execução. Exemplo: docker exec -it my_container bash . |
docker inspect OBJECT | O comando docker inspect é usado para obter informações detalhadas sobre um ou mais objetos Docker, como contêineres, imagens, volumes, redes e plugins. |
docker logs CONTAINER | Mostra os logs relacionados ao container. |
docker stats CONTAINER | Mostra estatísticas do container. |
docker run CONTAINER | É usado para criar e executar contêineres Docker a partir de imagens Docker. |
docker events | Este comando exibe eventos em tempo real a partir do servidor Docker. Os eventos podem incluir informações sobre contêineres criados, parados, iniciados, etc. |
docker stop CONTAINER | Este comando para a execução de um ou mais contêineres em execução. |
docker start CONTAINER | Este comando inicia um ou mais contêineres parados. |
docker pause CONTAINER | Este comando pausa a execução de um ou mais contêineres em execução, mantendo-os no estado atual, mas suspendendo a execução de processos dentro deles. |
docker cp | Este comando copia arquivos ou diretórios entre o sistema de arquivos do host e o sistema de arquivos de um contêiner Docker. Exemplo, copiando para o container: docker cp arquivo.txt CONTAINER:/path/ . Ou copiando do container para o host: docker cp CONTAINER:/path/ host/path . |
docker save | Este comando salva uma ou mais imagens Docker em um arquivo tar. Isso permite que você armazene as imagens localmente ou as transfira para outro sistema. Exemplo: docker save -o minha_imagem.tar minha_imagem:tag . |
docker load | Este comando carrega uma imagem Docker que foi salva em um arquivo tar. Exemplo: docker load -i minha_imagem.tar minha_imagem:tag . |
docker export | Exporta o Filesystem de um container para um arquivo tar. |
docker import | Este comando importa conteúdo de arquivo tar para criar uma nova imagem Docker. Isso pode ser útil para criar imagens a partir de arquivos tar existentes. Exemplo: docker import meu_arquivo.tar minha_imagem:tag . |
docker port CONTAINER | Mostra as portas que o container fez o bind com o host Docker. |
docker build | Cria uma imagem docker usando as instruções do Dockerfile. |
docker commit | Cria uma imagem docker usando um container que esteja rodando. |
docker system events | É usado para monitorar eventos em tempo real relacionados ao Docker no sistema. |
docker context * | É usado para gerenciar diferentes configurações de ambiente de forma eficiente. |
Vejamos alguns comandos com o docker:
# Subindo um container com a última imagem do ubuntu em modo interativo:
docker run -it ubuntu:latest
# Executar um comando (comando 'id') num container e apagar ele logo em seguida:
docker run --rm nginx:latest id
O -it
no comando docker run
é usado para habilitar a interatividade com o container. Ele é essencial quando você quer interagir diretamente com o terminal do container, como se estivesse trabalhando em uma máquina virtual ou servidor. O -i
(interactive), significa modo interativo, usamos ele para manter o stdin (entrada padrão) aberto para que possamos enviar comandos ao container. Sem o -i
, o Docker pode encerrar a conexão com o terminal assim que o container é iniciado.
Já o -t
(tty) é usado para alocar um pseudo-terminal (TTY) para o container. Ele simula o comportamento de um terminal real, necessário para muitas aplicações que esperam interagir diretamente com um terminal, como shells (bash
, sh
, etc.). Sem o -t
, o terminal do container não terá recursos interativos, como a exibição correta de prompts e formatação.
Para fazer backup de um container, nós podemos usar o comando docker export CONTAINER
. Lembrando que se o container for parado (stop
), todos os dados no filesystem serão perdidos, a menos aqueles que estejam num mount bind ou volume.
# Exportando filesystem do Container:
docker export CONTAINER -o container.tar
# Exportando filesystem do Container e comprimindo:
docker export CONTAINER | gzip > container.tar.gz
Para importar os dados desse container exportado, podemos usar o comando docker import
. Se atente ao fato de que, ao usar docker import
não é criado um novo container contendo aqueles dados, esse comando cria uma nova imagem e esse imagem possui os dados do filesystem do container exportado.
Apesar de criar uma nova imagem, essa nova imagem não vem com o CMD/Entrypoint padrão, ao tentar simplesmente executar esse container, dará erro. No entanto, é possível executar ele fornecendo o CMD.
# Importando o filesystem que fizemos backup e criando uma nova imagem para quando temos somente o '.tar':
docker import apiweb.tar container3
# Importando o filesystem que fizemos backup e criando uma nova imagem para quando temos a compactação também:
zcat container.tar.gz | docker import - container2
# Listando as imagens:
docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
container3 latest 494e4ccff1a5 About a minute ago 169MB
container2 latest 49d323bcb9d4 2 minutes ago 169MB
teste-apiweb latest 89edc50deb77 20 hours ago 169MB
# Executando o container:
docker container run -it --name contbackup container3 /bin/bash
Para dar um CMD nessa imagem (dar uma razão dela existir) sem ter que fazer isso explicitamente, poderíamos criar uma nova imagem a partir dessa já existente, por meio do dockerfile.
Docker API
A API do Docker é uma interface de programação que permite a interação direta com o daemon Docker. Ela possibilita a execução de comandos e o gerenciamento automatizado de recursos do Docker, sendo uma solução poderosa para criar scripts personalizados e atender a casos de uso específicos que ferramentas padrão do mercado não contemplam.
A API pode ser acessada localmente utilizando o socket Unix disponível em /var/run/docker.sock
. Este é o método mais comum em servidores Docker, especialmente para ambientes seguros e isolados. Mas também pode ser acessada remotamente através de HTTP ou HTTPS, caso o daemon Docker seja configurado para escutar em um endpoint TCP. Esse modo é ideal para integrações em sistemas distribuídos, mas requer atenção especial à segurança, como o uso de TLS e autenticação.
Por ser baseada em HTTP, a API pode ser utilizada por qualquer linguagem ou ferramenta que suporte chamadas HTTP ou interação com sockets Unix, como cURL, Python, Go, entre outras. Para acessar a documentação da API para Python, acesse aqui.
Docke Remoto
Por padrão, o Docker é acessível apenas localmente, o que significa que suas funcionalidades não estão disponíveis remotamente, mesmo com a existência da API. Isso ocorre porque, por padrão, o Docker é configurado para operar usando um Socket Unix (/var/run/docker.sock
), que serve como a interface entre o cliente Docker e a API, permitindo a interação com contêineres, redes, volumes e outros recursos.
Falamos um pouco sobre isso na sessão de Arquitetura.
Se você deseja gerenciar os contêineres de um servidor remotamente ou tornar a API acessível pela rede, será necessário modificar a configuração do serviço Docker (docker.service
) em ambientes que utilizam o SystemD, permitindo que ele também escute conexões via TCP.
O padrão é -H fd://
, isso indica que o Docker vai operar com Socket Unix, para habilitar conexões TCP também, adicione o seguinte -H tcp://0.0.0.0:2376
. Isso indica que o Docker deve escutar conexões de qualquer interface de rede (0.0.0.0
) e que a porta de conexão será a 2376 (essa é a porta que usa TLS).
Apesar de a porta 2376 ser amplamente reconhecida para o uso com TLS, não há qualquer criptografia configurada por padrão. Isso significa que apenas utilizá-la não garante segurança alguma. Para proteger a comunicação, é necessário configurar certificados TLS manualmente.
Configurar o TLS envolve a criação de uma CA (Autoridade Certificadora) e a geração de certificados de cliente. Esse processo adiciona uma camada robusta de autenticação, já que cada cliente que desejar se conectar à API precisará de um certificado válido, assinado pela CA configurada no dockerd
. Essa abordagem garante não apenas uma comunicação criptografada, mas também um controle refinado de acesso, aumentando significativamente a segurança.
Evite expor a API a toda a internet, use endereços IP específicos ou configure firewalls para restringir conexões. Lembre-se que uma vez aberta, a API pode ser acessada por qualquer pessoa com permissão para a rede. Portanto, a falta de proteção adequada pode permitir que terceiros controlem os contêineres e comprometam a segurança do sistema.
A segurança da API pode ser garantida através de certificados de cliente, onde cada cliente autorizado deve apresentar um certificado válido durante a conexão para obter acesso. Outra alternativa é o uso de API Tokens, dependendo do contexto de implementação e das necessidades de autenticação.
Se o objetivo é gerenciar o Docker de forma remota sem acessar o servidor via SSH manualmente todas as vezes, você pode utilizar o recurso de Docker Context. Esse recurso permite trocar entre ambientes Docker de forma prática. Para configurá-lo, siga os passos abaixo:
# Crie um contexto remoto usando o SSH:
docker context create --docker host=ssh://USERNAME@IP_ADDRESS --description "Docker on server XYZ" CONTEXT_NAME
Para trocar o contexto e usar o Docker do servidor que configuramos, utilize o comando abaixo:
docker context use CONTEXT_NAME
A partir de agora, todos os comandos Docker serão executados diretamente no servidor remoto configurado.
O usuário utilizado para acessar o servidor via SSH deve ter permissões para executar comandos Docker (geralmente, ele precisa fazer parte do grupo docker
). Configure o SSH para aceitar conexões somente com chaves públicas, reforçando a segurança do acesso remoto.
Seguindo essas orientações, você poderá gerenciar o Docker remotamente de forma segura e eficiente.
Plugins
Os plugins do Docker são extensões que adicionam funcionalidades ou modificam o comportamento padrão do Docker. Eles permitem que recursos personalizados sejam integrados ao Docker Engine, estendendo suas capacidades sem a necessidade de modificar diretamente o código principal.
Instalação de Plugins
Os plugins podem ser instalados diretamente com a CLI do Docker, nós obtemos eles normalmente do Docker Hub.
# Instalar o plugin:
docker plugin install <plugin-name> [options]
# Ativar o Plugin:
docker plugin enable <plugin-name>
# Desativar o Plugin:
docker plugin disable <plugin-name>
# Remover Plugins:
docker plugin rm <plugin-name>
# Listar Plugins Instalados:
docker plugin ls