Como utilizar a plataforma Heroku para deploy de aplicações
Heroku é atualmente uma das melhores opções PaaS ( Plataform as a Service ) para desenvolvedores fazerem o deploy de suas aplicações. Essa plataforma é muito utilizada nas startups porque facilita muito o gerenciamento de infraestrutura, monitoração de disco, cpu, memória e entre outros.
Nesse post vou mostrar como utilizo essa plataforma para fazer o deploy dos meus projetos pessoais em ambientes production-like.
A preparação
O código fonte da aplicação está publicado no link abaixo:
https://github.com/Responsus/TerminusNG
Essa aplicação é uma versão um pouco melhorada do meu tcc da faculdade, que foi um sistema para gerenciamento de projetos. Inicialmente esse sistema foi escrito com um framework chamado Pyramid e nessa nova versão foi escrita com o microframework Flask.
O Heroku possui vários planos que podem ser usados, eu uso o plano free, que disponibiliza um container com apenas 1 Worker e desliga após 30 minutos de inatividade, que é o suficiente para testar aplicações em ambientes não produção.
Todos os planos estão disponíveis no link abaixo:
https://www.heroku.com/pricing
Crie sua primeira aplicação
Agora, o primeiro passo é criar uma conta no Heroku.
https://signup.heroku.com/login
Após a sua conta criada, crie um novo app, clicando no botão New no topo da página conforme a imagem abaixo:
Ao criar o novo app, dê um nome único a ele.
Após a criação do seu app, você será redirecionado para uma outra página e nela clique em Settings, logo abaixo você encontrará um link para o seu repositório no Heroku, salve esse link que será usado mais a frente.
Instalação do client Heroku
Agora é necessário instalar o heroku-cli na máquina para publicar o projeto.
Nesse link temos todos os links para download em vários sistemas operacionais.
https://devcenter.heroku.com/articles/heroku-cli
Eu instalei a versão para windows, então os exemplos que vou usar em diante serão digitados usando o Windows Powershell.
Abaixo uma lista dos comandos disponíveis para o Heroku-cli.
PS C:\Users\1511 MXTI\Documents> heroku --help Usage: heroku COMMAND Help topics, type heroku help TOPIC for more details: access manage user access to apps addons tools and services for developing, extending, and operating your app apps manage apps auth heroku authentication authorizations OAuth authorizations buildpacks manage the buildpacks for an app certs a topic for the ssl plugin ci run an application test suite on Heroku clients OAuth clients on the platform config manage app config vars container Use containers to build and deploy Heroku apps domains manage the domains for an app drains list all log drains features manage optional features git manage local git repository for app keys manage ssh keys labs experimental features local run heroku app locally logs display recent log output maintenance manage maintenance mode for an app members manage organization members notifications display notifications orgs manage organizations pg manage postgresql databases pipelines manage collections of apps in pipelines plugins manage plugins ps manage dynos (dynos, workers) redis manage heroku redis instances regions list available regions releases manage app releases run run a one-off process inside a Heroku dyno sessions OAuth sessions spaces manage heroku private spaces status status of the Heroku platform teams manage teams update update CLI webhooks setup HTTP notifications of app activity
Primeiro vou fazer o git clone da aplicação.
PS C:\Users\1511 MXTI> git clone https://github.com/Responsus/TerminusNG.git Cloning into 'TerminusNG'... remote: Counting objects: 816, done. remote: Compressing objects: 100% (23/23), done. remote: Total 816 (delta 14), reused 21 (delta 10), pack-reused 783 Receiving objects: 100% (816/816), 4.21 MiB | 422.00 KiB/s, done. Resolving deltas: 100% (130/130), done. PS C:\Users\1511 MXTI>
Com a aplicação já clonada, entrei no diretório e fiz o login do heroku:
PS C:\Users\1511 MXTI> cd .\TerminusNG\ PS C:\Users\1511 MXTI\TerminusNG> heroku login Enter your Heroku credentials: Email: alisson.copyleft@gmail.com Password: ***************** Logged in as alisson.copyleft@gmail.com PS C:\Users\1511 MXTI\TerminusNG>
Agora adicione o repositório copiado do heroku nos passos anteriores.
PS C:\Users\1511 MXTI\TerminusNG> git remote add heroku https://git.heroku.com/alissonmachado.git PS C:\Users\1511 MXTI\TerminusNG>
Após adicionado o heroku como remote, foi feito um push para esse repositório:
PS C:\Users\1511 MXTI\TerminusNG> git add --all PS C:\Users\1511 MXTI\TerminusNG> git commit -m "deploy heroku" On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean PS C:\Users\1511 MXTI\TerminusNG> git push heroku Counting objects: 816, done. Delta compression using up to 8 threads. Compressing objects: 100% (645/645), done. Writing objects: 100% (816/816), 4.21 MiB | 59.00 KiB/s, done. Total 816 (delta 130), reused 816 (delta 130)
A saida do comando será parecida com essa:
remote: Compressing source files... done. remote: Building source: remote: remote: -----> Python app detected remote: -----> Installing python-3.6.4 remote: -----> Installing pip remote: -----> Installing requirements with pip remote: Collecting Flask (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading Flask-0.12.2-py2.py3-none-any.whl (83kB) remote: Collecting Flask_SQLAlchemy (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 2)) remote: Downloading Flask_SQLAlchemy-2.3.2-py2.py3-none-any.whl remote: Collecting gunicorn (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 3)) remote: Downloading gunicorn-19.7.1-py2.py3-none-any.whl (111kB) remote: Collecting flask-security (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask_Security-3.0.0-py2.py3-none-any.whl (68kB) remote: Collecting flask-mongoengine (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 5)) remote: Downloading flask-mongoengine-0.9.3.tar.gz (111kB) remote: Collecting bcrypt (from -r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 6)) remote: Downloading bcrypt-3.1.4-cp36-cp36m-manylinux1_x86_64.whl (54kB) remote: Collecting itsdangerous>=0.21 (from Flask->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading itsdangerous-0.24.tar.gz (46kB) remote: Collecting click>=2.0 (from Flask->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading click-6.7-py2.py3-none-any.whl (71kB) remote: Collecting Jinja2>=2.4 (from Flask->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading Jinja2-2.10-py2.py3-none-any.whl (126kB) remote: Collecting Werkzeug>=0.7 (from Flask->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading Werkzeug-0.14.1-py2.py3-none-any.whl (322kB) remote: Collecting SQLAlchemy>=0.8.0 (from Flask_SQLAlchemy->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 2)) remote: Downloading SQLAlchemy-1.2.0.tar.gz (5.5MB) remote: Collecting passlib>=1.7 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading passlib-1.7.1-py2.py3-none-any.whl (498kB) remote: Collecting Flask-Login>=0.3.0 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask-Login-0.4.1.tar.gz remote: Collecting Flask-Mail>=0.7.3 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask-Mail-0.9.1.tar.gz (45kB) remote: Collecting Flask-Principal>=0.3.3 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask-Principal-0.4.0.tar.gz remote: Collecting Flask-BabelEx>=0.9.3 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask-BabelEx-0.9.3.tar.gz (41kB) remote: Collecting Flask-WTF>=0.13.1 (from flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Flask_WTF-0.14.2-py2.py3-none-any.whl remote: Collecting mongoengine>=0.8.0 (from flask-mongoengine->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 5)) remote: Downloading mongoengine-0.15.0.tar.gz (144kB) remote: Collecting six (from flask-mongoengine->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 5)) remote: Downloading six-1.11.0-py2.py3-none-any.whl remote: Collecting cffi>=1.1 (from bcrypt->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 6)) remote: Downloading cffi-1.11.3-cp36-cp36m-manylinux1_x86_64.whl (420kB) remote: Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->Flask->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 1)) remote: Downloading MarkupSafe-1.0.tar.gz remote: Collecting blinker (from Flask-Mail>=0.7.3->flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading blinker-1.4.tar.gz (111kB) remote: Collecting Babel>=1.0 (from Flask-BabelEx>=0.9.3->flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading Babel-2.5.1-py2.py3-none-any.whl (6.8MB) remote: Collecting speaklater>=1.2 (from Flask-BabelEx>=0.9.3->flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading speaklater-1.3.tar.gz remote: Collecting WTForms (from Flask-WTF>=0.13.1->flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading WTForms-2.1.zip (553kB) remote: Collecting pymongo>=2.7.1 (from mongoengine>=0.8.0->flask-mongoengine->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 5)) remote: Downloading pymongo-3.6.0-cp36-cp36m-manylinux1_x86_64.whl (378kB) remote: Collecting pycparser (from cffi>=1.1->bcrypt->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 6)) remote: Downloading pycparser-2.18.tar.gz (245kB) remote: Collecting pytz>=0a (from Babel>=1.0->Flask-BabelEx>=0.9.3->flask-security->-r /tmp/build_f5fec0d0c01ac466add1d2bf054ac08c/requirements.txt (line 4)) remote: Downloading pytz-2017.3-py2.py3-none-any.whl (511kB) remote: Installing collected packages: itsdangerous, click, MarkupSafe, Jinja2, Werkzeug, Flask, SQLAlchemy, Flask-SQLAlchemy, gunicorn, passlib, Flask-Login, blinker, Flask-Mail, Flask-Principal, pytz, Babel, speaklater, Flask-BabelEx, WTForms, Flask-WTF, flask-security, pymongo, six, mongoengine, flask-mongoengine, pycparser, cffi, bcrypt remote: Running setup.py install for itsdangerous: started remote: Running setup.py install for itsdangerous: finished with status 'done' remote: Running setup.py install for MarkupSafe: started remote: Running setup.py install for MarkupSafe: finished with status 'done' remote: Running setup.py install for SQLAlchemy: started remote: Running setup.py install for SQLAlchemy: finished with status 'done' remote: Running setup.py install for Flask-Login: started remote: Running setup.py install for Flask-Login: finished with status 'done' remote: Running setup.py install for blinker: started remote: Running setup.py install for blinker: finished with status 'done' remote: Running setup.py install for Flask-Mail: started remote: Running setup.py install for Flask-Mail: finished with status 'done' remote: Running setup.py install for Flask-Principal: started remote: Running setup.py install for Flask-Principal: finished with status 'done' remote: Running setup.py install for speaklater: started remote: Running setup.py install for speaklater: finished with status 'done' remote: Running setup.py install for Flask-BabelEx: started remote: Running setup.py install for Flask-BabelEx: finished with status 'done' remote: Running setup.py install for WTForms: started remote: Running setup.py install for WTForms: finished with status 'done' remote: Running setup.py install for mongoengine: started remote: Running setup.py install for mongoengine: finished with status 'done' remote: Running setup.py install for flask-mongoengine: started remote: Running setup.py install for flask-mongoengine: finished with status 'done' remote: Running setup.py install for pycparser: started remote: Running setup.py install for pycparser: finished with status 'done' remote: Successfully installed Babel-2.5.1 Flask-0.12.2 Flask-BabelEx-0.9.3 Flask-Login-0.4.1 Flask-Mail-0.9.1 Flask-Principal-0.4.0 Flask-SQLAlchemy-2.3.2 Flask-WTF-0.14.2 Jinja2-2.10 MarkupSafe-1.0 SQLAlchemy-1.2.0 WTForms-2.1 Werkzeug-0.14.1 bcrypt-3.1.4 blinker-1.4 cffi-1.11.3 click-6.7 flask-mongoengine-0.9.3 flask-security-3.0.0 gunicorn-19.7.1 itsdangerous-0.24 mongoengine-0.15.0 passlib-1.7.1 pycparser-2.18 pymongo-3.6.0 pytz-2017.3 six-1.11.0 speaklater-1.3 remote: remote: -----> Discovering process types remote: Procfile declares types -> web remote: remote: -----> Compressing... remote: Done: 58.4M remote: -----> Launching... remote: Released v3
O log acima, mostra todo o processo de instalação de dependências para que seja criado o container e seja feito o deploy da aplicação, mas o mais importante é o final do log que aparecerá similiar ao mostrado abaixo:
remote: -----> Launching... remote: Released v3 remote: https://alissonmachado.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done.
Foi retornado a seguinte url: https://alissonmachado.herokuapp.com/.
E pronto, agora é só acessar a aplicação que já estará funcionando.
Mas como foi feito o deploy?
Ao se fazer uma aplicação que será publicada no heroku, ela já deve ser construída pensada em heroku, assim como qualquer outra plataforma DevOps que faz o deploy em containers.
Dentro do repositório existe um arquivo chamado Procfile: https://github.com/Responsus/TerminusNG/blob/master/Procfile , nesse arquivo é definido qual é o processo que deve ser iniciado, que no nosso caso é o servidor Web gunicorn e ele vai iniciar p arquivo app.py que é o principal da aplicação.
Outro ponto importante é deixar o arquivo requirements.txt: https://github.com/Responsus/TerminusNG/blob/master/requirements.txt, sempre atualizado, pois ele também faz a instalação do gunicorn que é o servidor de aplicação que é usado durante o deploy.
E acho que é isso ai, qualquer coisa é só mandar um salve (=
About author
Você pode gostar também
Descubra como a estratégia DevOps pode transformar sua empresa
DevOps é um termo que tem ganhado destaque no mundo corporativo. Considerado uma poderosa estratégia, surgiu da necessidade de agilizar entregas na área de tecnologia da informação, sempre buscando ações
Como montar seu próprio Registry Privado com Harbor
Hoje, no blog da 4Linux, sobre Registry Privado e em como montar o nosso com o Harbor. O que é um Registry Quando falamos de contêineres, sabemos que para ele
Domine o Ansible: Aprenda a provisionar e configurar sua infraestrutura na nuvem
Introdução O Ansible é uma ferramenta extremamente poderosa, podendo fazer todo a orquestração da sua infraestrutura. Porém, o que mais me chama atenção nele, é que podemos provisionar todo nosso