Voltar ao blog

Construir e Implantar uma Aplicação Flask com Docker no Ubuntu 20.04

Construir e Implantar uma Aplicação Flask com Docker no Ubuntu 20.04

Introdução

Docker é uma plataforma de contêineres de código aberto. É um ambiente padronizado, leve, virtualizado, portátil e definido por software que permite que o software seja executado de forma isolada de outros softwares em execução na máquina host física. O Docker oferece uma alternativa leve às máquinas virtuais. Ao mesmo tempo, oferece portabilidade, desempenho, agilidade e escalabilidade de aplicativos. Para um guia abrangente sobre o ecossistema Docker, dê uma olhada em nossa visão geral detalhada sobre conteinerização com o Docker.

Flask é um framework web minimalista de código aberto construído com Python. Algumas das excelentes características do Flask são o fato de ser leve, flexível e altamente estruturado. Além disso, não requer ferramentas ou plug-ins específicos para ser executado.

A combinação de Flask e Docker oferece um aplicativo leve, flexível e escalável. Você pode implantá-lo em vários servidores e infraestruturas, graças à natureza portátil dos contêineres Dockerizados. O foco deste tutorial é mostrar como implantar um aplicativo Flask com o Docker. Também demonstraremos como garantir que as atualizações futuras do seu aplicativo entrem em vigor.

Pré-requisitos

Este será um tutorial prático, e você deve criar um ambiente que permita acompanhar as etapas:

Agora, vamos começar!

Etapa 1: Preparar o Aplicativo Flask

Começaremos criando um diretório que conterá nosso aplicativo Flask. Você pode escolher o nome de diretório que preferir. No entanto, para este tutorial, nós o chamaremos de flask_demo. Salvaremos os arquivos do projeto dentro do diretório /var/www , que geralmente é o diretório ao qual o Ubuntu permite acesso à internet pública por padrão. Primeiro, execute os seguintes comandos para criar o diretório e navegar até ele:

Dentro deste diretório raiz do nosso projeto, criaremos a estrutura de pastas base de um aplicativo Flask. Em seguida, execute o seguinte comando para criar a estrutura base, adicionando a flag -p para criar todas as pastas pai ao longo do caminho:

A pasta app contém todos os arquivos relacionados a um aplicativo Flask, incluindo views e blueprints. As views contêm o código que você escreve para responder às requisições que chegam ao seu aplicativo. Os blueprints ajudam a criar componentes de aplicativo e oferecem suporte a padrões comuns em aplicativos Flask.

A pasta apropriadamente nomeada static contém recursos estáticos, como imagens, arquivos CSS e JavaScript. O diretório templates contém todos os templates HTML do projeto.

Agora podemos começar a escrever os arquivos necessários para inicializar um aplicativo Flask. Comece criando um arquivo chamado __init__.py dentro do diretório app para dizer ao Python interpretador que o diretório app deve ser tratado como um pacote. Execute o seguinte comando no seu terminal para abrir o arquivo com o editor nano:

Usamos pacotes em Python para agrupar módulos em namespaces ou hierarquias lógicas. A modularização permite dividir o código em blocos individuais e gerenciáveis que realizam funções definidas.

Depois disso, dentro do arquivo __init__.py aberto no seu editor, adicione o seguinte trecho de código para iniciar a instância do Flask e importar a lógica do views.py que você criará nas próximas etapas:

Quando terminar, pressione Ctrl + O e ENTER para salvar o arquivo, depois feche-o com Ctrl + X. Em seguida, vamos criar o views.py dentro do app diretório. O views.py arquivo conterá a maior parte da lógica da aplicação:

Dentro do arquivo, adicione o seguinte trecho de código. Este código exibirá uma string simples para mostrar que seu aplicativo está em execução quando os usuários visitarem seu site:

Neste arquivo, começamos importando a instância do aplicativo Flask. Depois, precisamos adicionar uma linha para definir a rota: @app.route(/). A linha @app.route(/) é referida como um decorador no Flask. Você pode usar decoradores para injetar funcionalidades adicionais em uma ou mais funções. Neste caso, estamos passando uma chamada para a rota / para a função home. Quando um usuário visitar esta rota, ele verá o texto: "Nosso aplicativo Flask está em execução!".

Em seguida, você criará o arquivo uwsgi.ini para conter as uWSGI configurações para a aplicação. uWSGI é uma opção de implantação para o Nginx que serve como um protocolo e um servidor de aplicação. Execute o seguinte comando para criar o arquivo no diretório raiz do projeto com o editor nano:

Dentro do arquivo aberto, adicione o seguinte trecho de código:

Este arquivo contém algumas diretivas. Definimos o propósito delas abaixo:

  • module – define o módulo a partir do qual a aplicação Flask será servida. Definimos o módulo como main, referenciando o arquivo main.py no diretório raiz. Criaremos este arquivo no próximo passo.
  • callable – direciona o uWSGI a usar a instância app exportada da aplicação.
  • master – garante que a aplicação continue em execução para minimizar o tempo de inatividade durante a reinicialização de toda a aplicação.

Salve e feche o arquivo quando terminar.

Agora você pode criar o arquivo main.py para determinar o ponto de entrada para a sua aplicação. O uWSGI lerá este arquivo para saber como interagir com a aplicação. Execute o seguinte comando para criar o arquivo main.py  com o nano dentro do diretório raiz do seu projeto:

Dentro do arquivo, adicione a seguinte linha que importará a instância do Flask que foi criada no pacote da aplicação:

A última coisa que você fará neste passo é definir as dependências necessárias para a aplicação ser executada. Definiremos essas dependências dentro de um arquivo chamado dependencies.txt. Quando o Docker construir a imagem da sua aplicação, ele executará um comando do gerenciador (de pacotes pip) para instalar as dependências. Abra o arquivo no diretório raiz com o seguinte comando:

Até este ponto em nosso projeto, queremos apenas uma dependência: Flask. Portanto, podemos adicionar a seguinte linha para referenciar a versão correta do Flask que queremos para o nosso projeto:

Estamos optando pela versão do Flask version 2.0.1 como a dependência. É a versão mais recente no momento da redação deste tutorial. Você pode descobrir mais sobre as várias versões na página Flask Changes . Isso conclui a configuração da aplicação Flask. Agora vamos preparar as configurações do Docker para a implantação.

Step 2: Configure Docker

Para configurar uma implantação do Docker, criaremos dois arquivos, Dockerfile e start.sh. O Dockerfile contém linhas declarativas que compõem uma imagem Docker. O start.sh é um script shell básico para construir a imagem e iniciar o contêiner a partir do Dockerfile. Enquanto estiver no diretório raiz do projeto, execute o seguinte comando para criar o Dockerfile:

Este arquivo contém as configurações necessárias para uma imagem Docker. Em seguida, adicione o seguinte trecho de código para especificar as dependências e como construir a imagem:

A primeira linha em um Dockerfile define a imagem base a partir da qual estamos construindo nossa imagem. Neste caso, construiremos com base no tiangolo/uwsgi-nginx-flask, disponível no DockerHub. Escolhemos esta imagem específica porque ela suporta muitas versões do Python.

Também especificamos que queremos atualizar a imagem. Em seguida, precisamos adicionar o bash comando processo , o nano texto editor, e o git cliente para fazer pull e push de código-fonte de repositórios de controle de versão como GitHub, Bitbucket, ou Gitlab. As linhas com ENV especificam variáveis de ambiente a serem usadas no contêiner.

O comando COPY copia as dependências para dentro do contêiner. O comando RUN invoca o gerenciador de pacotes pip para analisar o arquivo dependencies.txt e instalar as dependências. Salve e feche o arquivo quando terminar de editar.

Em seguida, você criará o script start.sh. Este script incluirá comandos do Docker para construir e executar a imagem. Embora você possa executar esses comandos progressivamente no terminal, achamos que é mais limpo adicioná-los a um script shell e apenas invocá-lo do terminal com um único comando.

Antes de podermos definir o conteúdo deste arquivo, devemos primeiro estabelecer uma porta livre que outros serviços não estejam usando. Usaremos a porta 45644. No entanto, você pode escolher uma porta diferente. Execute a seguinte linha para verificar se a porta está livre:

Dependendo da porta que você escolheu, se a saída do comando acima for 1, então ela está livre. Caso contrário, você terá que escolher outra porta e tentar o comando novamente:

Flask application Port Check

Como estabelecemos uma porta livre, agora podemos criar o arquivo com o nano dentro do diretório raiz do projeto executando o seguinte comando:

Dentro deste arquivo, adicione o seguinte trecho de código:

A primeira linha, referida como shebang, especifica que este é um arquivo bash e deve ser executado como comandos. A segunda linha declara uma variável chamada app_name. Usamos essa variável para definir os nomes da imagem e do contêiner. A terceira linha instrui o Docker a construir a imagem com base na definição do Dockerfile no diretório atual. A imagem será chamada docker-flask-demo de acordo com a variável.

A última linha cria um contêiner chamado docker-flask-demo de acordo com a variável que definimos. A flag -d mantém o contêiner rodando em segundo plano em um estado desanexado (detached) após a execução do comando terminar. A flag -p vincula uma porta no servidor a uma porta específica no contêiner. Neste caso, estamos mapeando a porta 45644 na máquina hospedeira para a porta 80 que o Docker exporá no contêiner.

We use the -v para especificar um volume do Docker a ser montado no contêiner. A variável $PWD é uma variável padrão do Linux que contém o caminho para o diretório atual em que você está em um determinado momento:

Flask application pwd

No nosso caso, estamos montando todo o diretório do projeto no diretório /var/www do contêiner. A configuração do Docker agora está pronta. Você pode construir a imagem e iniciar o contêiner com base na imagem construída executando o seguinte comando:

Aguarde a execução do script terminar e, em seguida, execute o seguinte comando Docker para listar todos os contêineres em execução:

The output will display running containers:

Demo Docker

Você deverá ver o nosso contêiner com o nome docker-flask-demo na lista de contêineres em execução. Encontre o IP público do seu servidor e acesse-o no seu navegador na porta especificada: http://your-server-public-ip:45644.

Você deverá ver uma saída semelhante:

Flask App Running

Se você vir o que está acima no seu navegador, significa que implantou com sucesso uma aplicação Flask. Em seguida, modificaremos arquivos e serviremos conteúdo aos usuários por meio de templates.

Passo 3: Servir Conteúdo por meio de Arquivos de Template

No Flask, Templates são usados para exibir conteúdo estático e dinâmico aos visitantes do site. Mostraremos como criar um template HTML e servi-lo aos seus usuários quando eles visitarem uma determinada rota. Por exemplo, pode ser uma página Inicial (Home) ou uma página Sobre (About).

Execute o seguinte comando no seu terminal para criar um arquivo index.html no diretório app/templates :

Em seguida, adicione o seguinte trecho de código ao arquivo:

Salve e feche o arquivo quando terminar. Além disso, crie outra página, vamos chamá-la de página Sobre (About), com o seguinte comando:

Adicione o seguinte trecho de código ao arquivo:

Salve e feche o arquivo quando terminar. Em seguida, modifique o arquivo app/views.py para referenciar os templates, bem como as rotas para as páginas reais:

Modifique o arquivo para que ele fique assim:

Salve e feche o arquivo quando terminar. As alterações feitas não entrarão em vigor até que você pare e reinicie o contêiner. Execute os seguintes comandos do Docker para parar e iniciar o contêiner. Anote o nome do contêiner conforme definimos anteriormente:

Assim que o contêiner estiver ativo e em execução, visite a página inicial e a página Sobre para ver alguns dos novos conteúdos:

Flask application Index

 Flask application 1

Até agora, você criou um aplicativo Flask que pode servir conteúdo para os visitantes do seu site. Aqui está a estrutura de arquivos do projeto:

File Structure

Você provavelmente notou que tivemos que reiniciar o contêiner Docker para que ele aplicasse as novas alterações. Na próxima etapa, automatizaremos isso para garantir menos tempo de inatividade.

Etapa 4: Configurar as Atualizações dos Arquivos do Aplicativo para Recarregar Automaticamente

Frequentemente fazemos alterações em um aplicativo, para melhorar a lógica, as interfaces de usuário ou adicionar algumas dependências. Para que tais alterações entrem em vigor, pode ser necessário reiniciar o contêiner Docker. Felizmente, uWSGI tem um recurso chamado touch-reload para recarregar um script Python sem reiniciar o contêiner.

Pronto para uso, o Python possui um recurso de auto--recarregamento que monitora todo o sistema de arquivos em busca de alterações e atualiza o aplicativo quando ocorre uma alteração. Embora o recarregamento automático seja bom para minimizar o tempo de inatividade, ele pode consumir muitos recursos. Portanto, não é recomendado para ambientes de produção.

Vejamos como você pode usar o touch-reload para monitorar alterações em um arquivo específico e recarregar o aplicativo quando houver alterações. Modifique o arquivo uwsgi.ini com o editor nano:

Adicione a linha destacada para que fique assim:

Salve e feche o arquivo quando terminar. A linha adicionada especificou um arquivo que será modificado para acionar o recarregamento do aplicativo. No entanto, para que essa condição seja ativada para modificações futuras, você deve primeiro reiniciar o contêiner:

Agora você pode modificar o arquivo app/views.py para demonstrar como funciona o recarregamento automático:

Altere a string retornada pela função home conforme destacado:

Salve e feche o arquivo assim que terminar.

Abra a página inicial do seu aplicativo no navegador: http://your-server-public-ip:45644.

Você ainda não verá nenhuma alteração. Isso ocorre porque a condição touch-reload detecta uma alteração no arquivo uwsgi.ini . Você pode usar touch para ativar a condição, recarregando assim todo o aplicativo com o seguinte comando:

Agora, se você recarregar a página inicial, verá as novas alterações exibidas:

Touch Reload

No futuro, se você fizer novas alterações, precisará apenas executar o comando sudo touch uwsgi.ini e todo o aplicativo será recarregado com menos tempo de inatividade. Isso nos traz ao final deste tutorial.

Conclusão

Neste tutorial, você implementou e implantou um aplicativo Flask com imagens e contêineres Docker. Para minimizar o tempo de inatividade, evitando a necessidade de reiniciar o contêiner, você configurou touch-reload para escutar alterações em um arquivo específico e recarregar automaticamente todo o aplicativo. Você finalmente testou tudo isso no navegador para garantir que funciona.

O Docker garante implantações mais rápidas e permite o dimensionamento fácil de aplicativos. Se você quiser saber mais sobre os vários comandos do Docker, dê uma olhada neste tutorial sobre como instalar e usar o Docker no Ubuntu.

Para mais recursos sobre o Docker em nosso blog, você pode conferir o seguinte:

Feliz Computação!

author

Pranay Kapgate

Autor · CloudSigma

Preslav Dobrev é um designer criativo na CloudSigma, focado na construção de uma identidade empresarial consistente por meio de canais de marketing tradicionais e inovadores. Ele é hábil em combinar a visão artística com o marketing estratégico para criar narrativas de marca impactantes.

Comentários

Nenhum comentário ainda. Seja o primeiro.