Voltar ao blog

Configurando o Django com PostgreSQL, Nginx e Gunicorn no Ubuntu 20.04

Configurando o Django com PostgreSQL, Nginx e Gunicorn no Ubuntu 20.04

Django é um framework de aplicativo web livre e de código aberto construído na Python linguagem de programação. O Django é super-rápido, seguro e altamente escalável. Nas mãos de um desenvolvedor experiente, o Django pode estabelecer rapidamente um site poderoso. Ele pode se integrar perfeitamente com servidores web populares (Apache, Nginx), e bancos de dados (MySQL, MariaDB, PostgreSQL, Oracle, e SQLite), etc. O Django alimenta alguns dos maiores sites do mundo, como Instagram, Mozilla e NASA. Este guia demonstra a configuração da base de um aplicativo web com a ajuda do Django com PostgreSQL, Nginx e Gunicorn no Ubuntu 20.04.

Pré-requisitos

Este guia exige que você esteja executando um servidor Ubuntu 20.04 configurado com um firewall básico e um usuário não-root com privilégios sudo. Confira este guia detalhado sobre como configurar um servidor Ubuntu. Siga este tutorial para configurar um usuário não-root com privilégios sudo. Você também pode configurar um firewall Iptables seguindo as etapas deste guia.

Instalaremos o Django dentro de um ambiente virtual. Ter um ambiente específico para o projeto permite um gerenciamento mais fácil de múltiplos projetos a partir do mesmo servidor. Assim que os bancos de dados e os aplicativos estiverem configurados, implantaremos o servidor de aplicação Gunicorn. O Gunicorn será a interface de aplicação que traduz as requisições dos clientes de HTTP para chamadas Python que nossa aplicação pode utilizar. Em seguida, implantaremos o Nginx na frente do Gunicorn para lidar com conexões de alto desempenho e recursos de segurança fáceis de implementar.

Instalando os Pacotes Necessários

Primeiro, comece instalando todos os pacotes necessários. Felizmente, todos esses pacotes estão disponíveis diretamente nos repositórios oficiais de pacotes do Ubuntu. Abra o terminal e atualize o APT cache de pacotes:

A lista de pacotes depende se a aplicação web vai usar Python 2 ou Python 3. Run o seguinte comando para instalar o Django com Python 3:

O Django 1.11 LTS é a última versão do Django que suportará o Python 2. Se você pretende usar o Django com o Python 2, instale os seguintes pacotes:

Banco de Dados e Usuário PostgreSQL

Quanto à solução de banco de dados, usaremos o PostgreSQL. É um sistema de banco de dados objeto-relacional poderoso e de código aberto. O PostgreSQL oferece confiabilidade, robustez e desempenho. Para etapas detalhadas sobre a configuração do PostgreSQL, confira este guia sobre configuração do PostgreSQL no servidor Ubuntu. Para o guia atual, configuraremos um banco de dados e um usuário dedicados para nossa aplicação Django.

Por padrão, o PostgreSQL implementa a “autenticação peer” como o esquema de autenticação para conexões locais. Em resumo, a “autenticação peer” autenticará o login se o nome de usuário do sistema operacional corresponder a um nome de usuário válido do PostgreSQL. Durante a instalação, o PostgreSQL configurou um usuário do sistema operacional postgres para corresponder ao usuário administrativo postgres do PostgreSQL. Faça login na sessão interativa do shell do PostgreSQL como postgres usando o seguinte comando:

Você entrará no prompt do PostgreSQL. O primeiro passo é criar um banco de dados dedicado para o projeto. Para demonstração, o banco de dados será nomeado viktor_project:

O próximo passo é criar um usuário dedicado para o banco de dados do projeto. O usuário deve ter um nome de usuário forte. Para demonstração, o nome de usuário será viktor_project_user:

Agora, modificaremos alguns parâmetros:

  • Certos parâmetros de conexão. Em resumo, não será necessário consultar e definir os valores corretos cada vez que uma conexão for estabelecida. Isso melhora muito o desempenho do banco de dados.
  • Codificação padrão para UTF-8. É uma codificação universal e o Django espera por ela.
  • Esquema de isolamento de transação padrão para “read committed”. Ele bloqueia a leitura de transações não confirmadas.
  • Fuso horário para UTC.

Todas essas alterações de parâmetros são recomendadas pelo próprio projeto Django. Para implementar essas alterações, execute os seguintes comandos. Não se esqueça de alterar o nome de usuário do banco de dados para o correto:

Altere o administrador do banco de dados para o usuário de banco de dados dedicado:

Nosso trabalho com o PostgreSQL está concluído por enquanto. Saia do shell interativo do PostgreSQL:

Exit the PostgreSQL interactive shell

Ambiente Virtual Python

Com o banco de dados preparado, agora podemos nos concentrar em estabelecer os demais requisitos do projeto. Para facilitar o gerenciamento, estabeleceremos um ambiente virtual e instalaremos todos os requisitos do Python nele. Para gerar um ambiente virtual, precisamos do virtualenv. Ele pode ser facilmente instalado com o pip.

Os seguintes comandos irão atualizar o pip e instalar o virtualenv. Para o Python 3, execute os seguintes comandos:

Para o Python 2, execute os seguintes comandos em vez disso:

Assim que o virtualenv estiver instalado, é hora de criar um ambiente virtual. Em seguida, crie um diretório dedicado para o ambiente virtual:

Depois disso, altere o diretório ativo atual para o diretório dedicado ao ambiente virtual:

Dentro do diretório, execute o seguinte comando. A ferramenta virtualenv criará um ambiente virtual com o nome do projeto:

Ela criará um subdiretório com o nome do projeto. O subdiretório conterá uma versão local do Python e do pip. Isso oferece flexibilidade para instalar e configurar um ambiente Python isolado para o projeto.

O seguinte comando ativará o ambiente virtual:

activate the virtual environment

O prompt do terminal mudará indicando que você está operando dentro de um ambiente virtual Python. Agora que estamos dentro do ambiente virtual, instalaremos os requisitos necessários do Python. Precisamos do Django, Gunicorn e psycopg2 (adaptador PostgreSQL). O seguinte comando instruirá o pip local a instalar os componentes:

Mesmo se você estiver usando o Python 3, pip é o comando correto. Isso ocorre porque, dentro do ambiente virtual, o pip3 é renomeado como pip.

Novo Projeto Django

Com os componentes do Python instalados, podemos começar a trabalhar com os arquivos reais do projeto Django.

  • Criando um projeto Django

O diretório do projeto já está estabelecido. Diremos ao Django para instalar seus arquivos lá. Este procedimento gerará um diretório de segundo nível contendo os códigos reais. O diretório também conterá um script de gerenciamento. O ponto principal é que estamos informando explicitamente ao Django o diretório de destino, em vez de deixá-lo decidir o diretório em relação ao atual:

O Django criará o projeto de acordo. Aqui estão alguns dos arquivos e diretórios importantes nos quais nos concentraremos. Os nomes de diretórios e arquivos são usados de acordo com a demonstração.

  • ~/viktor_project/manage.py: O script de gerenciamento de projeto do Django.
  • ~/viktor_project/viktor_project/: É o pacote que contém o projeto Django. Ele deve conter os arquivos __init__.py, settings.py, urls.py, asgi.py e wsgi.py.
  • Ajustando as configurações do projeto

Após a criação do projeto, a primeira coisa a fazer é ajustar sua configuração. Abra o settings.py em um editor de texto:

A primeira diretiva que procuramos é ALLOWED_HOSTS. Ela define os servidores ou nomes de domínio que podem se conectar à instância do Django. Se qualquer solicitação de entrada com um cabeçalho Host não corresponder à lista de ALLOWED_HOSTS, ela criará uma exceção. É recomendado pelo Django para evitar certos tipos de vulnerabilidades de segurança:

ALLOWED_HOSTS

A próxima seção na qual nos concentraremos é DATABASE. Ela gerencia o acesso ao banco de dados. Por padrão, ela contém a configuração para o mecanismo de banco de dados SQLite. No entanto, usaremos o banco de dados PostgreSQL para o projeto. O Django usará o adaptador psycopg2 para se comunicar com o PostgreSQL:

django 1

Agora, vá para o final do arquivo. Adicione as seguintes linhas para indicar o local dos arquivos estáticos. Isso ajuda o Nginx a lidar com as solicitações desses itens:

static

Nosso trabalho com settings.py está concluído por enquanto. Salve o arquivo e feche o editor.

  • Finalizando a configuração inicial do projeto

Agora podemos migrar o esquema inicial do banco de dados para o banco de dados PostgreSQL dedicado. Execute o seguinte comando:

Em seguida, precisamos criar um superusuário para o projeto. Para gerar um superusuário, execute o seguinte comando:

viktor_project

Colete todos os arquivos estáticos no local que especificamos em settings.py. Os arquivos estáticos serão coletados em um diretório separado chamado “static” sob o diretório do projeto:

Agora, precisamos mexer no firewall do servidor. Se você seguiu o guia de configuração do servidor, já deve ter o UFW configurado e ativado. Criaremos uma exceção para a porta 8000. Essa é a porta padrão que o Django usa. Consulte este guia para saber mais sobre os conceitos básicos e o uso do firewall UFW.

Em seguida, verifique a ação:

Finalmente, podemos testar o servidor em ação. Inicie o servidor de desenvolvimento do Django:

Se a configuração for bem-sucedida, o servidor de desenvolvimento do Django deverá iniciar e aceitar solicitações de entrada. Abra um navegador e acesse o IP/domínio do seu servidor na porta 8000:

django 2

Você deve cair na página inicial padrão do Django. Para acessar o painel de administração, adicione /admin ao final da URL. O painel de administração só é acessível pelo superusuário que criamos anteriormente:

Após fazer o login, você chegará à interface padrão de administração do Django:

django 3

Terminamos os testes por enquanto. Para parar o servidor, pressione “Ctrl + C” na janela do terminal.

  • Testando o Gunicorn

Antes de sair do ambiente virtual, queremos garantir que o Gunicorn possa servir as aplicações. A maneira de testar isso é usando o Gunicorn para carregar o módulo WSGI do projeto.

O comando Gunicorn está localizado dentro do diretório do projeto:

Isso iniciará o Gunicorn na mesma interface em que o Django estava rodando. Podemos testar o aplicativo novamente a partir de um navegador web normal. Observe que a interface de administração não terá nenhum estilo aplicado porque o Gunicorn ainda não sabe como encontrar os conteúdos CSS estáticos:

Quando terminar, pressione “Ctrl + C” na janela do terminal para parar o servidor Gunicorn.

  • Saindo do ambiente virtual

A configuração da aplicação Django está concluída. Execute o seguinte comando para sair do ambiente virtual:

Arquivos de Socket e Serviço do Gunicorn

Verificamos que o Gunicorn pode interagir com a aplicação Django. No entanto, precisamos de uma maneira mais robusta de gerenciar o servidor de aplicação. É aqui que o systemd entra na equação. O systemd é um dos sistemas de inicialização mais populares disponíveis no Linux. Aqui está um guia detalhado sobre como gerenciar serviços e unidades do systemd.

Podemos criar arquivos de socket e de serviço para o Gunicorn para permitir que o systemd o gerencie como se fosse um serviço. Na inicialização, o socket do Gunicorn será gerado. O socket escutará as conexões de entrada. Quando uma conexão ocorrer, o systemd iniciará os processos do Gunicorn para lidar com a conexão.

  • Socket do Gunicorn

Vamos começar criando um socket do Gunicorn. O arquivo precisa ser criado com privilégios de sudo:

Insira o seguinte código dentro do arquivo:

Como você pode ver, existem três seções no código.

  • [Unit]: Esta seção descreve o socket.
  • [Socket]: Ela define a localização do socket.
  • [Install]: Esta parte garante que o systemd crie o socket no momento certo.

Salve o arquivo e feche o editor.

  • Serviço do Gunicorn

Em seguida, criaremos um arquivo de serviço para o Gunicorn. Semelhante ao arquivo de socket, ele também deve ser criado com privilégios de sudo:

Insira o seguinte código:

O código contém várias seções:

  • [Unit]: Esta seção especifica metadados e dependências. Ela também descreve a inicialização apenas após o destino de rede ser alcançado.
  • [Service]: Esta seção especifica o usuário e o grupo sob os quais o processo será executado. A propriedade do grupo é definida como “www-data” para que o Nginx possa se comunicar com o Gunicorn. Ela também mapeia os diretórios de trabalho e especifica os comandos de inicialização.
  • [Install]: Esta seção informa ao systemd a que vincular este serviço se ele estiver ativado na inicialização. Ele deve iniciar após o sistema multiusuário regular começar a funcionar.

Em seguida, salve o arquivo e feche o editor.

  • Ativando o socket do Gunicorn

O socket do Gunicorn está pronto para uso. Portanto, você pode executar os seguintes comandos. Ele iniciará e ativará o socket. O arquivo de socket será criado em /run/gunicorn.sock na inicialização. Quando uma conexão for feita ao socket, o systemd iniciará o serviço Gunicorn para lidar com ela:

Verifique o status do socket do Gunicorn:

Agora, verifique a existência do arquivo de socket:

Se o status do systemctl indicar um erro ou o arquivo gunicorn.sock não for encontrado, isso indica que o socket não foi criado corretamente. Verifique o log detalhado para obter pistas:

gunicorn.socket

Não se esqueça de dar outra olhada no gunicorn.socket arquivo para possíveis erros.

  • Ativação do socket

Nós iniciamos o gunicorn.socket até agora. No entanto, sem qualquer solicitação de conexão, o gunicorn.service não será ativado. Em seguida, verifique o status do Gunicorn:

Podemos testar o mecanismo de ativação do socket enviando uma solicitação de conexão usando curl:

Você deve obter uma saída HTML da aplicação. Isso indica que o Gunicorn foi iniciado com sucesso e foi capaz de servir a aplicação Django. Verifique o status atual do serviço Gunicorn:

Se houver algum comportamento ou saída inesperada (indicando um erro), verifique os logs detalhados para obter pistas:

Se foram feitas alterações no arquivo gunicorn.service, você precisará recarregar o daemon para ler novamente a definição do serviço. Isso também requer reiniciar o serviço Gunicorn:

Configurando o Nginx

Agora, vamos configurar o Nginx para passar o tráfego de entrada para o processo. Primeiro, crie um novo bloco de servidor no Nginx:

Em seguida, insira o seguinte código:

 

Aqui estão vários blocos na configuração:

  • serviço: Este bloco define que o servidor deve escutar normalmente na porta 80 e deve responder ao nome de domínio ou endereço IP do servidor.
  • location: Esta é a primeira entrada de localização. Ela define onde encontrar os arquivos estáticos.
  • location: Esta é a segunda entrada de localização. Este bloco define os parâmetros padrão de proxy e como passar o tráfego para o socket do Gunicorn.

Salve o arquivo e feche o editor. Vincule o arquivo ao diretório “sites-enabled” para ativar:

Depois disso, teste se há algum erro de sintaxe na configuração do Nginx:

Se você não encontrou nenhum erro, reinicie o Nginx para implementar a alteração:

Precisamos modificar as regras do UFW novamente. Não precisamos mais de acesso ao servidor de desenvolvimento, então podemos remover a exceção para a porta 8000. Além disso, queremos abrir a porta 80 para o tráfego normal:

Verifique essas alterações nas regras do firewall:

O servidor agora deve estar acessível a partir de um navegador web normal.

Procedimentos de Solução de Problemas

Se todas as etapas foram seguidas corretamente, a aplicação Django deve estar acessível via internet. Se não estiver, isso indica que a instalação não ocorreu como planejado. Precisamos investigar para descobrir a origem do problema.

  • Nginx mostrando a página padrão

Se o Nginx estiver exibindo a página padrão em vez do proxy da aplicação, isso geralmente significa que o server_name foi configurado incorretamente no bloco do servidor.

Neste exemplo, o bloco do servidor está armazenado no seguinte local:

A entrada server_name determina qual bloco de servidor o Nginx usará para responder às requisições. Se estiver exibindo a página padrão, provavelmente o Nginx não conseguiu associar a requisição a um bloco de servidor explícito, então ele está recorrendo ao bloco padrão:

Verifique se o bloco de servidor do seu projeto Django possui um server_name.

  • 502 Bad Gateway

O erro 502 indica que o Nginx não conseguiu fazer o proxy da requisição com sucesso. Há uma ampla gama de possíveis problemas de configuração que podem levar ao erro 502, por isso precisamos de pistas para solucionar o problema adequadamente.

A principal fonte de pistas são os logs de erro do Nginx. Geralmente, eles darão indícios sobre as condições que causaram os problemas durante o proxy. Verifique o log de erros do Nginx usando o seguinte comando:

Assim que o log abrir, tente acessar o servidor mais uma vez. Isso deve gerar uma nova mensagem de erro no log. Isso pode ajudar a restringir o problema. Aqui estão algumas mensagens possíveis:

  • connect() to unix:/run/gunicorn.sock failed (2: No such file or directory)

Isso indica que o Nginx não conseguiu encontrar o gunicorn.sock no local definido na configuração. O local é descrito pela proxy_pass diretiva sob o bloco do site. Verifique se proxy_pass indica o local correto do gunicorn.sock gerado pela unidade systemd gunicorn.socket:

Se o gunicorn.sock não foi encontrado sob o diretório /run, isso significa que o systemd não conseguiu gerá-lo. Você deve verificar novamente as etapas de configuração do arquivo de socket do Gunicorn.

  • connect() to unix:/run/gunicorn.sock failed (13: Permission denied)

Isso indica que o Nginx não conseguiu se conectar ao socket do Gunicorn devido a problemas de permissão. Isso pode acontecer se o processo foi executado como usuário root em vez de um usuário sudo. Embora o systemd tenha gerado o gunicorn.sock com sucesso, o Nginx não consegue usá-lo.

Um possível culpado pode ser permissões limitadas entre o diretório raiz (/) e o arquivo gunicorn.sock. Verifique a permissão e a propriedade do arquivo de socket e de cada um de seus diretórios pai:

A primeira coluna descreve a permissão do arquivo. A segunda coluna descreve o usuário proprietário e a terceira coluna o grupo proprietário. Se qualquer um dos diretórios que levam ao gunicorn.sock não tiver as permissões adequadas de leitura e execução, o Nginx não conseguirá acessar o socket.

  • Django exibindo “could not connect to the server: Connection refused”

Isso indica que o Django não conseguiu se conectar ao servidor PostgreSQL. Certifique-se de que o servidor PostgreSQL está ativo e em execução:

Se não estiver em execução, execute os seguintes comandos para iniciá-lo e ativá-lo:

sudo systemctl enable postgresql

Se você ainda estiver enfrentando esse erro, certifique-se de que as credenciais do banco de dados estejam definidas corretamente em settings.py:

Mais resoluções de problemas

Para resoluções de problemas adicionais, existem vários logs configurados. Esses logs podem ajudar a identificar as origens dos problemas.

Aqui está uma lista de logs que podem ajudar:

  • Logs do Nginx
  • Logs de acesso - Nginx
  • Logs de erro - Nginx
  •  Logs do aplicativo - Gunicorn
  •  Logs de socket - Gunicorn
Após fazer qualquer atualização na configuração ou no aplicativo, pode ser necessário reiniciar os processos para aplicar as alterações. Se o aplicativo Django foi atualizado, reinicie o processo do Gunicorn para carregar as alterações:
Caso sejam feitas alterações nos arquivos de socket ou de serviço do Gunicorn, recarregue o daemon e reinicie os processos:
Se forem feitas alterações na configuração do bloco de servidor do Nginx, ela deve ser testada antes de ser colocada em prática. Também é necessário reiniciar o Nginx:

Considerações Finais

Este guia demonstra com sucesso como estabelecer as bases do Django. O Django fornece muitos dos componentes comuns de uma aplicação web, permitindo que você se concentre nos elementos exclusivos. O projeto Django operará dentro do ambiente virtual. O Gunicorn gerencia a comunicação entre as solicitações do cliente e o Django. Por fim, o Nginx atua como um proxy reverso para lidar com as conexões dos clientes.

Boa computação!

author

Hark Labs

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.