{"id":3251,"date":"2017-12-19T10:19:07","date_gmt":"2017-12-19T12:19:07","guid":{"rendered":"https:\/\/blog.umbler.com\/?p=3251"},"modified":"2018-12-05T09:28:11","modified_gmt":"2018-12-05T11:28:11","slug":"containers-3-como-containerizar-aplicacoes","status":"publish","type":"post","link":"https:\/\/blog.umbler.com\/br\/containers-3-como-containerizar-aplicacoes\/","title":{"rendered":"Containers #3: Como containerizar aplica\u00e7\u00f5es"},"content":{"rendered":"<p>Acharam que iam se livrar de mim n\u00e9? est\u00e3o muito enganados :). Voc\u00ea j\u00e1 sabe tudo sobre <a href=\"https:\/\/blog.umbler.com\/br\/containers-101-como-essa-tecnologia-pode-alavancar-suas-aplicacoes\/\">de onde vieram<\/a> os containers, j\u00e1 sabe <a href=\"https:\/\/blog.umbler.com\/br\/containers-102-primeiros-passos-para-realizar-a-instalacao\/\">como instalar<\/a> a plataforma mais completa de containers, o <a href=\"https:\/\/www.docker.com\/\">Docker<\/a> e hoje voc\u00ea entender\u00e1 como \u00e9 poss\u00edvel pegar aquela sua aplica\u00e7\u00e3o e colocar em um container ;).<\/p>\n<p>Bom, vamos come\u00e7ar por um ponto bem importante: Qual a melhor forma de fazer isso? Existem algumas formas. Umas melhores, outras piores, outras bem inusitadas, mas o que veremos \u00e9 a mais tradicional, que \u00e9 utilizando o Dockerfile. Por\u00e9m, antes precisamos saber o que \u00e9 o Dockerfile. Vamos l\u00e1!<\/p>\n<h2>O Dockerfile<\/h2>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"aligncenter size-medium\" src=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/giphy.gif\" width=\"275\" height=\"252\" \/><br \/>\nDe modo simples o Dockerfile \u00e9 um arquivo de texto descritivo de como deve ser seu ambiente para executar a sua aplica\u00e7\u00e3o. Ou seja, \u00e9 nele que voc\u00ea descreve quais pacotes precisam ser instalados, quais vers\u00f5es, etc.<\/p>\n<p>\u00c9 claro que voc\u00ea deve prestar aten\u00e7\u00e3o em alguns detalhes de como criar o Dockerfile, por exemplo. Voc\u00ea deve sempre se basear em uma imagem Docker j\u00e1 existente, outro ponto \u00e9 que quanto mais instru\u00e7\u00f5es seu Dockerfile tiver, mais camadas a imagem ter\u00e1 e possivelmente ser\u00e1 maior tamb\u00e9m. Abaixo te trago um exemplo bem simples de um Dockerfile para uma aplica\u00e7\u00e3o em Java:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\" data-line=\"2\"><code class=\"language-bash\"># Herda de uma imagem base.\r\nFROM dockerfile\/ubuntu\r\n# Instala o java e suas depend\u00eancias\r\nRUN \\\r\n \u00a0apt-get update &amp;&amp; \\\r\n \u00a0apt-get install -y openjdk-8-jdk &amp;&amp; \\\r\n \u00a0rm -rf \/var\/lib\/apt\/lists\/*\r\n# Define diret\u00f3rio onde estar\u00e1 sua aplica\u00e7\u00e3o\r\nWORKDIR \/data\r\n# Define a variavelJAVA_HOME \r\nENV JAVA_HOME \/usr\/lib\/jvm\/java-8-openjdk-amd64\r\n# Define comando de inicializa\u00e7\u00e3o do container\r\nCMD [\"bash\"]\r\n<\/code><\/pre>\n<p>Esse pequeno trecho de c\u00f3digo \u00e9 o suficiente para que possamos criar nossa pr\u00f3pria imagem Docker, para que com ela seja poss\u00edvel executar os nossos containers. Note que os comandos que a\u00ed est\u00e3o s\u00e3o exatamente os mesmos que devem ser executados em um host Linux tradicional para a instala\u00e7\u00e3o do Java, bem simples n\u00e3o \u00e9 mesmo?<\/p>\n<h2>A Imagem<\/h2>\n<p><a href=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/1241995827.png\"><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/1241995827-300x284.png\" alt=\"\" width=\"300\" height=\"284\" \/><\/a><br \/>\nCerto, j\u00e1 sabemos o que \u00e9 o Dockerfile, mas afinal, para que ele serve? A resposta \u00e9 simples: Serve para gerar uma imagem, que nada mais \u00e9 do que um \u201cartefato\u201d que ser\u00e1 utilizado como base para a execu\u00e7\u00e3o de seus containers. Uma imagem possui diversas camadas, e como mencionado acima, elas s\u00e3o originadas pelas instru\u00e7\u00f5es utilizadas no Dockerfile.<\/p>\n<p>Por padr\u00e3o, todas as camadas, exceto a mais superficial, s\u00e3o readonly, ou seja, n\u00e3o podem ser sobrescritas, isso facilita e \u00e9 o que torna as imagens t\u00e3o vers\u00e1teis, pois essas camadas podem ser reutilizadas em mais de uma imagem, bem loco n\u00e9? Veja na imagem abaixo como \u00e9 a estrutura de uma imagem:<br \/>\n<a href=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/docker-filesystems-multilayer.png\"><img decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/docker-filesystems-multilayer-300x225.png\" alt=\"\" width=\"300\" height=\"225\" \/><\/a><br \/>\nNote que todo container executa utilizando uma imagem, no entanto, como apenas a camada mais superficial (a que o container visualiza) pode ser escrita, \u00e9 poss\u00edvel utilizar essa mesma imagem para v\u00e1rios containers, pois a \u00fanica camada de escrita sempre ser\u00e1 diferente para cada container.<\/p>\n<h2>Unindo as coisas &#8211; Node.JS<\/h2>\n<p><a href=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/node-docker-logo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/node-docker-logo.png\" alt=\"\" width=\"500\" height=\"241\" \/><\/a><br \/>\nJ\u00e1 sabemos o que \u00e9 o Dockerfile e para que ele serve, j\u00e1 sabemos que o resultado do Dockerfile \u00e9 uma imagem, e sabemos para o que ela serve tamb\u00e9m, agora basta juntarmos essas duas informa\u00e7\u00f5es para criar nossas pr\u00f3prias imagens e executar nossos containers onde precisarmos.<\/p>\n<p>Vamos come\u00e7ar com algo simples, agora \u00e9 o momento de criarmos nossa imagem para nossa aplica\u00e7\u00e3o em node \\o\/.\u00a0O primeiro passo \u00e9 criarmos nosso Dockerfile, veja o exemplo abaixo:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\" data-line=\"2\">\r\n<code class=\"language-bash\">FROM node:8\r\n WORKDIR \/usr\/src\/app\r\n COPY package*.json .\/\r\n RUN npm install\r\n COPY . .\r\n EXPOSE 3000\r\n CMD [ \"npm\", \"start\" ]\r\n<\/code>\r\n<\/pre>\n<p>Em seguida, vamos montar a nossa aplica\u00e7\u00e3o, para isso vamos criar um arquivo chamado package.json com o seguinte conte\u00fado:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\" data-line=\"2\">\r\n<code class=\"language-bash\">{\r\n  \u00a0\"name\": \"umbler_web_app\",\r\n  \u00a0\"version\": \"1.0.0\",\r\n  \u00a0\"description\": \"Node.js no Docker\",\r\n  \u00a0\"main\": \"server.js\",\r\n  \u00a0\"scripts\": {\r\n  \u00a0\u00a0\u00a0\"start\": \"node server.js\"\r\n  \u00a0},\r\n  \u00a0\"dependencies\": {\r\n  \u00a0\u00a0\u00a0\"express\": \"^4.16.1\"\r\n  \u00a0}\r\n }\r\n<\/code>\r\n<\/pre>\n<p>O package.json serve para declarar as depend\u00eancias de nossa aplica\u00e7\u00e3o node. Assim \u00e9 poss\u00edvel definir algumas a\u00e7\u00f5es, por exemplo, como a aplica\u00e7\u00e3o deve ser inicializada.<br \/>\nO pr\u00f3ximo passo \u00e9 criar um arquivo, que vamos cham\u00e1-lo de server.js e adicionar o seguinte conte\u00fado:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\" data-line=\"2\">\r\n<code class=\"language-bash\">'use strict';\r\n const express = require('express');\r\n const PORT = 3000;\r\n const HOST = '0.0.0.0';\r\n const app = express();\r\n app.get('\/', (req, res) =&gt; {\r\n  \u00a0res.send('Ola mundo\\n');\r\n })\r\n app.listen(PORT, HOST);\r\n console.log(`Running on https:\/\/${HOST}:${PORT}`);\r\n<\/code>\r\n<\/pre>\n<p>Ok, lembre de criar todos os \u00a0arquivos no mesmo diret\u00f3rio, em seguida vamos executar um comando que gerar\u00e1 a imagem. Execute:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\">\r\n<code class=\"language-bash\">$docker build -t \u201cmeu-node\u201d<\/code><\/pre>\n<p>Note que este comando executar\u00e1 as instru\u00e7\u00f5es do Dockerfile passo-a-passo e, no caso de estar tudo certo, ele criar\u00e1 uma nova imagem chamada meu-node. Para visualizar a imagem voc\u00ea deve executar:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\"><code class=\"language-bash\">$docker images<\/code><\/pre>\n<p>Veja que aparecer\u00e1 essa imagem e mais uma imagem denominada node, com a tag 8, que como voc\u00ea pode ter notado \u00e9 a imagem base utilizada pelo nosso Dockerfile.<\/p>\n<blockquote><p>Certo Cristiano, como eu sei que isso ir\u00e1 funcionar?<\/p><\/blockquote>\n<p>Simples, vamos criar nossos containers. \ud83d\ude09<br \/>\nPara isso, precisamos executar o seguinte comando:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\">\r\n<code class=\"language-bash\">$docker run -d --name app1 -p 3000:300 meu-node<\/code><\/pre>\n<p>Dessa forma, se voc\u00ea acessar: <a href=\"https:\/\/ip-do-host:3000\">https:\/\/ip-do-host:3000<\/a> voc\u00ea visualizar\u00e1 a aplica\u00e7\u00e3o node que criamos.<\/p>\n<p>Para criar mais containers, basta voc\u00ea executar o mesmo comando, mudando apenas a porta exposta, visto que uma porta TCP pode ser utilizada apenas uma vez, fa\u00e7a isso mudando o primeiro atributo do par\u00e2metro -p.<\/p>\n<h2>Unindo as coisas &#8211; MongoDB<\/h2>\n<p><a href=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/center-image.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter\" src=\"https:\/\/blog.umbler.com\/wp-content\/uploads\/2017\/12\/center-image.png\" alt=\"\" width=\"640\" height=\"400\" \/><\/a><br \/>\nJ\u00e1 fizemos nossa aplica\u00e7\u00e3o em node.js executar em container, criamos uma imagem para isso, agora vamos seguir a mesma l\u00f3gica para containerizar o MongoDB.<\/p>\n<p>Precisamos cuidar um detalhe. Como sabemos, \u00e9 muito importante que os dados de um banco de dados nunca sejam perdidos, n\u00e3o \u00e9 mesmo? Para isso, quando voc\u00ea utilizar Docker para executar seu banco de dados, lembre-se de mapear uma pasta no host para onde ser\u00e3o salvos os dados que devem ser persistidos. Vamos entender melhor mais adiante.<\/p>\n<p>Diferentemente de nossa aplica\u00e7\u00e3o node, n\u00e3o precisamos criar uma imagem espec\u00edfica para mongodb, necessariamente (a n\u00e3o ser \u00e9 claro que voc\u00ea possua algo muito particular), podemos utilizar a imagem oficial que existe no hub do Docker. Antes, vamos preparar o ambiente, para isso:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\">\r\n<code class=\"language-bash\">$mkdir ~\/data<\/code><\/pre>\n<p>Dessa forma criamos uma pasta na home do usu\u00e1rio chamada \u201cdata\u201d onde ser\u00e3o armazenados os dados do mongo, que ser\u00e3o persistidos, para que n\u00e3o sejam perdidos caso o container morra. Em seguida, vamos criar o container de mongo:<\/p>\n<pre class=\"code-highlighter line-numbers theme-dark\">\r\n<code class=\"language-bash\">$docker run -d --name mongodb -p 27017:27017 -v ~\/data:\/data\/db mongo<\/code><\/pre>\n<p>Note que neste comando temos um par\u00e2metro novo, que \u00e9 o -v, que serve para realizar o mapeamento de um diret\u00f3rio do host para o container. Com isso, os dados salvos dentro desse diret\u00f3rio no container ser\u00e3o persistidos no host. Ou seja, caso o container morra, basta subir outro container de mongo mapeando o mesmo diret\u00f3rio.<\/p>\n<p>Outro ponto importante: no exemplo acima n\u00e3o tratamos a quest\u00e3o de autentica\u00e7\u00e3o para acesso ao banco de dados. Ou seja, N\u00c3O use essa forma em produ\u00e7\u00e3o, ok?<\/p>\n<blockquote><p>Ahh, mas eu quero saber como a imagem de mongo foi feita.<\/p><\/blockquote>\n<p>N\u00e3o tem problema, voc\u00ea pode acessar este <a href=\"https:\/\/github.com\/docker-library\/mongo\/blob\/c9a1b066a0f35f679c2f8e1854a21e025867d938\/3.0\/Dockerfile\">link<\/a> e ler o Dockerfile utilizado para gerar essa imagem \ud83d\ude09<\/p>\n<h2>Unindo as coisas &#8211; Node.JS + MongoDB<\/h2>\n<p>Sabendo como subir os dois ambientes, \u00e9 poss\u00edvel fazer com que os mesmos se comuniquem. Ou seja, que a aplica\u00e7\u00e3o em node se conecte como banco mongo, para fazer isso \u00e9 simples. Obviamente voc\u00ea deve adicionar em seu package.json algum driver de acesso ao banco mongo (normalmente mongoose). Ap\u00f3s isso, basta voc\u00ea editar a connection string para acessar o nome do container de mongo ou at\u00e9 mesmo o ip do host na porta do mongo, 27017.<\/p>\n<p>Assim sua aplica\u00e7\u00e3o node conseguir\u00e1 acessar o banco mongo, isso tudo sem precisar instalar o framework, servi\u00e7o do banco de dados, etc. \u00c9 necess\u00e1rio apenas ter o Docker instalado.<br \/>\nExiste ainda uma forma mais f\u00e1cil de ter esse ambiente, que \u00e9 utilizando o Docker Compose, mas isso \u00e9 assunto para um pr\u00f3ximo post \ud83d\ude42<\/p>\n<p>Por hora, \u00e9 isso que gostaria de apresentar. Qualquer coisa comenta a\u00ed que vamos conversando, ok?<\/p>\n<p>Abra\u00e7o!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Acharam que iam se livrar de mim n\u00e9? est\u00e3o muito enganados :). Voc\u00ea j\u00e1 sabe tudo sobre de onde vieram os containers, j\u00e1 sabe como instalar a plataforma mais completa de containers, o Docker e hoje voc\u00ea entender\u00e1 como \u00e9 poss\u00edvel pegar aquela sua aplica\u00e7\u00e3o e colocar em um container ;). Bom, vamos come\u00e7ar por [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":5229,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[279,280,277,256],"class_list":["post-3251","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dev","tag-containers","tag-docker","tag-mongodb","tag-node-js"],"_links":{"self":[{"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/posts\/3251"}],"collection":[{"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/comments?post=3251"}],"version-history":[{"count":0,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/posts\/3251\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/media\/5229"}],"wp:attachment":[{"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/media?parent=3251"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/categories?post=3251"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.umbler.com\/br\/wp-json\/wp\/v2\/tags?post=3251"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}