Nota: esta é uma tradução da minha postagem (em inglês), descrevendo a implementação do servidor de comentários usado no mesmo site em que o original está localizado.
Versão TL; DR: Desenvolvi a configuração do servidor Commento, que é fácil e simplesmente implementada no modo semiautomático. Copie este repositório para você do GitHub e siga as instruções no README .
Há algum tempo, eu queria irresistivelmente mudar o Disqus - que é talvez o sistema mais comum para adicionar comentários às páginas - para um Commento gratuito e aberto.
O problema com o Disqus, como muitos outros produtos "gratuitos", é que, nesse caso, o produto é o usuário - ou seja, você. Além disso, o Disqus “enriquece” todas as páginas em que é usado com megabytes de scripts e mais de cem solicitações HTTP adicionais.
Além disso, sua versão gratuita mostra anúncios dos quais você pode pagar "apenas" por US $ 9 por mês (plano Plus). Isso por si só é suficiente para querer encontrar algo melhor.
Em algum momento, me deparei com este post e descobri a existência de um servidor de comentários gratuito chamado Commento . Por uma coincidência de sorte, o Commento recentemente se tornou completamente aberto - antes de estar disponível em duas versões, Comunidade gratuita e Empresa comercial. Graças ao seu desenvolvedor Adhityaa Chandrasekar.
O Commento tem ordens de magnitude mais eficientes que o Disqus, o tamanho típico da carga adicional é de cerca de 11 KB , além dos próprios comentários, é claro. Aproximadamente a mesma situação com as solicitações HTTP necessárias.
Outra vantagem do servidor Commento é que ele é muito rápido, como está escrito em Go.
Bem, como uma cereja no bolo, ele tem uma importação de comentários do Disqus, com o que mais ele poderia sonhar?
Para usuários não avançados (tecnicamente), o Commento possui um serviço de nuvem pronto para uso no commento.io . O autor oferece a você a escolha da taxa mensal, mas ela não pode ser inferior a US $ 3 "por razões técnicas".
O Sr. Chandrasekar também oferece generosamente uma conta gratuita no Commento.io em troca de "patches não triviais" para o produto.
Bem, eu escolhi a terceira opção: aumentar o servidor Commento. Nesse caso, você não depende de ninguém (além do hoster, é claro), e eu amo a independência.
Dificuldades
Sou um grande fã dos contêineres do Docker e também uso frequentemente o Docker Compose , uma ferramenta para gerenciar grupos de vários contêineres relacionados. O Commento possui uma imagem do Docker pronta para uso no registro de contêiner do GitLab.
Portanto, a decisão de usar contêineres amadureceu por si só - mas primeiro algumas coisas tiveram que ser decididas.
Dificuldade Nº 1: PostgreSQL
O Commento requer uma versão bastante recente do servidor PostgreSQL, infelizmente nenhum outro servidor SQL é suportado.
Bem, ainda executamos tudo em contêineres, então é bem simples.
Dificuldade # 2: Não há suporte para HTTPS
O Commento em si é um servidor da Web, mas suporta apenas o protocolo HTTP inseguro.
Deve-se notar que essa prática é bastante comum atualmente: nesse caso, o servidor está oculto atrás do proxy reverso , que também executa a descarga de SSL. O fato é que o suporte a SSL / HTTPS é absolutamente obrigatório nesse caso, afinal de contas, no pátio de 2019 e procurar tentativas de autorizar um usuário usando um protocolo de Internet inseguro será muito distorcido.
Decidi usar o servidor Nginx ; primeiro, tive uma experiência considerável trabalhando com ele; segundo, é muito rápido, econômico e estável. E publica as versões oficiais das imagens do Docker .
O segundo ingrediente na receita HTTPS é o certificado SSL para o domínio. Sou eternamente grato à EFF e à Mozilla por criar a Let's Encrypt Certificate Authority , que emite milhões de certificados gratuitos todos os meses.
O Let's Encrypt também fornece um utilitário de linha de comando gratuito chamado certbot , que simplifica bastante o processo de obtenção e atualização de um certificado. Bem, e - é claro - uma imagem do Docker para ele!
Dificuldade # 3: Problema do ovo de galinha Certbot
Mas esse truque é mais complicado.
Queremos nos referir ao certificado SSL na configuração de nosso proxy reverso no Nginx, o que significa que, sem um certificado, ele simplesmente se recusa a iniciar. Ao mesmo tempo, para obter um certificado SSL para um domínio, você precisa de um servidor HTTP que funcione, o Let's Encrypt irá provar sua propriedade desse domínio.
Consegui resolver esse problema e, ao que me parece, com bastante elegância:
- Primeiro, é gerado um certificado inválido e fictício, cujo único objetivo é permitir que o Nginx inicie.
- Nginx e certbot recebem em conjunto um novo certificado agora válido.
- Assim que o certificado é recebido, o certbot entra em "modo de espera", acordando a cada 12 horas para verificar se precisa ser atualizado - de acordo com as recomendações do Let's Encrypt.
- Quando chegar o momento e o certificado for renovado, o certbot sinalizará ao Nginx para reiniciar.
Dificuldade nº 4: algo deve ser preservado
Suspeito fortemente que você deseja que os comentários do usuário sejam salvos após uma reinicialização ou atualização do sistema.
Além disso, para que o Let's Encrypt não o bane devido a solicitações muito frequentes, seria bom manter os certificados recebidos por toda a data de validade.
Ambos os pontos foram resolvidos na configuração proposta usando os volumes do Docker, criados automaticamente pelo systemd quando o Commento foi lançado. Como os volumes são marcados como "externos", o Docker os ignora ao remover contêineres usando docker-compose down -v
.
Junte tudo
Agora você pode ver como tudo funciona juntos.
A figura abaixo mostra a interação e o tráfego entre os quatro contêineres:

Eu apliquei a opção depends_on
Docker Compose depends_on
para garantir que os contêineres iniciem na ordem correta.
Se você deseja iniciar apenas seu próprio servidor Commento, pode pular o restante do artigo e ir diretamente para o código no GitHub .
Bem, falarei mais sobre essa implementação em mais detalhes posteriormente.
Como tudo isso funciona
Redigir arquivo
Como você pode ver na figura acima, minha “composição” consiste em quatro serviços:
certbot
- utilitário certbot
da EFFnginx
- proxy reverso implementando descarregamento de SSLapp
- servidor Commentopostgres
- banco de dados PostgreSQL
O docker-compose.yml
contém declarações de sua própria rede Docker, chamada commento_network
, e três volumes, dos quais dois são externos (ou seja, devem ser criados fora do Compose):
commento_postgres_volume
armazena dados do servidor PostgreSQL para o Commento: usuários, moderadores, comentários, etc.certbot_etc_volume
contém certificados recebidos pelo certbot
.
Nginx
O contêiner Nginx é baseado em uma imagem oficial leve baseada no Alpine e usa o seguinte script para executar:
- Linha 3 ( ARRGHHH, Habr não suporta a exibição de números de linha no código - aprox. Transl. ) Um manipulador de interrupção é registrado para que o Nginx e o processo de monitoramento em segundo plano concluam com êxito o trabalho quando o contêiner para.
- A linha 27 chama a função de espera, que interrompe o processo de inicialização do Nginx até que os arquivos de configuração SSL criados pelo contêiner
certbot
. Sem isso, o Nginx se recusaria a começar. - A linha 30 cria um processo em segundo plano que regularmente, a cada dez segundos, verifica a presença de um arquivo de sinalizador chamado
.nginx-reload
e, assim que é detectado, instrui o Nginx a recarregar a configuração. Este arquivo também cria o certbot quando o certificado é atualizado. - A linha 34 inicia o Nginx no modo normal. Nesse caso,
exec
significa que o processo atual do shell é substituído pelo processo Nginx.
Outro arquivo importante nesta imagem é a configuração do servidor virtual Commento, que força o Nginx a encaminhar solicitações HTTPS para o contêiner do commento
:
server { listen [::]:443 ssl ipv6only=on; listen 443 ssl; server_tokens off; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name __DOMAIN__; location / { proxy_pass http://app:8080/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ssl_certificate /etc/letsencrypt/live/__DOMAIN__/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/__DOMAIN__/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } server { listen 80 default_server; listen [::]:80 default_server; server_tokens off; server_name __DOMAIN__; location /.well-known/acme-challenge/ { root /var/www/certbot; }
O primeiro bloco do servidor (linhas 1-21 ) descreve como trabalhar com HTTPS e a regra de encaminhamento. É aqui que os arquivos do certificado Let's Encrypt são mencionados (ou stubs usados).
O domínio atendido pelo servidor é passado como argumento ao criar a imagem; ele substitui a linha __DOMAIN__
na configuração do servidor.
O segundo bloco (linhas 23-38 ) é a configuração do servidor HTTP, que é usada pelo certbot para confirmar a propriedade do domínio (o chamado "desafio da ACME"). Todos os outros pedidos causam um redirecionamento para o endereço correspondente via HTTPS.
certbot
Nossa imagem certbot é baseada na compilação oficial com o seguinte script:
Um breve tour por suas linhas:
- A linha 3 , como no script anterior, é necessária para a conclusão regular do contêiner.
- As linhas 17-19 verificam as variáveis necessárias.
- E nas linhas 22-25 - que os diretórios necessários para que o certbot funcione sejam montados corretamente.
- O garfo segue:
- As linhas 30-50 são executadas apenas no primeiro início do contêiner:
- Um certificado fictício é copiado, permitindo que o Nginx inicie normalmente.
- Enquanto isso, o Nginx aguarda o final desse processo, após o qual continua o download.
- Depois que o Nginx é iniciado, o certbot inicia o processo de obtenção de um certificado válido no Let's Encrypt.
- E, finalmente, assim que o certificado é recebido, o arquivo
.nginx-reload
é criado, sugerindo ao Nginx que é hora de recarregar a configuração.
- A linha 54 aguarda o início do Nginx - no caso em que um certificado completo já esteja disponível.
- Depois de tudo isso (linhas 58-63 ), ele continua o ciclo, uma vez a cada 12 horas, verificando a necessidade de renovar o certificado e sinalizando ao Nginx para reiniciar.
Os contêineres do app
e do postgres
usam as imagens originais fornecidas pelos desenvolvedores sem nenhuma alteração.
Serviço Systemd
A última parte deste quebra-cabeça é o arquivo da unidade systemd commento.service
, no qual você precisa criar um link simbólico em /etc/systemd/system/commento.service
para que ele inicie em um bom momento quando o sistema for iniciado:
[Unit] Description=Commento server [Service] TimeoutStopSec=30 WorkingDirectory=/opt/commento ExecStartPre=-/usr/bin/docker volume create commento_postgres_volume ExecStartPre=-/usr/bin/docker volume create certbot_etc_volume ExecStartPre=-/usr/local/bin/docker-compose -p commento down -v ExecStart=/usr/local/bin/docker-compose -p commento up --abort-on-container-exit ExecStop=/usr/local/bin/docker-compose -p commento down -v [Install] WantedBy=multi-user.target
Linhas:
- A linha 6 implica que o código do projeto é clonado no diretório
/opt/commento
- isso é muito mais simples. - As linhas 7-8 criam volumes externos, se ainda não estiverem.
- Na linha 9 , os possíveis restos dos contêineres anteriores são excluídos. Os volumes externos são preservados.
- A linha 10 marca o lançamento real do Docker Compose. O
--abort-on-container-exit
todo o bando de contêineres quando algum deles é --abort-on-container-exit
. Graças a isso, o systemd estará ciente de que o serviço está parado. - A linha 11 está novamente limpando e excluindo contêineres, redes e volumes.
Código fonte
Uma implementação totalmente funcional, exigindo apenas a configuração de variáveis no docker-compose.yml
, está disponível no GitHub . Você só precisa seguir cuidadosamente as etapas descritas em README .
O código está sujeito à licença MIT .
Obrigado por ler neste lugar, os comentários são freneticamente bem-vindos!