{"id":21593,"date":"2016-06-15T10:00:37","date_gmt":"2016-06-15T13:00:37","guid":{"rendered":"https:\/\/blog.locaweb.com.br\/?p=21593"},"modified":"2022-08-31T16:53:36","modified_gmt":"2022-08-31T19:53:36","slug":"como-o-docker-me-ajudou-nao-dizer-na-minha-maquina-funciona","status":"publish","type":"post","link":"https:\/\/www.locaweb.com.br\/blog\/temas\/codigo-aberto\/como-o-docker-me-ajudou-nao-dizer-na-minha-maquina-funciona\/","title":{"rendered":"Como o Docker me ajudou a n\u00e3o dizer: &#8220;Na minha m\u00e1quina funciona&#8221;"},"content":{"rendered":"<p>Ol\u00e1, no post de hoje iremos falar um pouco sobre <a href=\"https:\/\/www.docker.com\/what-docker\" target=\"_blank\" rel=\"noopener noreferrer\">docker<\/a>, e como utiliz\u00e1-lo em seu ambiente de desenvolvimento. Se voc\u00ea est\u00e1 iniciando sua carreira, talvez n\u00e3o tenha ainda presenciado a <del datetime=\"2016-06-08T15:22:06+00:00\">treta<\/del> discuss\u00e3o de um <strong>SysAdmin VS Desenvolvedor<\/strong> por conta do: <em>\u2018Na minha m\u00e1quina funciona&#8217;<\/em>, referente \u00e0 uma aplica\u00e7\u00e3o ou patch que foi desenvolvida(o) localmente, mas quando aplicado ao ambiente de produ\u00e7\u00e3o n\u00e3o apresentou o comportamento esperado.<\/p>\n<p><a href=\"http:\/\/blog.locaweb.com.br\/wp-content\/uploads\/2016\/06\/pa.jpg\"><img decoding=\"async\" class=\"alignnone wp-image-21594\" src=\"http:\/\/blog.locaweb.com.br\/wp-content\/uploads\/2016\/06\/pa-300x290.jpg\" alt=\"pa\" width=\"940\" height=\"909\" \/><\/a><\/p>\n<p>Resolvi falar sobre o assunto ap\u00f3s vivenciar o seguinte cen\u00e1rio: Estava trabalhando em um projeto e desenvolvendo-o localmente, tudo lindo e maravilhoso, at\u00e9 eu precisar disponibilizar um MVP para a equipe. Diante deste quadro, resolvi subir uma m\u00e1quina de testes\/dev (m\u00e1quina esta, que mais tarde viria a ser com certeza a maquina de produ\u00e7\u00e3o!) e fazer o deploy da aplica\u00e7\u00e3o. Em resumo:<\/p>\n<ol>\n<li>Criei uma m\u00e1quina virtual no nosso ambiente<\/li>\n<li>Fiz um scp do c\u00f3digo fonte para este servidor<\/li>\n<li>Coloquei a APP para rodar<\/li>\n<li>A galera curtiu 0\/<\/li>\n<li>Continuei todo o desenvolvimento neste servidor<\/li>\n<li>Larguei m\u00e3o de versionamento, CI e qualquer outra boa pr\u00e1tica.<\/li>\n<\/ol>\n<p><a href=\"http:\/\/blog.locaweb.com.br\/wp-content\/uploads\/2016\/06\/deploy.jpg\"><img decoding=\"async\" class=\"aligncenter wp-image-21595\" src=\"http:\/\/blog.locaweb.com.br\/wp-content\/uploads\/2016\/06\/deploy-300x225.jpg\" alt=\"deploy\" width=\"940\" height=\"705\" \/><\/a><\/p>\n<p>E isto se manteve at\u00e9 eu conversar com um colega de trabalho com maior experi\u00eancia, onde naquele momento, fui levado a refletir sobre algumas quest\u00f5es como:<\/p>\n<ul>\n<li>Eu conseguiria em caso de um desastre, remontar o servidor exatamente como ele est\u00e1 agora?<\/li>\n<li>A maquina precisa realmente de todas as libs para buildar c\u00f3digo?<\/li>\n<li>Quando o sistema estiver em uso, e eu precisar implementar novas features, onde vou desenvolver e testar? Visto que n\u00e3o posso simplesmente tirar o sistema do ar<\/li>\n<li>Como vai ser quando tiver mais de uma pessoa trabalhando no projeto?<\/li>\n<\/ul>\n<p>Tks <a href=\"http:\/\/pothix.com\/\">@pothix<\/a>!\u00a0Felizmente, antes que o pior pudesse acontecer, eu me dei conta de tudo isso e fui atr\u00e1s de uma solu\u00e7\u00e3o. Visto que eu n\u00e3o queria na minha m\u00e1quina local (no meu SO propriamente dito) ter a mesma stack de tecnologias que o projeto necessita e que eu j\u00e1 havia montado no servidor, lembrei de um cara chamado Docker.\u00a0Mas porque o docker?<\/p>\n<ul>\n<li>Dada a sua capacidade de isolar ambientes, eu n\u00e3o precisaria me preocupar em ter de gerenciar mais de um projeto em paralelo. Por exemplo: Ao mesmo tempo que em um container eu estou tocando minha aplica\u00e7\u00e3o atual com todas as suas depend\u00eancias na ultima vers\u00e3o, e afins, eu poderia tocar tamb\u00e9m um projeto legado, com vers\u00f5es inferiores e sem ter de me preocupar com compatibilidade ou conflitos entre vers\u00f5es.<\/li>\n<li>Tendo em vista que minha app quando publicada ir\u00e1 rodar um servidor Linux, mas para desenvolvimento eu utilizo Mac\/OSX. Com o docker eu consigo aproximar muito o meu ambiente de produ\u00e7\u00e3o do meu ambiente de desenvolvimento.<\/li>\n<li>Por que eu queria por em pratica o que aprendi no treinamento \u201c<a href=\"https:\/\/www.youtube.com\/c\/linuxtips\">Descomplicando o Dokcer<\/a>\u201d.<\/li>\n<\/ul>\n<p>Sem mais delongas, diante do problema apresentado acima eis minha solu\u00e7\u00e3o.<\/p>\n<p>Obs: Os passos abaixo, ter\u00e3o como exemplo um projeto Django\/Python e utilizando um banco de dados mysql, desta forma, teremos 2 containers que formaram nossa stack, sendo 1 para cada servi\u00e7o mencionado acima (django, mysql) . Utilizarei ent\u00e3o o <a href=\"https:\/\/docs.docker.com\/compose\/\">compose<\/a> para gerenciar e executar este ambiente. No final deste artigo, deixarei alguns links de apoio, links que tamb\u00e9m utilizei durante o processo de cria\u00e7\u00e3o.<\/p>\n<p>Bora l\u00e1:<\/p>\n<ul>\n<li>Primeiro, iniciei um novo projeto no gitlab aqui da Locaweb e \u201ccommitei&#8221; todo o c\u00f3digo fonte do meu projeto, iniciando mesmo que tardio o meu versionamento.<\/li>\n<li>Feito isso, iniciei a confec\u00e7\u00e3o do meu Dockerfile para criar a imagem com as libs que eu precisava para a aplica\u00e7\u00e3o web (django), que ficou da seguinte forma:<\/li>\n<\/ul>\n<p>[code]<br \/>\nFROM python:2.7<br \/>\nLABEL description=\u201cLerolero&quot;<br \/>\nMAINTAINER Adinan Paiva<br \/>\nWORKDIR \/app<br \/>\nADD requirements.txt requirements.txt<br \/>\nRUN pip install -r requirements.txt<br \/>\n[\/code]<\/p>\n<p>Onde:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#from\">FROM<\/a> &#8211; \u00c9 a imagem base que vou utilizar a partir do <a href=\"https:\/\/hub.docker.com\/explore\/\">docker hub<\/a> neste caso<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#label\">LABEL<\/a> &#8211; Metadatas que ser\u00e3o inseridas na imagem<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#maintainer\">MAINTAINER<\/a> &#8211; Autor\/Mantedor da imagem<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#workdir\">WORKDIR<\/a> &#8211; Define um diret\u00f3rio de trabalho, que pode ser utilizado na sequencia pelo RUN e que ser\u00e1 o diret\u00f3rio corrente para todo container inicializado a partir desta imagem.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#add\">ADD<\/a> &#8211; Adiciona um \u00a0arquivo a partir da m\u00e1quina host ou URL, ao filesystem da image que esta sendo criada.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/#run\">RUN<\/a> &#8211; Comando que ser\u00e1 executado em tempo de build da imagem.<\/li>\n<\/ul>\n<div>Na sequencia criei meu <a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/\">docker-compose.yml<\/a>, que ficou da seguinte forma:<\/div>\n<div><\/div>\n<p>[code]<br \/>\nversion: &#8216;2&#8217;<\/p>\n<p>services:<br \/>\n  db:<br \/>\n    image: mysql:5.7<br \/>\n    volumes:<br \/>\n      &#8211; \/Users\/adinanpaiva\/mysql:\/var\/lib\/mysql<br \/>\n    environment:<br \/>\n      MYSQL_ROOT_PASSWORD: senhainicial12<br \/>\n      MYSQL_DATABASE: nome_da_base<br \/>\n      MYSQL_USER: usuario<br \/>\n      MYSQL_PASSWORD: senha<\/p>\n<p>  web:<br \/>\n    build: .<br \/>\n    env_file: .env<br \/>\n    command: python manage.py runserver 0.0.0.0:8000<\/p>\n<p>    volumes:<br \/>\n      &#8211; .:\/app<br \/>\n    ports:<br \/>\n      &#8211; &quot;8000:8000&quot;<br \/>\n    extra_hosts:<br \/>\n      &#8211; \u201clala.locaweb.com.br:127.0.0.1:8000&quot;<br \/>\n    depends_on:<br \/>\n      &#8211; db<br \/>\n[\/code]<\/p>\n<p>Onde:<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#versioning\">version<\/a>\u00a0&#8211; Vers\u00e3o do formato do \u201ccompose-file&#8221;<\/li>\n<li>services &#8211; Defini\u00e7\u00e3o de cada servi\u00e7o a ser executado, neste caso web, db e celery<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#image\">image<\/a> &#8211; Define a partir de qual imagem aquele container ser\u00e1 inicializado.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#build\">build<\/a> &#8211; Cria a imagem a partir do path especificado, path este que deve ter um \u201c<a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#context\">build context<\/a>\u201d, ou seja, \u00a0um Dockerfile ou a URL para um reposit\u00f3rio git.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#volumes-volume-driver\">volumes<\/a> &#8211; Monta um diret\u00f3rio do host no container. No service <b>web<\/b> por exemplo, foi montado o diret\u00f3rio corrente do docker-composer.yml apontando para o \/app do container, isso para que eu pudesse editar meu c\u00f3digo a partir da maquina host e, n\u00e3o precisasse de um novo build a cada altera\u00e7\u00e3o no c\u00f3digo para v\u00ea-la em a\u00e7\u00e3o. J\u00e1 no service <b>db<\/b> a finalidade \u00e9 outra, fiz este mapeamento para que os dados do mysql fossem persistentes, ou seja, em caso de pane ou necessidade de desligar o ambiente eu n\u00e3o perderei os dados do meu banco.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#environment\">environment<\/a>\u00a0&#8211; Adiciona vari\u00e1veis de ambiente, que no caso do servi\u00e7o db por exemplo, s\u00e3o usadas pela imagem do mysql para um setup inicial.<\/li>\n<li>\u00a0<a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#env-file\">env_file<\/a> &#8211; Tamb\u00e9m adiciona vari\u00e1veis de ambiente, por\u00e9m, a partir de um arquivo onde seu conte\u00fado deve seguir o formato \u201cchave=valor\u201d. Cuidado, as vari\u00e1veis definidas a partir de \u201cenvironment\u201d mencionado acima, sobrep\u00f5e os valores das vari\u00e1veis de mesmo nome se configuradas tamb\u00e9m no env_file e, se voc\u00ea estiver utilizando as duas op\u00e7\u00f5es no mesmo service.<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#ports\">ports<\/a> &#8211; Portas que ser\u00e3o expostas\/&#8217;bindadas&#8217; do host \u00a0para o containe<\/li>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/#depends-on\">depends_on<\/a>\u00a0&#8211; Expressa\/relaciona depend\u00eancias entre os servi\u00e7os. Sendo assim, no nosso exemplo <i>docker-compose up<\/i> vai primeiro iniciar o servi\u00e7o db, e na sequ\u00eancia o servi\u00e7o web. Mesmo assim, \u00e9 v\u00e1lido notar que: <b>Iniciar n\u00e3o \u00e9 o mesmo que estar pronto para o uso.\u00a0<\/b><\/li>\n<\/ul>\n<p><span style=\"line-height: 1.5\">Seguindo, aqui vai nosso <a href=\"https:\/\/pip.pypa.io\/en\/stable\/user_guide\/#requirements-files\">requirements.txt<\/a> de exemplo:<\/span><\/p>\n<p>[code]<br \/>\nDjango==1.9.2<br \/>\nMySQL-python==1.2.5<br \/>\ngunicorn==19.3.0<br \/>\n[\/code]<\/p>\n<p>E aqui, nosso .env utilizado no servi\u00e7o web.<\/p>\n<p>[code]<br \/>\nDB_NAME= nome_da_base<br \/>\nDB_USER=usuario<br \/>\nDB_PASS=senha<br \/>\nDB_SERVICE=db<br \/>\nDB_PORT=3306<br \/>\n[\/code]<\/p>\n<p>Antes de seguirmos, cabe uma explica\u00e7\u00e3o para as vari\u00e1veis definidas no arquivo .env. O Django, utiliza um arquivo chamado <a href=\"https:\/\/docs.djangoproject.com\/en\/1.9\/ref\/settings\/\">settings.py<\/a> para configurar o \u2018core\u2019 do seu projeto, neste arquivo s\u00e3o definidas as apps que fazem parte do projeto, as conex\u00f5es com bancos de dados, configura\u00e7\u00f5es de timezone dentre outras tantas informa\u00e7\u00f5es. No entanto, entre o ambiente de dev e produ\u00e7\u00e3o coisas como bancos de dados, backends de autentica\u00e7\u00e3o por exemplo, iram variar, e como lidar com estas diferen\u00e7as de uma forma menos dolorosa?<\/p>\n<p>Inicialmente eu criei um novo arquivo \u201cdev_settings.py\u201d alterei o que precisava, como conex\u00e3o com o banco e no final do arquivo \u201csettings.py\u201d eu importei este arquivo, sobrescrevendo ent\u00e3o os valores.<\/p>\n<p>[code lang=&#8221;python&#8221;]<br \/>\ntry:<br \/>\n    from dev_settings import *<br \/>\nexcept:<br \/>\n    pass<br \/>\n[\/code]<\/p>\n<p>Mantive este arquivo fora do meu controle de vers\u00e3o, e zaz.. Mesmo assim, eu n\u00e3o estava satisfeito em manter dois arquivos, ent\u00e3o mais uma vez seguindo algumas dicas espertas (tks @pothix), eu passei a utilizar vari\u00e1veis de ambiente para \u201calternar\u201d entre estas diferen\u00e7as de ambiente. Encontrei este <a href=\"http:\/\/bruno.im\/2013\/may\/18\/django-stop-writing-settings-files\/\">artigo<\/a>, que mesmo sendo um pouco antigo me convenceu de que isso \u00e9 uma boa, al\u00e9m deste, tamb\u00e9m considerei as dicas do <a href=\"http:\/\/12factor.net\/\">12factor.net<\/a>, o capitulo de configura\u00e7\u00e3o diz: Store config in the environment<\/p>\n<p>Ent\u00e3o na raiz do seu projeto para \u2018buildar&#8217; as imagens e criar o site django de exemplo (caso n\u00e3o tenha o seu j\u00e1 iniciado), execute:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose run web django-admin.py startproject example .<br \/>\n[\/code]<\/p>\n<p>OK, vamos rodar isso de uma vez por todas. Antes, verifique se a esta altura sua estrutura de diret\u00f3rio se parece com isso (caso voc\u00ea esteja o caso de exemplo acima, claro!):<\/p>\n<p>.<br \/>\n\u251c\u2500\u2500 .env<br \/>\n\u251c\u2500\u2500 Dockerfile<br \/>\n\u251c\u2500\u2500 docker-compose.yml<br \/>\n\u251c\u2500\u2500 example<br \/>\n\u2502 \u251c\u2500\u2500 __init__.py<br \/>\n\u2502 \u251c\u2500\u2500 __init__.pyc<br \/>\n\u2502 \u251c\u2500\u2500 manage.py<br \/>\n\u2502 \u251c\u2500\u2500 settings.py<br \/>\n\u2502 \u251c\u2500\u2500 settings.pyc<br \/>\n\u2502 \u251c\u2500\u2500 urls.py<br \/>\n\u2502 \u251c\u2500\u2500 wsgi.py<br \/>\n\u2502 \u2514\u2500\u2500 wsgi.pyc<br \/>\n\u2514\u2500\u2500 requirements.txt<\/p>\n<p>Agora, suba o ambiente:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose up -d<br \/>\n[\/code]<\/p>\n<p>Verifique o status do seus containers:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose ps<br \/>\n[\/code]<\/p>\n<p>Opa, da pra ver os logs tamb\u00e9m com:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose logs<br \/>\n[\/code]<\/p>\n<p>Ou por service, assim:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose logs<br \/>\n[\/code]<\/p>\n<p>O Django no primeiro startup, precisa executar uma migra\u00e7\u00e3o para configurar o banco de dados, mas antes disso, certifique-se de que j\u00e1 configurou o seu settings.py para usar as vari\u00e1veis de ambiente que voc\u00ea configurou no .env. Por exemplo:<\/p>\n<p>[code lang=&#8221;python&#8221;]<br \/>\nDEBUG = bool(os.environ.get(&#8216;DEBUG&#8217;, False))<br \/>\nALLOWED_HOSTS = os.environ.get(&#8216;ALLOWED_HOSTS&#8217;, &quot;*&quot;).split()<\/p>\n<p>DATABASES = {<br \/>\n   &#8216;default&#8217;: {<br \/>\n      &#8216;ENGINE&#8217;: &#8216;django.db.backends.mysql&#8217;,<br \/>\n      &#8216;NAME&#8217;: os.environ[&#8216;DB_NAME&#8217;],<br \/>\n      &#8216;USER&#8217;: os.environ[&#8216;DB_USER&#8217;],<br \/>\n      &#8216;PASSWORD&#8217;: os.environ[&#8216;DB_PASS&#8217;],<br \/>\n      &#8216;HOST&#8217;: os.environ[&#8216;DB_SERVICE&#8217;],<br \/>\n      &#8216;PORT&#8217;: os.environ[&#8216;DB_PORT&#8217;]<br \/>\n   }<br \/>\n}<br \/>\n[\/code]<\/p>\n<p>Agora sim:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose run web python manage.py migrate<br \/>\n[\/code]<\/p>\n<p>Que tal ver o resultado no browser?<\/p>\n<p>Se tudo deu certo seguindo os passos anteriores, voc\u00ea ver\u00e1 a pagina de boas vindas do django, que \u00e9 exibida gra\u00e7as ao modo de debug estar ativado &#x1f600;<\/p>\n<p>Caso tenha absolvido as ideias e implementado em seu projeto j\u00e1 existente, teste, acredito que ter\u00e1 sucesso tamb\u00e9m.<\/p>\n<p>Quando desejar, pode parar o ambiente da seguinte forma:<\/p>\n<p>[code lang=&#8221;bash&#8221;]<br \/>\n$ docker-compose down<br \/>\n[\/code]<\/p>\n<p>Isto ir\u00e1 remover os containers criados, mas as imagens permaneceram, bem como os dados dos volumes mapeados.<\/p>\n<p>Conclus\u00e3o:<\/p>\n<p>Com o setup acima, que a primeira vista pode parecer complexo mas, se for levado em considera\u00e7\u00e3o o fator de que ser\u00e1 feito uma \u00fanica vez, deixa de parecer, eu consegui me manter organizado, organizar o projeto, proporcionar a novos DEVs que por ventura venham a participar do desenvolvimento, um setup seguro, confi\u00e1vel e pr\u00e1tico, onde em poucos minutos o cara que chegou ontem j\u00e1 estar\u00e1 \u2018codando\u2019 e contribuindo com o crescimento da aplica\u00e7\u00e3o.<\/p>\n<p>Espero que esse relato possa ser \u00fatil para quem esta iniciando n\u00e3o cometer os erros aqui mencionados, bem como, para quem j\u00e1 tem um tempo nesta jornada, mas assim como eu foi &#8220;relaxado&#8221; possa corrigir isto.<\/p>\n<p>Queria deixar claro tamb\u00e9m, que tudo que eu disse aqui \u00e9 apenas quest\u00e3o de opini\u00f5es que pude formar conversando com a galera, lendo documenta\u00e7\u00f5es e artigos da internet e que n\u00e3o \u00e9 uma verdade absoluta.\u00a0Mais uma vez, espero ter ajudado algu\u00e9m de alguma forma.<\/p>\n<p>Links de apoio:<\/p>\n<div>Tutorias:<\/div>\n<ul>\n<li><a href=\"https:\/\/docs.docker.com\/compose\/django\/\">https:\/\/docs.docker.com\/compose\/django\/<\/a><\/li>\n<li><a href=\"https:\/\/realpython.com\/blog\/python\/django-development-with-docker-compose-and-machine\/\">https:\/\/realpython.com\/blog\/python\/django-development-with-docker-compose-and-machine\/<\/a><\/li>\n<\/ul>\n<div>Documenta\u00e7\u00e3o Oficial:<\/div>\n<ul>\n<li>Dockerfile &#8211;\u00a0<a href=\"https:\/\/docs.docker.com\/engine\/reference\/builder\/\">https:\/\/docs.docker.com\/engine\/reference\/builder\/<\/a><\/li>\n<li>Compose &#8211;\u00a0<a href=\"https:\/\/docs.docker.com\/compose\/\">https:\/\/docs.docker.com\/compose\/<\/a><\/li>\n<li>Compose File &#8211;\u00a0<a href=\"https:\/\/docs.docker.com\/compose\/compose-file\/\">https:\/\/docs.docker.com\/compose\/compose-file\/<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Ol\u00e1, no post de hoje iremos falar um pouco sobre docker, e como utiliz\u00e1-lo em seu ambiente de desenvolvimento. Se voc\u00ea est\u00e1 iniciando sua carreira, talvez n\u00e3o tenha ainda presenciado a treta discuss\u00e3o de um SysAdmin VS Desenvolvedor por conta do: \u2018Na minha m\u00e1quina funciona&#8217;, referente \u00e0 uma aplica\u00e7\u00e3o ou patch que foi desenvolvida(o) localmente, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":21667,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[5],"tags":[],"class_list":["post-21593","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo-aberto"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/posts\/21593","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/comments?post=21593"}],"version-history":[{"count":1,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/posts\/21593\/revisions"}],"predecessor-version":[{"id":36493,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/posts\/21593\/revisions\/36493"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/media\/21667"}],"wp:attachment":[{"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/media?parent=21593"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/categories?post=21593"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.locaweb.com.br\/blog\/wp-json\/wp\/v2\/tags?post=21593"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}