AWS

26 nov, 2014

Docker de aplicação web em Python

Publicidade

Há algumas semanas a Elastic Beanstalk anunciou o suporte para a implementação e gerenciamento de containers Docker na nuvem AWS. Neste artigo, vamos descrever como fazer o dock de um aplicativo simples de formulário web, originalmente escrito para o ambiente Elastic Beanstalk Python.

Sobre o aplicativo

Desenvolvemos e divulgamos o aplicativo há alguns meses. Há uma série de vídeos em quatro partes e um post que detalha o uso do DynamoDB e do SNS com o app. Neste artigo, faremos uma análise em 4 fases sobre como o aplicativo roda com o Docker e o Elastic Beanstalk.

Código fonte para referência

O código fonte para a aplicação Python original (ou seja, sem o dock) está disponível no GitHub (no ramo principal). A versão “Dockerized” está no ramo docker.

E se você preferir o código e comparativos para blogar a respeito, confira a visualização disponível no GitHub para comparar as diferenças entre esses dois ramos. Verifique os arquivos adicionados e cada linha alterada em Dockerize neste exemplo.

Fase 1: Adição de um Dockerfile

Vamos começar analisando o código fonte do GitHub:

gt; git clone git@github.com:awslabs/eb-py-flask-signup.git
gt; cd eb-py-flask-signup
gt; git checkout master

Analisando os conteúdos do diretório, vemos que este é um aplicativo web simples escrito em Python, que usa o framework Flask, o Boto para interagir com o DynamoDB e o SNS, e algumas outras dependências declaradas no arquivo requirements.txt.

Em seguida, criamos um Dockerfile que irá construir uma imagem adequada para executar esta aplicação. O Dockerfile fica no diretório com o restante da fonte do aplicativo (ou seja, ao lado de requirements.txt, application.py etc):

FROM ubuntu:12.10
 
# Install Python Setuptools
RUN apt-get install -y python-setuptools
 
# Install pip
RUN easy_install pip
 
# Add and install Python modules
ADD requirements.txt /src/requirements.txt
RUN cd /src; pip install -r requirements.txt
 
# Bundle app source
ADD . /src
 
# Expose
EXPOSE 5000
 
# Run
CMD ["python", "/src/application.py"]

Fase 2: Testes locais

Embora este aplicativo exija uma tabela DynamoDB e o tópico SNS para ser totalmente funcional, podemos testá-lo sem eles:

Em primeiro lugar, construa a imagem Docker:

gt; docker build -t eb-py-sample .

Por último, execute um container a partir da imagem (mapeando a porta 5000 do container para a porta de host 8080, e defina algumas env vars discutidas abaixo):

gt; docker run -d \
-e APP_CONFIG=application.config.example \
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
-p 8080:5000 \
eb-py-sample

No OS X podemos abrir http://localhost:8080 e lá está o app!

local_app

Sidebar: Usamos as opções – e para passar adiante algumas variáveis de ambiente:

  1. APP_CONFIG: O aplicativo requer esta variável de ambiente para apontar para o arquivo de configuração. Apontamos para o arquivo de configuração padrão que vem com o aplicativo. Você poderia criar uma tabela DynamoDB e um tópico SNS e adicioná-los a este arquivo conf para fazer o app funcionar perfeitamente em um env dev local.
  2. AWS_ACCESS_KEY_ID e AWS_SECRET_ACCESS_KEY: O aplicativo usa o Boto para se conectar ao DynamoDB e ao SNS, e o Boto usa essas variáveis de ambiente para assinar as requisições para esses serviços. Isso vale apenas para o dev local. Quando implementarmos a Elastic Beanstalk usaremos o IAM Roles.

Fase 3: Modificar .ebextensions

Nosso aplicativo possui um diretório “especial.ebextensions” com um arquivo setup.config. Usamos o arquivo para informar ao Elastic Beanstalk que este deve criar a tabela DynamoDB e ao tópico SNS nossas necessidades de aplicativo, e também para criar um arquivo de configuração do app – /var/app/app.config – que inclui os nomes da tabela DynamoDB e o tópico SNS que acabou de ser criado.

O arquivo também detalha algumas coisas específicas ao tipo de ambiente Python (ao contrário do Docker) no Elastic Beanstalk. Precisamos remover os bits agora:

Modifique o membro files para remover as chaves owner e group para que se pareçam com:

files:
"/var/app/app.config":
mode: "000444"
content: |
AWS_REGION = '`{ "Ref" : "AWS::Region"}`'
STARTUP_SIGNUP_TABLE = '`{ "Ref" : "StartupSignupsTable"}`'
NEW_SIGNUP_TOPIC = '`{ "Ref" : "NewSignupTopic"}`'

Modifique option_settings para remover mapeamento estático de arquivos para que se pareça com:

option_settings:
"aws:elasticbeanstalk:customoption":
"AlarmEmail" : "nobody@amazon.com"
"aws:elasticbeanstalk:application:environment":
"APP_CONFIG": "/var/app/app.config"
"FLASK_DEBUG": "false"
"THEME": "flatly"

Confira o artigo anterior para mais informações sobre setup.config, ou consulte setup.config do Dockerized no GitHub

Fase 4: Implementação do Elastic Beanstalk

Já construímos e testamos o container localmente, removemos algumas .ebextensions que eram específicas do ambiente Elastic Beanstalk Python, e agora estamos prontos para implementá-lo com confiança!

Criamos um arquivo chamado Dockerrun.aws.json no mesmo lugar em que criamos o Dockerfile. Este arquivo informará ao Elastic Beanstalk como deve executar o container Docker e se parece com isso (veja o quadro abaixo para mais detalhes sobre este arquivo):

"AWSEBDockerrunVersion": "1",
"Volumes": [
{
"ContainerDirectory": "/var/app",
"HostDirectory": "/var/app"
}
],
"Logging": "/var/eb_log"
}

Sidebar sobre o Dockerrun.aws.json:

O membro Volumes irá mapear /var/app na instância EC2 de /var/app no container. Isso permite que o aplicativo em execução no container do Docker acesse o arquivo app.config criado por .ebextensions/setup.config. O membro Logging indica ao Elastic Beanstalk que nosso aplicativo Dockerized irá gravar logs em /var/eb_log no container. Beanstalk puxará automaticamente os logs a partir deste diretório sempre que o usuário clicar em Snapshot Logs no console, ou se ativar a rotação automática de log.

Vamos comitar as alterações e usar o git archive para fazer um zip para implementar a Elastic Beanstalk (você pode usar a ferramenta zip ou Finder ou ainda Windows Explorer para obter o mesmo):

gt; git add Docker* && git commit -am "Dockerized"
gt; git archive --format=zip HEAD > eb-py-flask-signup.zip

E então implementamos o zip via Elastic Beanstalk Management Console.

app_deploying

Quando nosso ambiente estiver verde, poderemos, é claro, acessá-lo e verificar se funciona:

deployed_app
Também faremos um snapshot dos logs do ambiente:

logs-1024x640

Referências

***

Artigo escrito por Jonathan Fritz, Senior Product Manager da Amazon EMR.

Este artigo faz parte do AWSHUB, rede de profissionais AWS gerenciado pelo iMasters.