Docker para Iniciantes: Diga Adeus aos Pesadelos de Implantação!

Docker para Iniciantes: Diga Adeus aos Pesadelos de Implantação!

Desenvolvedores iniciantes frequentemente enfrentam problemas como atualizações, lançamentos e implantações de código ineficientes, além de desafios em manter a consistência do ambiente. Código que funciona perfeitamente no ambiente de desenvolvimento pode apresentar erros em uma máquina diferente. Na era da computação em nuvem, implantar código usando métodos tradicionais parece ultrapassado. Este post de blog vai te apresentar ao Docker.

Docker, baseado na linguagem Go e de código aberto sob a licença Apache 2.0, é um mecanismo de contêiner de aplicações. Essa tecnologia de conteinerização permite que desenvolvedores empacotem suas aplicações e dependências em contêineres leves e portáteis. Esses contêineres podem ser implantados em qualquer máquina Linux popular, sem se preocupar com diferenças de ambiente.

Docker vs. Máquinas Virtuais (VMs)

Como mencionado, o Docker utiliza virtualização. Ao falar sobre virtualização, as Máquinas Virtuais (VMs) inevitavelmente entram em cena. Como ambas dependem de virtualização, é natural perguntar sobre suas diferenças. Vamos nos aprofundar nisso.

Primeiramente, vejamos um diagrama típico da arquitetura de uma VM. Acima da infraestrutura (representando o hardware subjacente), há um hipervisor. Atuando como intermediário entre o servidor físico e os sistemas operacionais, ele permite que múltiplos sistemas operacionais e aplicações compartilhem o hardware subjacente. As máquinas virtuais executam vários sistemas operacionais distintos sobre o sistema operacional host e usam o hipervisor para acessar o hardware subjacente.

Se você precisasse executar três aplicações isoladas, criaria três máquinas virtuais. Isso significa que três sistemas operacionais seriam executados sobre o hipervisor, resultando em uma sobrecarga significativa de recursos.

Um diagrama típico da arquitetura de uma VM

(Nota: O diagrama deveria idealmente mostrar um Sistema Operacional Host acima do Hipervisor)

O Docker, por outro lado, é notavelmente leve. Seu daemon (Docker Daemon) substitui o hipervisor, executando diretamente no sistema operacional. O código fonte da aplicação e suas dependências são empacotados em uma imagem Docker. O mecanismo Docker então usa essa imagem para criar um contêiner. Diferentes aplicações são executadas em contêineres isolados.

Além disso, o daemon do Docker se comunica diretamente com o sistema operacional para alocar recursos aos contêineres Docker. Sem a sobrecarga de um sistema operacional completo, o tempo de inicialização do contêiner é reduzido de minutos para máquinas virtuais para meros milissegundos para contêineres Docker, aumentando significativamente a eficiência e economizando espaço em disco e outros recursos do sistema.

Embora o Docker ofereça vantagens convincentes, ele não substitui completamente as máquinas virtuais. Cada tecnologia tem seus pontos fortes. As máquinas virtuais são excelentes para isolar todo o ambiente de execução, sendo comumente usadas por provedores de nuvem para separar usuários por meio de VMs. O Docker, no entanto, normalmente isola aplicações diferentes.

Como Usar o Docker

Instalação do Docker (Exemplo CentOS 7)

  1. Instale ferramentas essenciais do sistema:
yum install -y yum-utils device-mapper-persistent-data lvm2 
  1. Atualize o kernel do sistema e o cache do yum:
yum update
yum makecache fast
  1. Instale o Docker e inicie-o:
yum -y install docker-ce
systemctl start docker 
  1. Teste se o Docker foi instalado com sucesso:
docker run hello-world 

Se você vir “Hello from Docker” na tela, parabéns! A instalação está completa.

Conceitos

Antes de nos aprofundarmos no Docker, vamos abordar alguns conceitos-chave para uma experiência de aprendizado mais suave.

  1. Imagens Docker: A imagem Docker é um modelo usado para criar contêineres Docker.
  2. Contêiner Docker: O Docker cria contêineres a partir de imagens para executar um conjunto de aplicações independentes.
  3. Registro Docker: Repositório de código para salvar imagens.

Normalmente, baixamos a imagem apropriada de um registro Docker e a usamos para criar contêineres para executar nossas aplicações.

Exemplos

Vamos conectar esses conceitos por meio de dois exemplos comuns para ilustrar como usar o Docker.

Instalando Python com Docker

Como mencionado, o primeiro passo para usar um contêiner Docker é baixar a imagem correspondente de um repositório. Isso nos leva ao primeiro comando do nosso tutorial:

  • Objetivo: Procurar uma imagem específica no repositório de imagens.
  • Sintaxe: docker search [OPÇÕES] TERMO
  • Exemplo: docker search python
  • Explicação: Procurar imagens relacionadas ao Python no repositório.
[root@novita ~]# docker search pythonINDEX       NAME                                       DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
docker.io   docker.io/python                           Python is an interpreted, interactive, obj...   4356      [OK]
docker.io   docker.io/django                           Django is a free web application framework...   856       [OK]
docker.io   docker.io/pypy                             PyPy is a fast, compliant alternative impl...   196       [OK]
docker.io   docker.io/kaggle/python                    Docker image for Python scripts run on Kaggle   125                  [OK]
docker.io   docker.io/arm32v7/python                   Python is an interpreted, interactive, obj...   38
docker.io   docker.io/centos/python-35-centos7         Platform for building and running Python 3...   36

Vamos escolher a imagem oficial com a tag (versão) 3.7.

docker pull

  • Objetivo: Baixar ou atualizar uma imagem especificada do repositório de imagens.
  • Sintaxe: docker pull [OPÇÕES] NOME:TAG
  • Exemplo: docker pull python:3.7
  • Explicação: Baixar a imagem Python com a tag 3.7 do repositório.
[root@novita ~]# docker pull python:3.7
Trying to pull repository docker.io/library/python ...3.7: Pulling from docker.io/library/python
5ae19949497e: Downloading [=============>                                     ] 13.72 MB/50.38 MB
ed3d96a2798e: Download complete
f12136850781: Downloading [============================================>      ] 8.789 MB/9.978 MB
1a9ad5d5550b: Downloading [==>                                                ] 2.628 MB/51.77 MB
6f18049a0455: Waiting
ce39fa9d79d1: Waiting
Digest: sha256:d8718f4c8f28360c88d2d8b53681edb3c95e6a7bacedabd32eb5b1d120a75dc5
Status: Downloaded newer image for docker.io/python:3.7

O Docker já baixou a imagem especificada. Para visualizar as imagens Docker existentes:

docker images

  • Objetivo: Listar imagens locais.
  • Sintaxe: docker images [OPÇÕES] [REPOSITÓRIO[:TAG]]
  • Exemplo: docker images
  • Explicação: Visualizar todas as imagens Docker locais.
[root@novita ~]# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
docker.io/python        3.7                 42d620af35be        6 days ago          918 MB
docker.io/rabbitmq      3-management        7aae48fa6ef6        7 days ago          179 MB
docker.io/golang        latest              f50db16df5da        9 days ago          774 MB

A imagem python3.7 está presente. Vamos criar um contêiner usando-a.

docker run

Antes de criar o contêiner, vamos abordar brevemente os IDs. No Docker, IDs identificam exclusivamente imagens ou contêineres. Interagimos com eles usando “comando + ID”. Por exemplo, no código anterior, o ID da imagem python3.7 é 42d620af35be.

  • Objetivo: Criar um novo contêiner.
  • Sintaxe: docker run [OPÇÕES] IMAGEM [COMANDO] [ARG...]

Para testar o ambiente Python, vamos criar um arquivo hello.py localmente:

#!/usr/bin/python 
import sys 

print("Hello, Docker!") 
print(sys.version)  # Exibe o número da versão do Python 

Supondo que esse código esteja salvo em /root/code/python:

[root@novita python]# docker run  -v $PWD:/usr/src/code  -w /usr/src/code python:3.7 python hello.py 
Hello, Docker! 
3.7.4 (default, Jul 13 2019, 14:04:11) [GCC 8.3.0] 

Vamos detalhar este comando:

  • docker run: Cria um contêiner.
  • -v $PWD:/usr/src/code: Monta o diretório local no contêiner Docker. Aqui, monta o diretório onde o comando é executado para /usr/src/code dentro do contêiner. Os dois pontos separam o caminho local do caminho do contêiner. Você pode usar caminhos absolutos em vez de $PWD.
  • -w /usr/src/code: Define o diretório de trabalho do contêiner. Como o diretório do código Python está montado em /usr/src/code, o definimos como diretório de trabalho.
  • python:3.7: Especifica a imagem. Você pode usar o ID da imagem.
  • python hello.py: Executa este comando dentro do contêiner.

Exercício mental: Se você tem um arquivo hello.go em /root/data/ e quer executá-lo usando um contêiner Golang com o ID de imagem f50db16df5da, qual seria o comando? (Dica: O comando para executar o código Go é go run NOME_DO_ARQUIVO)

Instalando MariaDB com Docker

Supondo que você já saiba procurar e baixar uma imagem MariaDB, vamos focar em iniciá-la. Serviços como bancos de dados exigem que portas correspondentes estejam abertas no host. Como conseguimos isso com Docker? Usaremos mapeamento de portas, similar à montagem de diretórios.

[root@novita python]# docker run -d -v /data/mysql/:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456  --restart unless-stopped 3a2ef06682ac 
  • -d: Executa o contêiner em segundo plano.
  • -p 3306:3306: Mapeia a porta 3306 do contêiner para a porta 3306 do host.
  • -e MYSQL_ROOT_PASSWORD=123456: Define a senha do root do MariaDB como 123456.
  • --restart unless-stopped: Reinicia o contêiner automaticamente se ele parar inesperadamente.
  • 3a2ef06682ac: O ID da imagem para criar o contêiner.

Agora, vamos verificar se o serviço de banco de dados está em execução:docker ps

  • Objetivo: Listar contêineres.
  • Sintaxe: docker ps [OPÇÕES]
[root@novita ~]# docker ps 
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                                                                                        NAMES
107b52416c13        3a2ef06682ac        "docker-entrypoint..."   5 minutes ago       Up 5 minutes        0.0.0.0:3306->3306/tcp                                                                       quizzical_mcnulty 

Em seguida, vamos acessar o ambiente interno do contêiner.docker exec

  • Objetivo: Executar um comando em um contêiner em execução.
  • Sintaxe: docker exec [OPÇÕES] CONTÊINER COMANDO [ARG...]
  • Exemplo: docker exec -it 107b52416c13 bash
  • Explicação: Acessar o contêiner com ID 107b52416c13 e executar o comando bash.

Dentro do contêiner, você pode interagir com ele como em um ambiente Linux normal. Usando as credenciais definidas anteriormente, você pode acessar o MariaDB.

[root@novita ~]# docker exec -it 107b52416c13 bash 
root@107b52416c13:/# mysql -u root -p123456 
Welcome to the MariaDB monitor.  Commands end with ; or \g. 
Your MariaDB connection id is 11 
Server version: 10.4.6-MariaDB-1:10.4.6+maria~bionic mariadb.org binary distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
MariaDB [(none)]> 

Até agora, você aprendeu o básico do Docker. Tente explorar mais.

Novita AI é a plataforma de nuvem completa que capacita suas ambições de IA. Com APIs perfeitamente integradas, computação serverless e aceleração de GPU, fornecemos as ferramentas econômicas necessárias para construir e escalar rapidamente seu negócio orientado por IA. Elimine as dores de cabeça de infraestrutura e comece gratuitamente - Novita AI torna seus sonhos de IA realidade.