Construindo e executando uma simples aplicação web em Docker.

Já começo avisando que neste artigo eu não vou ensinar a instalar o Docker. Na documentação oficial você encontra detalhes de como fazer isso.

Nosso principal objetivo é construir uma imagem docker de uma aplicação web Python. Como objetivo secundário, iremos realizar alguns troubleshooting para subir nossa aplicação e aumentar os skills necessários para resolver problemas básicos relacionados ao contexto do que aprenderemos nesse post.

O primeiro passo é agrupar os arquivos da nossa aplicação e suas dependências em um container. Para isso, vamos fazer o seguinte:

Temos aqui uma aplicação simples que irá exibir Hello World! assim que você acessar a aplicação pelo teu browser favorito.

from flask import Flask
app = Flask(__name__)


@app.route("/")
def hello():
    return "Hello World!\n"


if __name__ == "__main__":
    app.run(host='0.0.0.0')

Repare na primeira linha do código que importamos a biblioteca Flask, que é um framework muito popular usado entre os desenvolvedores Python.

Crie um diretório para ser a base do seu aplicativo. Sugiro web-python. Dentro desse diretório, cria outro diretório chamado app e salve o código acima como helloworld.py.

O que precisamos fazer para rodar nossa aplicação em um container?

Basicamente, precisamos fazer o build da imagem docker. Ou seja, iremos empacotar a aplicação em uma imagem de container.

Antes de construir nossa imagem, vamos parar para pensar como rodaríamos essa aplicação diretamente em nosso ambiente de desenvolvimento.

Você precisaria do ambiente Python instalado em seu sistema, que ficaria responsável por interpretar seu código. Você também precisa instalar o framework Flask.

  • Precisamos de uma versão específica do Python e também do Flask. A versão do Python para ter o suporte necessário para executar o código na versão que o mesmo foi desenvolvido e a versão da biblioteca do Flask para você amarrar a versão específica que foi testada durante o desenvolvimento. Mais tarde vou explicar o porque de usar essa abordagem.
  • Só para criar uma simples imagem de uma aplicação em container vai envolver o conhecimento básico de algumas tecnologias. Para não entrar muito em detalhes, vou exemplificar algumas: gerenciamento de pacotes, imagens de sistemas operacionais e execução de comandos.

Dica: sempre crie um ambiente Python para executar seus códigos. Nunca instale bibliotecas diretamente no sistema operacional.

Vamos ao que interessa

Para empacotar nossa imagem, vamos criar um arquivo Dockerfile com o seguinte conteúdo:

FROM ubuntu:20.04
RUN apt-get update -y && apt-get install -y python3-pip python3-dev
COPY requirements.txt /app/requirements.txt
WORKDIR /app
RUN pip3 install -r requirements.txt
COPY ./app/helloworld.py /app
ENTRYPOINT ["python3", "helloworld.py"]

Salve o arquivo Dockerfile na pasta principal. Se você seguiu minha sugestão, esse arquivo ficará na raiz do diretório web-python.

  • Na linha 1, informamos qual a distribuição linux iremos utilizar como imagem base para construção da imagem da aplicação.
  • Em seguida (linha 2), partimos para a execução de comandos para instalar o Python em nossa imagem.
  • Depois, copiamos o arquivo que armazena os pre-requisitos para rodar nossa aplicação (linha 3), informamos o diretório padrão de trabalho da nossa aplicação dentro do container (linha 4) e fazemos a instalação des pre-requisitos (linha 5).
  • Por fim, copiamos o código da nossa aplicação (linha 6) e informamos o que deverá ser executado quando o container for inicializado (linha 7).

Com o arquivo Dockerfile pronto, vamos criar o arquivo requirements.txt (que fizemos referência) e salvá-lo na pasta raíz web-python com o seguinte conteúdo:

Flask==1.1.2

Lembra que eu comentei de amarrar a versão da biblioteca do Flask. Isso é necessário para não correr o risco de quebrar a nossa aplicação caso for preciso criar uma nova versão da imagem docker. Se você apenas informar a biblioteca Flask, o gerenciamento de pacotes pip vai tentar instalar a última versão disponível do pacote. Digamos que ele tente instalar a versão 1.1.3 e esta teve uma modificação que quebra o seu código. Sua aplicação não irá funcionar como esperado e como foi testado no ambiente de desenvolvimento.

A estrutura da nossa aplicação ficará conforme a seguir:

$ tree
.
├── Dockerfile
├── app
│   └── helloworld.py
└── requirements.txt

1 directory, 3 files

Com a estrutura da nossa aplicação pronta, podemos usar o comando para construir nossa imagem:

docker build -t helloworld-server .

Para rodar nossa aplicação, executamos:

docker run -d helloworld-server

Um dos principais motivos que me fez escrever esse post foi para demonstrar que muitas pessoas que querem ingressar na área de DevOps querem pular etapas, mesmo sem saber que estão pulando (neste caso é porque estão sendo enganadas). E não digo isso apenas para os que estão começando na área, mas também para profissionais que já tem certa experiência e estão mais preocupados em adquirir conhecimentos em ferramentas e esquecem que devem ter conhecimentos sólidos de toda a parte que envolve determinadas tecnologias (digo conceitos se sistemas operacionais, redes etc.).

Vocês observaram que no início do post eu citei que para construir a imagem da nossa aplicação, precisamos ter conhecimento básico de alguns comandos de sistemas, instalação e gerenciamento de pacotes?

Pois bem. Se você chegou a executar o container com a imagem que construímos, deve ter reparado que a nossa aplicação não abriu no navegador. Eu fiz isso de propósito. O que faltou para a nossa aplicação funcionar?

Antes de eu dar essa resposta, por que não verificamos se a nossa aplicação está funcionando dentro do container? Para isso, vamos acessar o terminal do container executando o seguinte comando:

docker exec -it <id-do-container> bash

Para verificar o id do container, execute docker ps que você irá obter uma resposta parecida com a seguinte:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
faa60fb6a829 helloworld-server "python3 helloworld.…" 9 minutes ago Up 9 minutes sweet_hermann

Você também pode obter acesso ao terminal do container passando o nome ao invés do seu ID.

Já dentro do container, vamos instalar o curl, uma ferramenta para várias utilidades. Uma delas é testar acesso a sites direto do terminal.

apt-get install curl -y

Em seguida, vamos fazer o teste de acesso a nossa aplicação:

curl http://localhost

E receberemos a seguinte mensagem:

curl: (7) Failed to connect to localhost port 80: Connection refused

Ora, não conseguimos acesso a aplicação?

Será que nossa aplicação está rodando no container. Vamos verificar?

# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 1.2 105156 25272 ? Ss 21:19 0:00 python3 helloworld.py
root 168 0.0 0.1 4244 3520 pts/0 Ss 21:29 0:00 bash
root 178 7.0 0.1 5900 2904 pts/0 R+ 21:33 0:00 ps aux

Nossa aplicação está sendo executada. Se você tem conhecimento do framework Flask, sabe que uma aplicação por padrão roda em uma porta específica. Mas, se você não tem conhecimento e chegou até aqui nesse post, como saber em que porta a aplicação está rodando. Vamos instalar mais uma ferramenta para descobrirmos isso:

apt-get install net-tools -y

Instalamos o pacote net-tools. Mas, a ferramenta que iremos usar é a netstat que vem instalada com esse pacote.

Agora executamos o comando:

# netstat -ntal
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:5000 0.0.0.0:* LISTEN
tcp 0 0 172.17.0.2:46426 91.189.88.152:80 TIME_WAIT

Observe que a primeira linha iniciada com tcp faz referência a 0.0.0.0 (que definimos como valor de host na última linha de código da nossa aplicação), seguida de :5000. Essa é a porta onde a aplicação está em execução. Agora, podemos fazer o teste certo:

curl http://localhost:5000
Hello World!

Tivemos o retorno esperado da nossa aplicação.

Sabendo que nossa aplicação está funcionando dentro do container, podemos matar o container

docker rm -f <id_do_container>

E agora executamos novamente o container passando o parâmetro de mapeamento de portas.

docker run -d -p 8080:5000 helloworld-server

Executando docker ps, podemos observar que o mapeamento de portas está configurado para nosso container:

docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e786dc13503e helloworld-server "python3 helloworld.…" 2 seconds ago Up 1 second 0.0.0.0:8080->5000/tcp exciting_hypatia

A porta 8080 será a porta que estará listada no host onde o docker está rodando. Ao ser requisitado acesso a porta 8080, automaticamente o acesso será encaminhado para a porta 5000 do container.

Agora podemos abrir o browser e acessar nossa aplicação passando a porta 8080.

Pronto. Nossa primeira aplicação em container rodando 100%.

Viram que para subir uma simples aplicação web, passamos por várias tecnologias, conceitos básicos, ferramentas etc.

Eu poderia muito bem resumir esse post apenas passando os comandos certos para você executar e no final ter a sua aplicação rodando lindamente, sem ter passado pelos erros que simulamos aqui.

O que eu quero postar no blog a partir desse artigo é para ajudar você a pensar em aprender a dominar uma tecnologia, aprender a ter conhecimentos sólidos e básicos de tudo que envolve para você resolver problemas. Infelizmente, nos últimos anos, muitos profissionais estão sendo “adestrados” por cursos e vídeos em redes sociais para serem fanáticos por ferramentas, meros mortais executores de comandos sem saber o que está fazendo. E acredite. Se você está se sentindo assim, o objetivo dessas pessoas está sendo atingido. Eles não querem que você pense para resolver problemas. Eles querem que você siga passos prontos e assim você sempre fica na dependência de uma nova dica de como fazer. Mas, nunca como você deve aprender.

A pergunta que eu faço é:

Você quer ser mais um desses “adestrados” e não se destacar no mercado de trabalho?

Se sua resposta for não, comece a seguir este blog, compartilhe com seus colegas. Eu vou continuar a minha missão aqui, que é passar conhecimento de verdade. E tenho outros amigos que desejam fazer o mesmo porque temos o mesmo intuito, mudar tudo que está sendo feito nesses últimos anos. E temos experiência para isso.

Em um post futuro vou demonstrar como podemos melhorar a construção da nossa imagem Docker e deixar ela mais otimizada. Por que para melhorar, sempre existe um jeito. Antes, teremos mais novidades.

Até a próxima.

Publicado por Janssen dos Reis Lima

+20 anos de experiência na área de TI. Graduado em Sistemas de Informação pela FeMASS e especialista em Administração em Redes Linux pela UFLA. Apaixonado por tecnologia, procuro sempre me manter atualizado. Já escrevi livro, já plantei árvore e tenho um filho. Possuo certificação em Kubernetes (CKA), Azure (AZ-104) e Zabbix (ZCS e ZCP).

Um comentário em “Construindo e executando uma simples aplicação web em Docker.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s

%d blogueiros gostam disto: