Seguindo a lista do modelo 12factor, temos “Vínculos de portas” como sétima boa prática.
É comum encontrar aplicações que são executadas dentro de contêineres de servidores web, tais como Tomcat ou Jboss. Normalmente, essas aplicações são implantadas dentro desses serviços para que possam ser acessadas pelos usuários externamente.
Essa boa prática sugere que o aplicativo em questão seja autocontido e dependa de um servidor de aplicação, tal como Jboss, Tomcat e afins. O software sozinho deve exportar um serviço HTTP e lidar com as requisições que chegarem por ele. Isso quer dizer que nenhuma aplicação adicional deveria ser necessária para que seu código possa estar disponível para comunicação externa.
Tradicionalmente, a implantação de aplicações em serviços de aplicação web, tal como Tomcat e Jboss, exigem que seja gerado um artefato e ele deve ser enviado para o serviço web em questão, mas, no modelo de contêiner Docker, a ideia é que o artefato do processo de implantação seja o próprio contêiner em si.
O processo antigo de implantação do artefato em um servidor de aplicação normalmente não tinha um retorno rápido, e isso aumentava demasiadamente o processo de implantação de um serviço, pois cada alteração demandava enviar o artefato para o serviço de aplicação web, sendo que este tinha como responsabilidade de importar, ler e executar o novo artefato.
Usar Docker facilmente torna a aplicação autocontida. Já construímos um Dockerfile que descreve tudo que a aplicação precisa:
FROM python:2.7 ADD requirements.txt requirements.txt RUN pip install -r requirements.txt ADD . /code WORKDIR /code CMD python app.py EXPOSE 5000
As dependências estão descritas no arquivo requirements.txt e os dados que devem ser persistidos são geridos por um serviço externo (serviços de apoio) à aplicação.
Outro detalhe desta boa prática é que a aplicação deve exportar o serviço através da vinculação a uma única porta. Como podemos ver no código exemplo, a porta padrão do python (5000) é iniciada, mas você pode escolher outra, caso julgue necessário. Segue o recorte do código que trata desse assunto:
if __name__ == "__main__": app.run(host="0.0.0.0", debug=True)
Essa porta 5000 pode ser utilizada para servir dados localmente em um ambiente de desenvolvimento ou através de um proxy reverso quando for migrada para produção, com um nome de domínio adequado à aplicação em questão.
Utilizar esse modelo de vinculação de portas torna o processo de atualização de aplicação mais fluído, uma vez que, na utilização de um proxy reverso inteligente, é possível adicionar novos nós gradativamente com a nova versão e remover os antigos à medida que as versões atualizadas estão sendo executadas em paralelo.
Convém salientar que mesmo que o Docker permite a utilização de mais de uma porta por contêineres. Essa boa prática é enfática ao afirmar que você só deve utilizar uma porta vinculada por aplicação.