Docker: um guia prático para colocar seu projeto em produção

Rafael K
12 min readNov 10, 2020

--

Palavras chaves: Docker, deployment, colocar o projeto no ar, container, Heroku, Streamlit

Material produzido para a Tera

A divulgação de um projeto é um passo essencial a ser tomado pelas pessoas que trabalham com a Ciência de Dados, afinal de contas, imagine o desperdício em ter desenvolvido a melhor solução para um problema porém deixá-la esquecida em seu computador?

Que baleia graciosa, não é mesmo?

Antes de mais nada…

O que é o Docker e para o que ele serve?

Docker é uma ferramenta de compartimentalização. Ele agrega todos aqueles arquivos necessários para o funcionamento de um aplicativo e os concentra em um único compartimento chamado container.

Quem não precisa de algo assim na vida?

Certo, então o Docker simplesmente organiza meu documento de código e base de dados em um lugar só?

Não é bem isso. A princípio pode parecer que um projeto de Ciência de Dados funciona apenas com um script de código e dados. Entretanto, vale lembrar que mesmo o mais simples dos projetos utiliza muitas coisas, desde bibliotecas ao próprio sistema operacional da máquina.

Um projeto que tenha sido codificado utilizando uma versão específica de uma biblioteca pode apresentar um comportamento inesperado ou quebrar caso seja executado em uma máquina que contenha uma versão diferente da mesma biblioteca. Essa incompatibilidade pode ocorrer inclusive com os sistemas operacionais: um projeto desenvolvido em um ambiente Windows pode comportar-se diferente em um Linux. Esse problema de incompatibilidade de configurações entre máquinas é conhecido como dependency hell🔥.

O risco de incompatibilidade é mitigado pelo Docker, que concentra no container tudo o que o aplicativo precisa para funcionar em qualquer máquina. Isso garante que o projeto se comporte exatamente da mesma forma para qualquer usuário.

O mesmo projeto para qualquer pessoa e em qualquer lugar

A definição acima parece de uma máquina virtual. Qual é a diferença entre uma máquina virtual e um container?

De fato, em termos práticos, ambos são semelhantes. Tanto a máquina virtual quanto o container emulam ambientes operacionais com configurações específicas dentro de uma máquina. Elas diferem, contudo, na maneira como isso é feito.

Arquitetura simplificada de uma máquina virtual. Fonte: https://www.docker.com/resources/what-container

De forma geral, uma máquina virtual emula um computador de forma integral, processando todas as configurações, desde o sistema operacional, softwares e até bibliotecas.

Ou seja, a carga de processamento da máquina virtual é alta pois ela cria virtualmente uma segunda máquina completa com os recurso da máquina física.

Arquitetura simplificada do container. Fonte: https://www.docker.com/resources/what-container

O container, por sua vez, processa apenas as configurações necessárias para a execução do projeto, evitando a alocação desnecessária da capacidade de processamento da máquina física.

Essa diferença é a vantagem do container, pois ao economizar esse poder de processamento, o projeto é executado em menos tempo.

Em outras palavras, a vantagem do container é sua eficiência.

Entendido o que é o Docker e quais são suas funcionalidades básicas, o próximo passo consiste em entender como usá-lo.

Guia prático do Docker

Este guia prático contém um passo-a-passo para colocar um projeto simples no ar. Cada etapa aborda os comandos a serem executados e sua explicação conceitual.

O funcionamento do Docker será exemplificado a partir de um projeto comum em Python que utilize o framework de aplicação web do Streamlit. O Docker será utilizado para criar uma versão executável da aplicação web e, por fim, o deployment será via Heroku.

Visão geral das etapas deste tutorial

Passo 1: Python

Durante o desenvolvimento de um projeto é comum a utilização de recursos como o Jupyter Notebook ou o Google Colab que facilitem a visualização gráfica do código.

Para o deployment será necessário converter o código do formato “.ipynb” em um arquivo com extensão “.py”. Essa conversão é simples, bastando utilizar um programa de editor de texto (e.g. Notepad ou Sublime) para salvar o arquivo na extensão “.py”.

Passo 2: Streamlit

Provavelmente, uma solução de machine learning apresentada apenas em linhas de código não será compreendida pela maioria de seus usuários. Uma maneira de solucionar isso é transformar o código em uma interface gráfica amigável e de fácil entendimento. O Streamlit é uma das opções mais populares para cumprir essa função.

Exemplo do framework de aplicativo web proporcionado pelo Streamlit

O Streamlit é uma biblioteca open source do Python e sua função é permitir o desenvolvimento da interface de um aplicativo web. Desenhada para ser uma solução simples e de fácil utilização, a biblioteca permite a implementação de uma interface pré-definida em poucas linhas de código.

Uma introdução do Streamlit e suas funcionalidades básicas pode ser encontrada neste artigo. O exemplo utilizado pode ser acessado no link abaixo:

Este guia prático do Docker se baseará no mesmo projeto acima, e pode ser encontrado no repositório GitHub abaixo:

Copie o repositório acima em sua máquina física e certifique-se que o Streamlit consiga executá-lo. Para isso, abra o terminal e execute os comandos abaixos:

Executando o Streamlit localmente

Uma janela do navegador deverá ser aberta e apresentar a imagem abaixo:

Esse é o projeto a ser colocado em produção com o Docker e Heroku

É importante que tenhamos certeza que o Streamlit está sendo executado corretamente. Caso o projeto não tenha carregado no navegador ou o terminal falhou em executar o projeto, será necessário investigar o problema. Nesse sentido, o próprio log resultado no terminal é uma pista dos possíveis erros.

Passo 3: Docker

3.1: Instalando o Docker

O Docker pode ser utilizado em máquinas Mac, Windows ou Linux. O website oficial contém uma seção dedicada para a instalação em cada plataforma.

Certifique-se que o Docker foi instalado corretamente executando o seguinte comando no terminal:

Resultado esperado do comando ‘docker run hello-world’

O hello-world foi importado do repositório público do Docker (i.e. Docker Hub) e executado em nossa máquina física. Isso significa que a instalação foi um sucesso.

Repare que na primeira linha de retorno do código o objeto destacado foi image e não um container :

unable to find image "hello-world:latest" locally

A imagem é um “diagrama”que contém os elementos necessários para a execução de um aplicativo, sendo a partir dela que um container é criado. Para entender mais das diferenças, esse artigo da Sofija Simic faz uma análise interessante sobre imagens vs containers.

A próxima etapa é criar uma imagem do projeto exemplo.

3.2: Preparação para criação da imagem

A criação da imagem do projeto exemplo depende de outros dois arquivos: o Dockerfile e o requirements.txt.

Inclusão do Dockerfile e o requirements.txt na pasta raiz

O Dockerfile é um arquivo de texto sem extensão que contém os comandos a serem executados pelo Docker durante a criação da imagem, ou seja, o Dockerfile é a “receita” da imagem. Caso o arquivo não seja incluído no projeto, o terminal resultará na mensagem de erro abaixo:

Erro de ausência do Dockerfile ao criar uma imagem

Para criar o Dockerfile basta copiar o código a seguir em um editor de texto, como por exemplo o Notepad ou o Sublime, e salvá-lo sem extensão:

Dica: no Windows, basta salvar o documento com aspas, ou seja, “Dockerfile”)

Conteúdo do Dockerfile

Além do Dockerfile, será utilizado também um arquivo chamado requirements.txt, que é um documento de texto simples que contém as bibliotecas e versões específicas utilizadas no projeto. Em nosso exemplo, o requirements.txt contém os seguintes códigos:

Conteúdo do requirements.txt

Esse documento, diferentemente do Dockerfile, não é essencial para rodar o Docker. Nesse caso, basta incluir manualmente as bibliotecas e suas versões no Dockerfile, o que pode ser mais simples se estamos falando de duas ou três bibliotecas. Contudo, quando o projeto contém múltiplas bibliotecas (que é o mais provável), torna-se impraticável fazê-lo manualmente.

Felizmente, existem maneiras fáceis de se criar o requirements.txt, como o uso da biblioteca Pipreqs. Ela gera automaticamente o documento requirements.txt com base nas bibliotecas encontradas na pasta raiz.

No terminal execute o código abaixo:

Instalando e executando o Pipreqs
Sucesso ao criar o documento “requirements.txt” com o Pipreqs

3.3: Criando a imagem

Para criar a imagem, é necessário executar no terminal o código abaixo. Essa linha de código significa basicamente “docker, pegue os arquivos da pasta atual e construa uma imagem e o nomeie como artigo_docker”.

Comando de criação de uma imagem

Dica 💡: a primeira execução desse código deve levar alguns minutos, então aproveite para pegar um café e trocar sua playlist de música.

Imagine que isso está acontecendo dentro de seu computador

Repare que o processo de criação da imagem durou vários passos (nesse exemplo foram 7 passos) e esses passo são determinados por cada linha do Dockerfile.

Trecho inicial do processo de criação da imagem

Essa lógica de construção gradual da imagem é denominada criação por camadas, e também contribui para a agilidade do Docker. Neste exemplo a primeira camada foi o Python (mais especificamente, uma imagem da versão 3.8.2 do Python que encontra-se no repositório público do Docker Hub). Gradulmente, outras camadas foram sendo agregadas até resultar na imagem final artigo_docker.

A vantagem disso é que, caso a imagem seja recriada ou opte-se por criar outras imagens também utilizem a versão 3.8.2 do Python, o processo leva menos tempo, dado que as parte das configurações necessárias já estarão salvas em sua máquina física.

Para verificar as imagens existentes em sua máquina física, insira no terminal docker image ls . O terminal deverá retornar três imagens: a hello-world usada no começo do artigo, a python utilizada em nossa imagem e a própria imagem artigo_docker.

Lista de imagens na máquina física

Disclaimer: não executaremos o container no Docker.
Apesar do Docker ser capaz de montar e executar o container, neste tutorial usaremos o Docker apenas para criar a imagem, enquanto criar o container e executá-lo ficará a cargo do Heroku. A lógica disso é que o objetivo é disponibilizar o projeto na internet, porntato, o container deverá ser executado no servidor, e não em um ambiente local.

Passo 4: Heroku

Uma vez construída a imagem, os próximos passos são construir o container e executá-lo em um servidor. Este tutorial utiliza a plataforma de servidores em nuvem Heroku. Será necessário a criação de uma conta, mas fique tranquilo pois há a possibilidade criar uma conta gratuita que permite a hospedagem simultânea de até cinco aplicativos.

Faça o login em sua conta e crie um novo aplicativo:

Clique em “New” no canto superior direito da tela inicial e depois em “Create new app”
Preencha com o nome desejado (nesse guia optamos por “app-artigo-docker”)

Após criar sua conta, será necessário também instalar o Heroku Command Line Interface (CLI), que possibilita a interação do usuário com o servidor via terminal de comando. O link abaixo é um tutorial de como instalar o Heroku CLI para Mac, Windows ou Linux:

No terminal, execute o script abaixo uma linha por vez:

Comandos a serem executados no Terminal para interagir com o Heroku

Hora da Verdade

Uma aba do navegador deverá ter sido aberta e o endereço deverá ter um sufixo herokuapp.com. É comum que a janela demore alguns minutos para carregar pois o primeiro acesso é mais demorado que os próximos.

Que essa tenha sido sua reação ao abrir o navegador

Caso a página aberta seja parecida com esta página, parabéns, você conseguiu colocar o projeto no ar usando o Docker!

Caso, infelizmente, este não seja o caso, não se aborreça. Gaste mais alguns minutos lendo o FAQ ao final do artigo. Quem sabe seu problema não é resolvido?

Conclusão

Este artigo introduziu o Docker e alguns de seus conceitos principais, como imagem, container e criação em camadas, além de disponibilizar um guia prático contendo o passo-a-passo de como usá-lo.

É importante ressaltar, contudo, que o deployment é apenas uma das utilidades do Docker. Aproveite o conhecimento adquirido e descubra as possibilidades que essa tecnologia pode proporcionar.

Vai lá, explore esse mundão e aprenda coisas novas! E, se possível, depois volte para nos contar o que você descobriu.

Só vai, colega

Disclaimer: a partir de 1/11/2020 o Docker mudou sua política de uso e anunciou um limite na quantidade de importações que uma conta gratuita pode fazer:

“Free accounts are limited to 200 pulls per 6 hour period.”

FAQ

No FAQ suas dúvidas podem estar

Como eu crio um arquivo sem extensão (i.e. Dockerfile)?

Tanto em uma máquina Linux quanto em um Mac, basta renomear o arquivo sem extensão e salvá-lo.

No Windows, entretanto, essa tarefa não é óbvia, pois arquivos sem extensão são automaticamente atribuídos como .txt. A solução é colocar o nome do arquivo entre aspas, ou seja, “Dockerfile”.

Qual é a diferença entre usar o Docker e o GitHub para colocar um projeto no ar com o Heroku?

As duas estratégias para o deployment diferem em relação aos arquivos necessários, grau de complexidade e limitações.

Enquanto o deployment com o Docker requer o arquivo Dockerfile para a criação da imagem, o GitHub requer o arquivo Procfile.

Embora o uso do GitHub possa ser considerado mais simples, dado que não é necessário usar o terminal de comando, ele é limitado, dado que é possível fazer o deployment apenas de repositórios próprios. O uso do Docker, em contrapartida, requer o uso do terminal (via Heroku CLI) porém pode ser aplicado em qualquer imagem.

Observação: o Heroku permite até 6 maneiras diferentes para colocar um projeto no ar.

Como deletar uma imagem criada por engano?

Primeiro é necessário listas as imagens existentes com docker image ls e depois executar o comando docker rmi -f [ID IMAGEM] .

Dica: não é necessário escrever o ID completo, mas apenas os caracteres suficientes para identificar a imagem a ser deletada. Nesse exemplo apenas os 4 primeiros caracteres foram suficientes para identificar o ID.

Como deletar uma imagem

O navegador retornou a mensagem de erro abaixo. O que fazer?

Isso definitivamente não parece bom

Apesar da mensagem padrão de erro do Heroku sugerir executar o comando heroku logs --tail para encontrar o erro, essa abordagem pode não ser a mais eficiente. O problema de começar a análise pelo logs do Heroku é que os registros são relativamente complexos de se entender e indicam problemas vinculados ao Heroku. Isso significa que irregularidades ocorridas em passos anteriores, como por exemplo durante a criação do Dockerfile, podem passar despercebidas.

Portanto, a abordagem sugerida é rever o guia prático deste artigo, certificando-se que todos os passos e códigos foram corretamente executados.

Após conferir a correta criação da imagem pelo Docker é que vale a pena avaliar os logs do Heroku. Caso essa seja seu caso, o log contém linhas que identificam o erro ocorrido e sua categoria, como por a imagem abaixo. Com essa pista em mãos, o caminho é explorar o StackOverflow e/ou fóruns especializados.

Exemplo de erro código H10 no Heroku. Fonte: https://forum.theodinproject.com/t/web-dev-101-blogger-heroku-error-code-h10/40029

Glossário

  • Container: unidade operacional executável formado por todas as configurações necessárias para a execução de um aplicativo. O container é uma instância de uma imagens.
  • Docker: tecnologia de compartimentalização baseada em container.
  • Docker Hub: repositório de imagens, semelhante ao Git Hub.
  • Dockerfile: lista de comandos a serem tomados pelo Docker durante a criação de uma imagem.
  • Imagem: unidade operacional não executável que concentra os arquivos necessários para a execução de um aplicativo. É o “diagrama” dos containers.
  • Máquina virtual: unidades operacional que emula uma máquina de forma independente da máquina física. Ela permite executar programas próprios de sistemas operacionais diferentes ou mesmo isolar uma aplicação do resto do sistema.
  • Streamlit: biblioteca open source de desenvolvimento de aplicativos web.

Para saber mais

That’s all Folks (Fonte: Bart van meele on Unsplash)

--

--

Rafael K
Rafael K

Written by Rafael K

Data Scientist at Zup Innovation