<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>DevOps - MCU &amp; FPGA</title>
	<atom:link href="https://mcu.tec.br/tags/devops/feed/" rel="self" type="application/rss+xml" />
	<link>https://mcu.tec.br</link>
	<description>Microcontroladores &#38; FPGA</description>
	<lastBuildDate>Fri, 04 Jul 2025 20:27:55 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://mcu.tec.br/wp-content/uploads/2025/02/Robo-para-o-site-MCU.tec_.br-512x512-1-150x150.png</url>
	<title>DevOps - MCU &amp; FPGA</title>
	<link>https://mcu.tec.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Tutorial DevOps &#8211; Parte 3: Publicando sua Aplicação na Nuvem com Cloud Run</title>
		<link>https://mcu.tec.br/infraestrutura/tutorial-devops-parte-3-publicando-sua-aplicacao-na-nuvem-com-cloud-run/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tutorial-devops-parte-3-publicando-sua-aplicacao-na-nuvem-com-cloud-run</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 20:07:52 +0000</pubDate>
				<category><![CDATA[Infraestrutura]]></category>
		<category><![CDATA[Artifact Registry]]></category>
		<category><![CDATA[autenticação gcloud]]></category>
		<category><![CDATA[CI/CD Google Cloud]]></category>
		<category><![CDATA[CLI Google Cloud]]></category>
		<category><![CDATA[Cloud Build]]></category>
		<category><![CDATA[como usar o Cloud Run]]></category>
		<category><![CDATA[configuração de projeto GCP]]></category>
		<category><![CDATA[deploy de contêineres]]></category>
		<category><![CDATA[deploy na nuvem]]></category>
		<category><![CDATA[deploy serverless]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Entrega Contínua]]></category>
		<category><![CDATA[escalabilidade automática]]></category>
		<category><![CDATA[FastAPI na nuvem]]></category>
		<category><![CDATA[gcloud]]></category>
		<category><![CDATA[Google Cloud Run]]></category>
		<category><![CDATA[Integração Contínua]]></category>
		<category><![CDATA[monitoramento de logs Cloud Run]]></category>
		<category><![CDATA[publicação de APIs]]></category>
		<category><![CDATA[Tutorial DevOps]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=564</guid>

					<description><![CDATA[<p>Aprenda neste tutorial prático como publicar sua aplicação na nuvem usando Google Cloud Run, Cloud Build e Artifact Registry. Veja como realizar o deploy de contêineres de forma escalável e serverless com a CLI do gcloud.</p>
<p>The post <a href="https://mcu.tec.br/infraestrutura/tutorial-devops-parte-3-publicando-sua-aplicacao-na-nuvem-com-cloud-run/">Tutorial DevOps – Parte 3: Publicando sua Aplicação na Nuvem com Cloud Run</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introdução ao Deploy na Nuvem com Google Cloud</h2>



<p class="wp-block-paragraph">No estágio final do nosso tutorial sobre DevOps, chegamos a um dos momentos mais esperados: a publicação da aplicação em um ambiente de nuvem pública. Até aqui, aprendemos a criar uma aplicação com contêineres e rodá-la localmente. Agora, vamos expandir esse conhecimento e disponibilizar a aplicação online para que qualquer pessoa possa acessá-la por meio de um link.</p>



<p class="wp-block-paragraph">Essa etapa é fundamental na cultura DevOps, pois representa a transição entre o desenvolvimento local e a disponibilização contínua de software em ambientes reais de produção, utilizando práticas modernas de integração e entrega contínua (CI/CD). O foco é realizar o <strong>deploy da aplicação na nuvem</strong> com o suporte das ferramentas do <strong>Google Cloud Platform</strong>, sem a necessidade de configuração manual de servidores ou máquinas físicas.</p>



<p class="wp-block-paragraph">A plataforma escolhida para isso é o <strong>Cloud Run</strong>, um serviço gerenciado que permite executar contêineres de forma “serverless”, ou seja, sem a preocupação com a infraestrutura. Ele proporciona escalabilidade automática, cobrança sob demanda e simplicidade na operação. Neste ponto, o desenvolvedor pode focar no código e na experiência do usuário final, enquanto o Google Cloud se encarrega da orquestração da infraestrutura necessária para que o serviço esteja sempre disponível.</p>



<h2 class="wp-block-heading">Criando o Projeto no Google Cloud e Instalando a CLI <code>gcloud</code></h2>



<p class="wp-block-paragraph">Para que possamos utilizar os recursos do Google Cloud, o primeiro passo prático é <strong>criar um projeto</strong> dentro da plataforma. No contexto do Google Cloud, um projeto funciona como um contêiner lógico que organiza todos os recursos relacionados à sua aplicação, como APIs, autenticações, serviços e permissões.</p>



<p class="wp-block-paragraph">Ao acessar o console do Google Cloud, podemos criar um novo projeto clicando no seletor de projeto, próximo ao canto superior da tela, e em seguida na opção <strong>&#8220;Novo Projeto&#8221;</strong>. O nome do projeto deve seguir convenções específicas: não pode conter espaços e deve, preferencialmente, usar hifens (ex: <code>tutorial-devops-api</code>). Após a criação, é necessário garantir que estamos trabalhando dentro desse novo contexto — selecionando o projeto recém-criado na lista de projetos disponíveis.</p>



<p class="wp-block-paragraph">Com o projeto criado, precisamos instalar a <strong>CLI <code>gcloud</code> (Google Cloud SDK)</strong>. Essa ferramenta de linha de comando permite interagir com a conta do Google Cloud diretamente do terminal, automatizando tarefas como deploys, configurações de serviços e autenticações. O instalador está disponível para <strong>Windows, macOS e Linux</strong>, com passos simples que incluem: baixar o executável, aceitar os termos de uso e seguir o processo de instalação (&#8220;Next&#8221;, &#8220;Next&#8221;, &#8220;Finish&#8221;).</p>



<p class="wp-block-paragraph">Faça o download conforme sua plataforma:</p>



<figure class="wp-block-table"><table class="has-fixed-layout"><thead><tr><th>Platform</th><th>Package name</th><th>Size</th><th>SHA256 Checksum</th></tr></thead><tbody><tr><td>Linux 64-bit(x86_64)</td><td><a href="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86_64.tar.gz">google-cloud-cli-linux-x86_64.tar.gz</a></td><td>149.7 MB</td><td>01d322b29107e57f13e1418c789b9c3c0e6db1eb8e182d41ab6de09e6e0ca805</td></tr><tr><td>Linux 64-bit(Arm)</td><td><a href="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-arm.tar.gz">google-cloud-cli-linux-arm.tar.gz</a></td><td>56.3 MB</td><td>009a1ca0b114e4049cadb517a81c2a4b697d180425da1d2fdb456952d7f070b5</td></tr><tr><td>Linux 32-bit(x86)</td><td><a href="https://dl.google.com/dl/cloudsdk/channels/rapid/downloads/google-cloud-cli-linux-x86.tar.gz">google-cloud-cli-linux-x86.tar.gz</a></td><td>56.3 MB</td><td>1fea8bf6373c49c435ab4089aa128f981da425408b28f88b6c4a91d18b19e3a3</td></tr><tr><td>Windows</td><td><a href="https://dl.google.com/dl/cloudsdk/channels/rapid/GoogleCloudSDKInstaller.exe">Google Cloud CLI installer</a>.</td><td></td><td></td></tr></tbody></table></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">Ao finalizar a instalação, é fundamental <strong>reiniciar o editor de código (como o Visual Studio Code)</strong> para que o terminal reconheça os novos comandos. Isso garante que os comandos <code>gcloud</code> estejam disponíveis na sessão atual do terminal.</p>



<p class="wp-block-paragraph">Pronto! Com o projeto criado e a CLI instalada, estamos preparados para autenticar nossa sessão e começar a configurar o ambiente de deploy da aplicação.</p>



<h2 class="wp-block-heading">Autenticando e Configurando o Projeto com o <code>gcloud</code></h2>



<p class="wp-block-paragraph">Com o <code>gcloud</code> instalado e o projeto já criado no console do Google Cloud, o próximo passo é <strong>autenticar a linha de comando com sua conta Google</strong> e <strong>vincular o terminal ao projeto correto</strong>. Essa etapa garante que todas as ações executadas via terminal estejam conectadas ao ambiente certo.</p>



<p class="wp-block-paragraph">O comando inicial é:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="gcloud auth login
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">gcloud</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">auth</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">login</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse comando abre o navegador padrão e solicita que você faça login com sua conta Google. Após o login, o terminal estará autorizado a acessar os serviços da nuvem com suas credenciais. Isso é essencial para permitir que o <code>gcloud</code> controle recursos como repositórios, deploys e configurações de rede em nome do usuário autenticado.</p>



<p class="wp-block-paragraph">Logo em seguida, é necessário indicar qual projeto queremos utilizar como contexto padrão. Isso é feito com o comando:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="gcloud config set project [PROJECT_ID]
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">gcloud</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">config</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">set</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">project</span><span style="color: #D8DEE9FF"> [</span><span style="color: #D8DEE9">PROJECT_ID</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Substitua <code>[PROJECT_ID]</code> pelo ID do projeto criado anteriormente. Esse ID pode ser encontrado no painel do Google Cloud, próximo ao nome do projeto, ou no seletor de projetos. Ele define que todas as ações subsequentes do <code>gcloud</code> ocorrerão dentro desse projeto específico.</p>



<p class="wp-block-paragraph">Com a autenticação e o contexto configurados, o terminal está pronto para iniciar o processo de build, armazenamento e deploy da aplicação. Essa separação clara por projetos é importante tanto para organização quanto para controle de acesso, especialmente em times maiores ou com múltiplas aplicações em execução.</p>



<h2 class="wp-block-heading">Deploy com Cloud Run e Artifact Registry: Publicando sua Aplicação</h2>



<p class="wp-block-paragraph">Agora que o projeto está configurado e autenticado, é hora de realizar o deploy da aplicação. O processo envolve três ferramentas principais da plataforma Google Cloud:</p>



<ul class="wp-block-list">
<li><strong>Artifact Registry</strong>: armazena a imagem Docker da aplicação.</li>



<li><strong>Cloud Build</strong>: constrói a imagem a partir do código-fonte.</li>



<li><strong>Cloud Run</strong>: executa o contêiner de forma escalável e serverless.</li>
</ul>



<p class="wp-block-paragraph">A primeira etapa é garantir que o <code>gcloud</code> esteja preparado para realizar o build e deploy. O comando a ser utilizado é:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="gcloud run deploy --port=8000
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">gcloud</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">deploy</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">port</span><span style="color: #81A1C1">=</span><span style="color: #B48EAD">8000</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse comando inicia uma série de etapas interativas:</p>



<ol class="wp-block-list">
<li><strong>Confirmação do diretório de origem do código</strong> — onde está o <code>Dockerfile</code>.</li>



<li><strong>Nome do serviço</strong> — por exemplo, <code>api</code>.</li>



<li><strong>Seleção da região</strong> — escolher <code>southamerica-east1</code> para datacenters em São Paulo, otimizando a latência para usuários brasileiros.</li>



<li><strong>Criação automática do repositório no Artifact Registry</strong>, se necessário.</li>



<li><strong>Permissões de acesso</strong> — ativar <code>Allow unauthenticated invocations</code> para tornar a aplicação pública e acessível sem autenticação.</li>
</ol>



<p class="wp-block-paragraph">Durante o processo, o <code>Cloud Build</code> constrói a imagem da aplicação e a envia ao <code>Artifact Registry</code>. Em seguida, o <code>Cloud Run</code> provisiona a infraestrutura necessária, com balanceamento de carga e criação automática de um endpoint (URL) para acesso à aplicação.</p>



<p class="wp-block-paragraph">Esse modelo de implantação <strong>serverless</strong> traz diversos benefícios:</p>



<ul class="wp-block-list">
<li><strong>Escalabilidade automática</strong> — aumenta ou reduz recursos com base na demanda.</li>



<li><strong>Custos otimizados</strong> — o serviço escala para zero quando não há requisições.</li>



<li><strong>Facilidade operacional</strong> — não exige manutenção de VMs ou clusters.</li>
</ul>



<p class="wp-block-paragraph">Após o deploy, o terminal exibirá o <strong>Service URL</strong>, que pode ser acessado por qualquer pessoa. Basta clicar no link e utilizar endpoints como <code>/docs</code> ou <code>/api</code> para testar a aplicação no navegador.</p>



<h2 class="wp-block-heading">Validação da Aplicação na Nuvem e Considerações Finais</h2>



<p class="wp-block-paragraph">Com o deploy concluído, é hora de <strong>verificar se tudo está funcionando corretamente</strong>. Ao acessar a <strong>Service URL</strong> gerada pelo Cloud Run, é possível navegar até rotas como <code>/docs</code> para visualizar a documentação automática da API — ideal para ambientes baseados em frameworks como FastAPI.</p>



<p class="wp-block-paragraph">Para testar a aplicação, podemos realizar operações CRUD diretamente na interface interativa. Por exemplo, criar um novo &#8220;aluno&#8221; com nome, e-mail e telefone, submetendo os dados via <code>POST</code>. A resposta com <strong>status code 200</strong> indica que a API está funcional e a aplicação foi corretamente disponibilizada. Com isso, também é possível visualizar os registros armazenados usando um <code>GET</code>.</p>



<p class="wp-block-paragraph">Além disso, o Google Cloud oferece ferramentas para <strong>monitoramento e diagnóstico</strong>:</p>



<ul class="wp-block-list">
<li><strong>Logs em tempo real</strong> da aplicação disponíveis no painel do Cloud Run.</li>



<li><strong>Métricas de uso e desempenho</strong> — número de requisições, latência, falhas e consumo de recursos.</li>



<li>Histórico de versões da imagem no <strong>Artifact Registry</strong>, possibilitando reversões ou comparações entre builds.</li>
</ul>



<p class="wp-block-paragraph">Essa etapa mostra como o ciclo DevOps se completa: o código desenvolvido localmente é testado, empacotado, enviado à nuvem, escalado automaticamente e monitorado — tudo isso com poucos comandos.</p>



<p class="wp-block-paragraph">Ao final, fica claro que a adoção de plataformas como o Google Cloud simplifica significativamente o trabalho de desenvolvedores e equipes de infraestrutura. A ideia de que &#8220;nuvem é complicada&#8221; se desfaz ao perceber que, com as ferramentas certas, o deploy de uma aplicação pode ser tão fácil quanto pronunciar o nome de uma banda punk alemã.</p>



<p class="wp-block-paragraph">Esse é o poder de combinar <strong>contenedores leves</strong>, <strong>ferramentas DevOps</strong> e <strong>infraestrutura serverless</strong>: permitir que ideias saiam rapidamente do ambiente local e ganhem o mundo.</p>



<p class="wp-block-paragraph"></p><p>The post <a href="https://mcu.tec.br/infraestrutura/tutorial-devops-parte-3-publicando-sua-aplicacao-na-nuvem-com-cloud-run/">Tutorial DevOps – Parte 3: Publicando sua Aplicação na Nuvem com Cloud Run</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">564</post-id>	</item>
		<item>
		<title>Automatizando e Orquestrando Contêineres com Docker Compose e GitHub Actions &#8211; Tutorial Parte 2</title>
		<link>https://mcu.tec.br/infraestrutura/automatizando-e-orquestrando-conteineres-com-docker-compose-e-github-actions-tutorial-parte-2/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automatizando-e-orquestrando-conteineres-com-docker-compose-e-github-actions-tutorial-parte-2</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 19:51:27 +0000</pubDate>
				<category><![CDATA[Infraestrutura]]></category>
		<category><![CDATA[Artifact Registry]]></category>
		<category><![CDATA[automação de build]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[container name]]></category>
		<category><![CDATA[deploy na nuvem]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[Docker Compose]]></category>
		<category><![CDATA[docker volumes]]></category>
		<category><![CDATA[docker-compose.yml]]></category>
		<category><![CDATA[Dockerfile]]></category>
		<category><![CDATA[GitHub Actions]]></category>
		<category><![CDATA[Google Cloud]]></category>
		<category><![CDATA[Integração Contínua]]></category>
		<category><![CDATA[pipeline GitHub]]></category>
		<category><![CDATA[push no GitHub]]></category>
		<category><![CDATA[Tutorial DevOps]]></category>
		<category><![CDATA[versionamento semântico]]></category>
		<category><![CDATA[workflow GitHub]]></category>
		<category><![CDATA[YAML]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=562</guid>

					<description><![CDATA[<p>Aprenda neste tutorial como usar Docker Compose e GitHub Actions para automatizar o build de sua aplicação, validar com CI e preparar o deploy na nuvem com o Google Cloud.</p>
<p>The post <a href="https://mcu.tec.br/infraestrutura/automatizando-e-orquestrando-conteineres-com-docker-compose-e-github-actions-tutorial-parte-2/">Automatizando e Orquestrando Contêineres com Docker Compose e GitHub Actions – Tutorial Parte 2</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introdução</h2>



<p class="wp-block-paragraph">Neste segundo tutorial da nossa série sobre Cloud e DevOps, avançamos no uso do Docker, explorando maneiras mais eficientes de executar aplicações por meio da orquestração com Docker Compose. Também aprendemos a integrar esse processo ao GitHub utilizando workflows automáticos com GitHub Actions, preparando o caminho para o deploy em nuvem. O foco aqui é a produtividade, a padronização e a portabilidade do ambiente de desenvolvimento.</p>



<h2 class="wp-block-heading">Otimizando o Uso do Docker com Docker Compose</h2>



<p class="wp-block-paragraph">Na primeira parte da série, rodamos a aplicação com um comando extenso usando <code>docker run</code>. Agora, substituímos essa abordagem manual pela criação de um arquivo <code>docker-compose.yml</code>, que automatiza e simplifica o processo de build e execução da aplicação.</p>



<p class="wp-block-paragraph">O Docker Compose permite descrever os serviços de uma aplicação usando YAML, o mesmo formato utilizado amplamente em DevOps (como em Kubernetes, Prometheus, entre outros). Com ele, é possível definir serviços, volumes, portas, variáveis de ambiente e dependências entre aplicações – tudo em um único arquivo.</p>



<p class="wp-block-paragraph">Exemplo de estrutura simples do <code>docker-compose.yml</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="services:
  app:
    build: .
    container_name: imersao-api
    ports:
      - &quot;8000:8000&quot;
    volumes:
      - .:/app
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">services</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  app</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    build</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"><span style="color: #D8DEE9FF">    container_name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imersao</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">api</span></span>
<span class="line"><span style="color: #D8DEE9FF">    ports</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">8000:8000</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    volumes</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF">:</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Essa estrutura permite que o código fonte editado localmente seja refletido imediatamente no contêiner, sem necessidade de reiniciar o serviço, graças à montagem do volume <code>.:/app</code>.</p>



<h2 class="wp-block-heading">Criando e Executando com Docker Compose</h2>



<p class="wp-block-paragraph">Com o arquivo YAML configurado, o comando necessário para subir o ambiente se resume a:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker compose up
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">compose</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">up</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse comando compila a imagem (caso necessário) e sobe o contêiner em background ou com os logs visíveis, dependendo do uso da flag <code>-d</code>. Isso representa um grande ganho em relação ao processo anterior, que exigia múltiplos comandos de terminal, configuração de ambiente virtual, instalação de dependências e execução manual da aplicação.</p>



<h2 class="wp-block-heading">Commit e Versionamento do Projeto</h2>



<p class="wp-block-paragraph">Com a aplicação funcional e o ambiente Docker pronto, o próximo passo é versionar o projeto e enviá-lo ao GitHub. A convenção de commits sugerida segue o modelo do Angular, com prefixos como <code>feat</code>, <code>fix</code>, entre outros. Por exemplo:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="git commit -m &quot;feat: adiciona Docker Compose ao repositório&quot;
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">git</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">commit</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">m</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">feat: adiciona Docker Compose ao repositório</span><span style="color: #ECEFF4">&quot;</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">O projeto é então enviado ao GitHub via <code>git push</code>, já contendo os arquivos <code>Dockerfile</code> e <code>docker-compose.yml</code>, prontos para replicar o ambiente em qualquer máquina.</p>



<h2 class="wp-block-heading">Integração Contínua com GitHub Actions</h2>



<p class="wp-block-paragraph">Em seguida, foi configurado um pipeline básico de integração contínua (CI) com GitHub Actions. A configuração está em um arquivo YAML no caminho <code>.github/workflows/docker-image.yml</code>. Esse pipeline é disparado automaticamente a cada push na branch <code>main</code> e executa a build da imagem Docker.</p>



<p class="wp-block-paragraph">A Action utiliza um runner baseado em Ubuntu e realiza passos como:</p>



<ul class="wp-block-list">
<li>Verificação do push</li>



<li>Build da imagem Docker com o <code>Dockerfile</code></li>



<li>Output da imagem com uma tag (que pode ser personalizada com hash de commit ou versão semântica)</li>
</ul>



<p class="wp-block-paragraph">Isso garante que toda atualização de código seja validada automaticamente, reduzindo erros e garantindo consistência para deploys futuros.</p>



<h2 class="wp-block-heading">Boas Práticas: Versionamento e SemVer</h2>



<p class="wp-block-paragraph">Foi abordada também a importância de versionar imagens corretamente, evitando o uso da tag <code>latest</code> em produção. Recomenda-se seguir o padrão SemVer (Semantic Versioning), com versões <code>major.minor.patch</code>, o que facilita rollbacks e controle de mudanças.</p>



<h2 class="wp-block-heading">Próximos Passos</h2>



<p class="wp-block-paragraph">Com a imagem construída e validada via GitHub Actions, o próximo passo será enviar essa aplicação para a nuvem – mais especificamente, para o Google Cloud. Para isso, foi apresentado o processo de resgate de créditos na plataforma, criação de projeto e ativação do faturamento.</p>



<ol class="wp-block-list"></ol>



<h2 class="wp-block-heading">Criando o Projeto na Google Cloud</h2>



<p class="wp-block-paragraph">Agora é necessário criar um projeto no console do Google Cloud, que será o destino do deploy da aplicação.</p>



<h3 class="wp-block-heading">Etapas:</h3>



<ol class="wp-block-list">
<li>Acesse o console e clique em “Abrir seletor de projetos”.</li>



<li>Clique em <strong>&#8220;Novo Projeto&#8221;</strong>, dê um nome (ex: <code>Alura-Imersao</code>) e crie.</li>



<li>Após criado, clique sobre o projeto para selecioná-lo.</li>



<li>Em seguida, vá até a aba <strong>Faturamento</strong> e vincule os créditos ativados ao projeto. Selecione a conta de faturamento &#8220;de avaliação&#8221; e clique em &#8220;Definir conta&#8221;.</li>
</ol>



<p class="wp-block-paragraph">Após isso, o painel exibirá o valor disponível para o projeto, que pode ser usado para criar instâncias, serviços e realizar o deploy.</p>



<h2 class="wp-block-heading">Finalizando a Preparação para o Deploy</h2>



<p class="wp-block-paragraph">Com os créditos ativos e o projeto criado, a estrutura para o deploy está pronta. O próximo passo – a ser abordado no próximo tutorial – será <strong>colocar no ar a aplicação que foi versionada e enviada ao GitHub</strong>, utilizando os serviços da Google Cloud, como o <strong>Artifact Registry</strong> ou o <strong>Cloud Run</strong>, tornando a API acessível de qualquer lugar da internet.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Recapitulando o que aprendemos neste tutorial</h2>



<ul class="wp-block-list">
<li>Criamos um <code>docker-compose.yml</code> para orquestrar o build e a execução da aplicação com um único comando.</li>



<li>Automatizamos o processo de CI com GitHub Actions.</li>



<li>Versionamos e subimos o projeto no GitHub.</li>



<li>Ativamos créditos gratuitos no Google Cloud.</li>



<li>Criamos e configuramos um projeto na plataforma para receber a aplicação.</li>



<li>Entendemos o papel do CI na consistência de builds e na produtividade do time DevOps.</li>
</ul>



<h2 class="wp-block-heading">Automatizando o Build com GitHub Actions</h2>



<p class="wp-block-paragraph">Uma das grandes vantagens do uso do GitHub em projetos DevOps é a possibilidade de criar <strong>pipelines de integração contínua (CI)</strong> com <strong>GitHub Actions</strong>, utilizando arquivos YAML que descrevem o passo a passo da automação.</p>



<p class="wp-block-paragraph">No nosso projeto, configuramos um workflow chamado <code>docker-image.yml</code>, responsável por:</p>



<ul class="wp-block-list">
<li>Monitorar alterações (<code>push</code> ou <code>pull_request</code>) na branch <code>main</code>.</li>



<li>Executar os passos para <strong>construir a imagem Docker</strong> da aplicação.</li>



<li>Validar que a imagem foi construída com sucesso, sem a necessidade de rodar comandos manuais.</li>
</ul>



<p class="wp-block-paragraph">Esse processo ajuda a garantir que qualquer mudança feita no repositório principal gere uma nova versão da imagem de forma <strong>automática, reproduzível e rastreável</strong>.</p>



<h3 class="wp-block-heading">Boas práticas aplicadas:</h3>



<ul class="wp-block-list">
<li>Definição de etapas (<code>steps</code>) claras no YAML, como <code>build</code>, <code>run</code>, <code>login</code>.</li>



<li>Separação lógica das fases de execução, facilitando a leitura por desenvolvedores e DevOps.</li>



<li>Uso opcional de <code>tags</code> e versionamento semanticamente significativos (evitando <code>latest</code> em produção).</li>



<li>Possibilidade de usar <code>hash de commit</code>, <code>data</code>, ou <code>número de versão</code> como parte do nome da imagem.</li>
</ul>



<h2 class="wp-block-heading">O Que Mais Podemos Fazer com Workflows?</h2>



<p class="wp-block-paragraph">Embora neste tutorial o foco tenha sido a criação e validação da imagem Docker, os workflows do GitHub Actions vão muito além:</p>



<ul class="wp-block-list">
<li><strong>Rodar testes automatizados</strong> (unitários, de integração, de segurança).</li>



<li><strong>Executar análise estática de código</strong>.</li>



<li><strong>Escanear imagens Docker por vulnerabilidades</strong>.</li>



<li><strong>Efetuar deploys automáticos</strong> para ambientes como Docker Hub, Google Cloud ou AWS.</li>



<li><strong>Gerenciar pipelines CI/CD completas</strong>, desde o push até o deploy em produção.</li>
</ul>



<h2 class="wp-block-heading">Caminho para o Deploy</h2>



<p class="wp-block-paragraph">Com a imagem criada, validada e o projeto devidamente versionado no GitHub, além de termos o projeto no Google Cloud com os créditos ativados, estamos prontos para a etapa final desta trilogia de tutoriais: <strong>colocar a aplicação no ar com um link acessível publicamente</strong>.</p>



<p class="wp-block-paragraph">Esse processo envolverá:</p>



<ul class="wp-block-list">
<li>Escolha de um serviço de deploy (Cloud Run, GKE, App Engine&#8230;).</li>



<li>Autenticação com o Google Cloud.</li>



<li>Push da imagem para o repositório de imagens (Artifact Registry).</li>



<li>Configuração de variáveis e ambiente.</li>



<li>Acesso via navegador com domínio público.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Conclusão do Tutorial Parte 2</h2>



<p class="wp-block-paragraph">Neste tutorial você aprendeu a:</p>



<p class="wp-block-paragraph"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Automatizar o build de sua aplicação com Docker Compose<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Configurar workflows de CI com GitHub Actions<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Utilizar boas práticas de versionamento e padronização<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Criar um projeto no Google Cloud e ativar seus créditos<br><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Preparar o ambiente para o deploy na nuvem</p>



<p class="wp-block-paragraph">No próximo e último tutorial da série, vamos realizar o deploy completo da aplicação na Google Cloud, garantindo que ela funcione <strong>fora da sua máquina local</strong>, de forma segura e profissional.</p><p>The post <a href="https://mcu.tec.br/infraestrutura/automatizando-e-orquestrando-conteineres-com-docker-compose-e-github-actions-tutorial-parte-2/">Automatizando e Orquestrando Contêineres com Docker Compose e GitHub Actions – Tutorial Parte 2</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">562</post-id>	</item>
		<item>
		<title>Tutorial Completo de Cloud DevOps com Docker, CI/CD e Monitoramento &#8211; Parte 1</title>
		<link>https://mcu.tec.br/infraestrutura/tutorial-completo-de-cloud-devops-com-docker-ci-cd-e-monitoramento-parte-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=tutorial-completo-de-cloud-devops-com-docker-ci-cd-e-monitoramento-parte-1</link>
		
		<dc:creator><![CDATA[Carlos Delfino]]></dc:creator>
		<pubDate>Fri, 04 Jul 2025 19:36:11 +0000</pubDate>
				<category><![CDATA[Infraestrutura]]></category>
		<category><![CDATA[Aplicação em produção]]></category>
		<category><![CDATA[Boas práticas DevOps]]></category>
		<category><![CDATA[CI/CD]]></category>
		<category><![CDATA[Cloud DevOps]]></category>
		<category><![CDATA[Container]]></category>
		<category><![CDATA[Cultura DevOps]]></category>
		<category><![CDATA[Deploy Automatizado]]></category>
		<category><![CDATA[DevOps]]></category>
		<category><![CDATA[DevOps com Python]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Engenharia de Software]]></category>
		<category><![CDATA[Entrega Contínua]]></category>
		<category><![CDATA[Feedback Contínuo]]></category>
		<category><![CDATA[Flask com Docker]]></category>
		<category><![CDATA[GitHub Actions]]></category>
		<category><![CDATA[Grafana]]></category>
		<category><![CDATA[Infraestrutura como Código]]></category>
		<category><![CDATA[Integração Contínua]]></category>
		<category><![CDATA[Log centralizado]]></category>
		<category><![CDATA[Monitoramento]]></category>
		<category><![CDATA[Observabilidade]]></category>
		<category><![CDATA[Pipeline DevOps]]></category>
		<category><![CDATA[Prometheus]]></category>
		<category><![CDATA[Tutorial DevOps]]></category>
		<category><![CDATA[Versionamento de imagens Docker]]></category>
		<guid isPermaLink="false">https://mcu.tec.br/?p=560</guid>

					<description><![CDATA[<p>Aprenda passo a passo como implementar DevOps na prática com Docker, integração contínua (CI), entrega contínua (CD) e monitoramento em nuvem. Ideal para desenvolvedores e profissionais de infraestrutura que buscam automatizar e escalar aplicações com eficiência e confiabilidade.</p>
<p>The post <a href="https://mcu.tec.br/infraestrutura/tutorial-completo-de-cloud-devops-com-docker-ci-cd-e-monitoramento-parte-1/">Tutorial Completo de Cloud DevOps com Docker, CI/CD e Monitoramento – Parte 1</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></description>
										<content:encoded><![CDATA[<h2 class="wp-block-heading">Introdução ao Tutorial de Cloud DevOps</h2>



<p class="wp-block-paragraph">Este tutorial marca o início da jornada na criação de ambientes reais utilizando Docker dentro do contexto da filosofia DevOps. A proposta vai muito além de ensinar o uso de ferramentas específicas. O objetivo é apresentar uma cultura de colaboração entre desenvolvimento e operações, promovendo automação, escalabilidade e portabilidade em aplicações modernas.</p>



<p class="wp-block-paragraph">Nesta primeira etapa, o foco está em entender o papel do DevOps como facilitador da entrega contínua, da confiabilidade e da padronização de ambientes. Será demonstrado como uma aplicação desenvolvida em Python pode ser estruturada para ser executada com consistência em diferentes sistemas operacionais.</p>



<p class="wp-block-paragraph">O conteúdo explora como transformar um projeto funcional em um ambiente local em um serviço encapsulado com Docker, pronto para ser executado de forma segura e escalável, tanto localmente quanto na nuvem.</p>



<p class="wp-block-paragraph">O tutorial não se aprofunda no código da aplicação em si, mas sim em como tornar a aplicação portátil, replicável e independente do ambiente onde será executada. Essa abordagem reflete o verdadeiro papel do profissional DevOps: garantir que aplicações funcionem de forma previsível e segura em qualquer lugar.</p>



<h2 class="wp-block-heading">O que é DevOps e sua História</h2>



<p class="wp-block-paragraph">O termo <strong>DevOps</strong> é uma junção de duas palavras: <strong>Development</strong> (desenvolvimento) e <strong>Operations</strong> (operações). Trata-se de uma <strong>filosofia de trabalho</strong> e <strong>conjunto de práticas culturais e técnicas</strong> que visam integrar os times de desenvolvimento de software com os times responsáveis pela infraestrutura e operação dos sistemas. O objetivo é <strong>automatizar processos</strong>, <strong>melhorar a colaboração</strong>, <strong>aumentar a velocidade das entregas</strong> e <strong>manter a confiabilidade das aplicações</strong> em ambientes complexos e em constante mudança.</p>



<h3 class="wp-block-heading">Origens e Evolução</h3>



<p class="wp-block-paragraph">Na década de 1980, o desenvolvimento de software era centralizado e vinculado diretamente ao hardware. As equipes de desenvolvimento e operação trabalhavam de forma isolada, com pouca comunicação entre si. Essa abordagem seguiu por muito tempo, marcada por ciclos longos e sequenciais de entrega, conhecidos como <strong>modelo em cascata</strong> (Waterfall).</p>



<p class="wp-block-paragraph">Com a popularização dos computadores pessoais nos anos 1990, surgiram os primeiros servidores dedicados e aplicações cliente-servidor. Mesmo com esse avanço, as organizações ainda mantinham a separação rígida entre desenvolvimento e operações, o que gerava conflitos, atrasos e uma constante transferência de responsabilidades em caso de falhas.</p>



<p class="wp-block-paragraph">Foi apenas nos anos 2000, com a introdução do <strong>Manifesto Ágil</strong> (2001), que começou uma transformação cultural importante. As equipes passaram a trabalhar com ciclos curtos, feedback contínuo e colaboração entre áreas como desenvolvimento, testes e análise de negócios. Contudo, ainda persistia a separação das operações de TI, o que impedia uma integração plena entre todos os envolvidos no ciclo de vida da aplicação.</p>



<p class="wp-block-paragraph">A virada decisiva ocorreu em <strong>2009</strong>, quando foi apresentada publicamente uma abordagem capaz de realizar <strong>diversos deploys diários com baixo risco e alta confiabilidade</strong>, promovendo a automação de infraestrutura, controle de versão compartilhado e práticas como <strong>infraestrutura como código</strong> (IaC). Também foi criado, no mesmo ano, o evento internacional <strong>DevOpsDays</strong>, responsável por consolidar o termo “DevOps” como um movimento mundial. Foi nesse momento que se tornou evidente que <strong>mudanças pequenas, contínuas e colaborativas são mais eficazes do que grandes lançamentos esporádicos</strong>.</p>



<h3 class="wp-block-heading">Princípios e Benefícios</h3>



<p class="wp-block-paragraph">DevOps propõe que todos os envolvidos no desenvolvimento de uma aplicação — desde os requisitos até a operação em produção — atuem como <strong>um sistema integrado</strong>, com <strong>confiança mútua</strong>, <strong>respeito</strong>, <strong>aprendizado contínuo</strong>, e foco em <strong>entregar valor com qualidade e estabilidade</strong>.</p>



<p class="wp-block-paragraph">Entre os benefícios da adoção de práticas DevOps, destacam-se:</p>



<ul class="wp-block-list">
<li>Redução de riscos operacionais e falhas em produção;</li>



<li>Maior qualidade nas entregas de software;</li>



<li>Aumento da produtividade e eficiência da equipe;</li>



<li>Feedback contínuo dos usuários e dos sistemas;</li>



<li>Integração contínua (CI) e entrega contínua (CD);</li>



<li>Monitoramento proativo e correções rápidas.</li>
</ul>



<h3 class="wp-block-heading">DevOps Hoje</h3>



<p class="wp-block-paragraph">Com o avanço de tecnologias como <strong>virtualização</strong>, <strong>containers</strong>, <strong>cloud computing</strong> e <strong>orquestração com Kubernetes</strong>, DevOps se consolidou como uma abordagem essencial para empresas que desejam escalar suas operações, melhorar a resiliência dos sistemas e reduzir o tempo de resposta às mudanças do mercado.</p>



<p class="wp-block-paragraph">Essa filosofia é hoje aplicada em diversos setores, incluindo bancos, e-commerce, telecomunicações, saúde e indústria, sendo uma peça-chave na transformação digital e na inovação contínua.</p>



<h2 class="wp-block-heading">Analisando o Projeto e Criando o Ambiente Virtual com Python</h2>



<p class="wp-block-paragraph">O primeiro passo prático no tutorial é conhecer a aplicação que será utilizada como base para as atividades DevOps. Trata-se de uma aplicação desenvolvida em Python com o framework <strong>Flask</strong>, escolhida por sua leveza e simplicidade, ideal para demonstrar práticas de empacotamento, deploy e monitoramento.</p>



<p class="wp-block-paragraph">A estrutura inicial do projeto conta com arquivos básicos como <code>app.py</code>, que contém a lógica principal do servidor, e um diretório de templates com arquivos HTML que definem a interface web da aplicação. Também estão presentes arquivos auxiliares como <code>requirements.txt</code>, onde são listadas todas as dependências necessárias para executar o projeto, e o <code>.gitignore</code>, que define quais arquivos não devem ser versionados.</p>



<p class="wp-block-paragraph">Para garantir que o ambiente seja consistente em diferentes sistemas operacionais e livre de conflitos com outras bibliotecas instaladas no sistema, é criada uma <strong>virtual environment (ambiente virtual Python)</strong>. Esse ambiente isolado garante que as dependências da aplicação fiquem contidas em um único espaço, controlado e replicável.</p>



<p class="wp-block-paragraph">O processo de criação do ambiente virtual segue os seguintes passos:</p>



<ol class="wp-block-list">
<li><strong>Criação do ambiente virtual:</strong> <code>python -m venv venv</code> Isso cria uma pasta chamada <code>venv</code> contendo a estrutura necessária para o isolamento.</li>



<li><strong>Ativação do ambiente:</strong><ul><li>Em sistemas Unix/Linux/macOS: <code>source venv/bin/activate</code></li><li>Em sistemas Windows: <code>.\venv\Scripts\activate</code></li></ul>Após ativado, o terminal indicará que o ambiente virtual está ativo, geralmente com o prefixo <code>(venv)</code>.</li>



<li><strong>Instalação das dependências da aplicação:</strong> <code>pip install -r requirements.txt</code> Isso garante que todas as bibliotecas utilizadas pela aplicação estejam instaladas corretamente no ambiente isolado.</li>
</ol>



<p class="wp-block-paragraph">Com o ambiente configurado, o próximo passo será a <strong>execução local da aplicação</strong>, permitindo verificar se tudo está funcionando corretamente antes de seguir para o empacotamento com Docker.</p>



<h2 class="wp-block-heading">Executando a Aplicação Localmente e Entendendo o Ciclo de Vida DevOps</h2>



<p class="wp-block-paragraph">Com o ambiente virtual Python ativado e as dependências instaladas, o próximo passo é <strong>executar a aplicação localmente</strong>. Isso permite garantir que tudo está funcionando corretamente antes de iniciar o processo de empacotamento, automação e deploy.</p>



<p class="wp-block-paragraph">A aplicação Flask pode ser executada com o seguinte comando:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="python app.py
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">python</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">py</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Ao rodar esse comando, o servidor local será iniciado, geralmente escutando na porta <code>5000</code>. Acesse <code>http://localhost:5000</code> no navegador para visualizar a interface da aplicação.</p>



<p class="wp-block-paragraph">Esse processo de execução local é essencial dentro do ciclo de vida DevOps, pois representa a <strong>fase de desenvolvimento e validação inicial</strong>, onde o código é testado manualmente antes de seguir para etapas mais avançadas como integração contínua, testes automatizados, entrega e monitoramento.</p>



<h3 class="wp-block-heading">O Ciclo de Vida DevOps</h3>



<p class="wp-block-paragraph">No contexto DevOps, o ciclo de vida de uma aplicação não se limita à sua construção. Ele envolve uma série de etapas que trabalham de forma contínua e colaborativa:</p>



<ol class="wp-block-list">
<li><strong>Planejamento</strong><br>Levantamento de requisitos, definição de funcionalidades e arquitetura da solução.</li>



<li><strong>Desenvolvimento</strong><br>Codificação do sistema com foco em modularidade, testes e versionamento.</li>



<li><strong>Integração e Testes</strong><br>Automatização de testes e validações a cada nova modificação no código, utilizando pipelines de integração contínua (CI).</li>



<li><strong>Entrega e Deploy</strong><br>Preparação do sistema para produção com automação de build, empacotamento (ex: containers) e publicação.</li>



<li><strong>Operação e Monitoramento</strong><br>Garantia da estabilidade da aplicação em produção com uso de ferramentas de observabilidade, logs, alertas e métricas.</li>



<li><strong>Feedback Contínuo</strong><br>Retorno constante do sistema, dos usuários e das métricas de produção para ajustes e melhorias contínuas.</li>
</ol>



<p class="wp-block-paragraph">Executar a aplicação localmente é uma etapa essencial que precede a automação. Ela garante que todos os requisitos foram corretamente instalados e que a aplicação está apta para ser <strong>empacotada</strong> — tema da próxima seção do tutorial.</p>



<h2 class="wp-block-heading">Containerizando a Aplicação com Docker</h2>



<p class="wp-block-paragraph">Agora que a aplicação está funcionando corretamente em ambiente local, o próximo passo é torná-la independente do sistema operacional onde será executada. Isso é feito através do <strong>Docker</strong>, uma tecnologia que permite empacotar a aplicação e suas dependências em uma imagem leve e portátil chamada <strong>container</strong>.</p>



<h3 class="wp-block-heading">O que é Docker?</h3>



<p class="wp-block-paragraph">Docker é uma plataforma que automatiza a criação, o empacotamento e a execução de aplicações em <strong>ambientes isolados</strong>. Com ele, é possível garantir que a aplicação funcione exatamente da mesma forma em qualquer máquina — seja localmente, em um servidor de produção ou na nuvem.</p>



<p class="wp-block-paragraph">Diferente de máquinas virtuais, containers compartilham o mesmo kernel do sistema operacional, tornando-os muito mais leves e rápidos.</p>



<h3 class="wp-block-heading">Criando o Dockerfile</h3>



<p class="wp-block-paragraph">O primeiro passo é criar um arquivo chamado <code>Dockerfile</code> na raiz do projeto. Esse arquivo define <strong>instruções passo a passo</strong> para construir a imagem da aplicação. Veja um exemplo básico:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="# Imagem base oficial do Python
FROM python:3.11

# Diretório de trabalho no container
WORKDIR /app

# Copia os arquivos do projeto para o container
COPY . .

# Instala as dependências da aplicação
RUN pip install -r requirements.txt

# Expõe a porta utilizada pelo Flask
EXPOSE 5000

# Comando para iniciar a aplicação
CMD [&quot;python&quot;, &quot;app.py&quot;]
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Imagem</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">base</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">oficial</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Python</span></span>
<span class="line"><span style="color: #D8DEE9">FROM</span><span style="color: #D8DEE9FF"> python</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">3.11</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Diretório</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">de</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">trabalho</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">container</span></span>
<span class="line"><span style="color: #D8DEE9">WORKDIR</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Copia</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">os</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">arquivos</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">do</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">projeto</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">container</span></span>
<span class="line"><span style="color: #D8DEE9">COPY</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Instala</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">as</span><span style="color: #D8DEE9FF"> dependências da aplicação</span></span>
<span class="line"><span style="color: #D8DEE9">RUN</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">requirements</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Expõe</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">porta</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">utilizada</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pelo</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Flask</span></span>
<span class="line"><span style="color: #D8DEE9">EXPOSE</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5000</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF"># </span><span style="color: #D8DEE9">Comando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">iniciar</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">a</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">aplicação</span></span>
<span class="line"><span style="color: #D8DEE9">CMD</span><span style="color: #D8DEE9FF"> [</span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">python</span><span style="color: #ECEFF4">&quot;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">app.py</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Cada instrução cumpre uma etapa essencial:</p>



<ul class="wp-block-list">
<li><code>FROM</code> define a base da imagem (no caso, Python 3.11).</li>



<li><code>WORKDIR</code> cria o diretório interno onde o código será executado.</li>



<li><code>COPY . .</code> transfere os arquivos da aplicação local para dentro do container.</li>



<li><code>RUN</code> executa o comando de instalação das dependências.</li>



<li><code>EXPOSE</code> informa qual porta será usada.</li>



<li><code>CMD</code> define o comando final que roda a aplicação.</li>
</ul>



<h3 class="wp-block-heading">Construindo a Imagem Docker</h3>



<p class="wp-block-paragraph">Com o <code>Dockerfile</code> criado, o próximo passo é <strong>construir a imagem</strong>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker build -t app-devops .
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">build</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">devops</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse comando instrui o Docker a ler o <code>Dockerfile</code> e construir uma imagem chamada <code>app-devops</code>.</p>



<h3 class="wp-block-heading">Executando a Aplicação no Container</h3>



<p class="wp-block-paragraph">Uma vez criada a imagem, a aplicação pode ser executada dentro de um container com:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run -p 5000:5000 app-devops
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5000</span><span style="color: #D8DEE9FF">:</span><span style="color: #B48EAD">5000</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">devops</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">O parâmetro <code>-p 5000:5000</code> faz o mapeamento da porta do container para a porta local, permitindo o acesso via <code>http://localhost:5000</code>.</p>



<p class="wp-block-paragraph">Agora, a aplicação está empacotada com tudo o que precisa para rodar de forma consistente, replicável e portátil. Este é o <strong>primeiro passo concreto rumo à automação e à escalabilidade</strong>, base para práticas mais avançadas de DevOps.</p>



<h2 class="wp-block-heading">Versionamento e Imagens Docker Otimizadas</h2>



<p class="wp-block-paragraph">Com a aplicação containerizada e funcionando, é hora de adotar práticas que tornam o processo mais profissional e escalável. Um dos principais aspectos nesse estágio é o <strong>versionamento das imagens</strong> e a <strong>otimização do Dockerfile</strong>, garantindo performance, segurança e controle de versões durante o ciclo de vida do projeto.</p>



<h3 class="wp-block-heading">Por que versionar as imagens?</h3>



<p class="wp-block-paragraph">Ao versionar uma imagem Docker, você evita confusões entre builds diferentes da aplicação. Isso permite, por exemplo:</p>



<ul class="wp-block-list">
<li>Identificar qual versão do container está em produção;</li>



<li>Fazer rollback em caso de falhas;</li>



<li>Executar testes A/B entre versões distintas;</li>



<li>Facilitar a integração com pipelines de CI/CD.</li>
</ul>



<p class="wp-block-paragraph">O versionamento pode ser feito no momento da construção da imagem:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker build -t app-devops:1.0.0 .
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">build</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Depois, para executar essa versão específica:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run -p 5000:5000 app-devops:1.0.0
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">5000</span><span style="color: #D8DEE9FF">:</span><span style="color: #B48EAD">5000</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Otimizando o Dockerfile</h3>



<p class="wp-block-paragraph">A criação de imagens mais enxutas e seguras impacta diretamente no tempo de build, no espaço ocupado em disco e na segurança do ambiente. Algumas boas práticas incluem:</p>



<h4 class="wp-block-heading">1. <strong>Usar imagens menores (ex: Alpine)</strong></h4>



<p class="wp-block-paragraph">Ao invés de usar <code>python:3.11</code>, que é baseada no Debian e possui muitos pacotes desnecessários, é possível utilizar:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="FROM python:3.11-alpine
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">FROM</span><span style="color: #D8DEE9FF"> python</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">3.11</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">alpine</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Essa imagem é significativamente menor, porém requer alguns ajustes nas dependências e ferramentas, pois nem tudo está disponível por padrão.</p>



<h4 class="wp-block-heading">2. <strong>Separar camadas com mais eficiência</strong></h4>



<p class="wp-block-paragraph">Cada comando em um Dockerfile cria uma camada. Agrupar instruções reduz o número de camadas e melhora o cache:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="RUN pip install --no-cache-dir -r requirements.txt
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">RUN</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">no</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">cache</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">dir</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">requirements</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading">3. <strong>Ignorar arquivos desnecessários com <code>.dockerignore</code></strong></h4>



<p class="wp-block-paragraph">Assim como o <code>.gitignore</code>, o <code>.dockerignore</code> evita que arquivos como logs, <code>.venv/</code>, <code>__pycache__/</code>, e outros diretórios desnecessários sejam incluídos na imagem:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="__pycache__/
*.pyc
.venv/
.env
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">__pycache__</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #81A1C1">*</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">pyc</span></span>
<span class="line"><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">venv</span><span style="color: #81A1C1">/</span></span>
<span class="line"><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">env</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Verificando o tamanho e camadas da imagem</h3>



<p class="wp-block-paragraph">Use o comando abaixo para investigar o tamanho da imagem criada:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker image ls
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">image</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ls</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Ou para examinar as camadas em detalhes:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker history app-devops:1.0.0
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">history</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span></span>
<span class="line"></span></code></pre></div>



<h3 class="wp-block-heading">Publicando a imagem no Docker Hub (opcional)</h3>



<p class="wp-block-paragraph">Caso deseje compartilhar sua imagem com outros membros da equipe ou utilizá-la em pipelines CI/CD, é possível enviá-la ao Docker Hub:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker tag app-devops:1.0.0 seu-usuario/app-devops:1.0.0
docker push seu-usuario/app-devops:1.0.0
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tag</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">usuario</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span></span>
<span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">push</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">usuario</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #B48EAD">1.0</span><span style="color: #ECEFF4">.</span><span style="color: #B48EAD">0</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Para isso, é necessário ter uma conta gratuita no <a href="https://hub.docker.com/">Docker Hub</a>.</p>



<h2 class="wp-block-heading">Criando um Pipeline de Integração Contínua (CI)</h2>



<p class="wp-block-paragraph">Após a containerização da aplicação e a adoção de boas práticas com Docker, é hora de automatizar o processo de build e validação utilizando <strong>Integração Contínua (Continuous Integration &#8211; CI)</strong>. O objetivo da CI é garantir que, a cada alteração feita no código, a aplicação seja testada, empacotada e validada automaticamente, reduzindo erros e acelerando o ciclo de desenvolvimento.</p>



<h3 class="wp-block-heading">O que é Integração Contínua?</h3>



<p class="wp-block-paragraph">Integração Contínua é uma prática onde os desenvolvedores enviam mudanças frequentes ao repositório, geralmente hospedado em plataformas como GitHub, GitLab ou Bitbucket. Cada commit dispara uma série de ações automáticas:</p>



<ul class="wp-block-list">
<li><strong>Download do código atualizado</strong>;</li>



<li><strong>Execução de testes automatizados</strong>;</li>



<li><strong>Construção da imagem Docker</strong>;</li>



<li><strong>Validação do build</strong>.</li>
</ul>



<p class="wp-block-paragraph">Essas ações são definidas por meio de <strong>pipelines</strong>, descritas em arquivos YAML que informam à plataforma como automatizar as etapas desejadas.</p>



<h3 class="wp-block-heading">Exemplo com GitHub Actions</h3>



<p class="wp-block-paragraph">Para projetos hospedados no GitHub, cria-se um arquivo chamado <code>ci.yml</code> dentro do diretório <code>.github/workflows/</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="name: CI DevOps Tutorial

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - name: Clonando o repositório
      uses: actions/checkout@v3

    - name: Instalando o Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'

    - name: Instalando dependências
      run: |
        python -m venv venv
        source venv/bin/activate
        pip install -r requirements.txt

    - name: Executando testes
      run: |
        source venv/bin/activate
        python -m unittest discover tests

    - name: Build da imagem Docker
      run: |
        docker build -t app-devops:ci .

" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">CI</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">DevOps</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Tutorial</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">on</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  push</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    branches</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [ </span><span style="color: #D8DEE9">main</span><span style="color: #D8DEE9FF"> ]</span></span>
<span class="line"><span style="color: #D8DEE9FF">  pull_request</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    branches</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [ </span><span style="color: #D8DEE9">main</span><span style="color: #D8DEE9FF"> ]</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">jobs</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  build</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #D8DEE9">runs</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">on</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">ubuntu</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">latest</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    steps</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Clonando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">repositório</span></span>
<span class="line"><span style="color: #D8DEE9FF">      uses</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">actions</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">checkout</span><span style="color: #D8DEE9FF">@</span><span style="color: #D8DEE9">v3</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Instalando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">o</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Python</span></span>
<span class="line"><span style="color: #D8DEE9FF">      uses</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">actions</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">setup</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">python</span><span style="color: #D8DEE9FF">@</span><span style="color: #D8DEE9">v4</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">with</span><span style="color: #D8DEE9FF">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">python</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">version</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">3.11</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Instalando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">dependências</span></span>
<span class="line"><span style="color: #D8DEE9FF">      run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">python</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">m</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">venv</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">venv</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">source</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">venv</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">bin</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">activate</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">pip</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">install</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">r</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">requirements</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">txt</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Executando</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">testes</span></span>
<span class="line"><span style="color: #D8DEE9FF">      run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">source</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">venv</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">bin</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">activate</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">python</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">m</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">unittest</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">discover</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tests</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Build</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imagem</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Docker</span></span>
<span class="line"><span style="color: #D8DEE9FF">      run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">build</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">t</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">ci</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">.</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Esse pipeline define o seguinte:</p>



<ol class="wp-block-list">
<li>O processo é acionado quando há <code>push</code> ou <code>pull request</code> na branch <code>main</code>.</li>



<li>O GitHub Actions baixa o código, instala o Python 3.11 e configura o ambiente virtual.</li>



<li>Instala as dependências e executa os testes contidos no diretório <code>tests/</code>.</li>



<li>Se os testes forem bem-sucedidos, constrói a imagem Docker.</li>
</ol>



<h3 class="wp-block-heading">Vantagens do Pipeline de CI</h3>



<ul class="wp-block-list">
<li><strong>Validação automática do código</strong>;</li>



<li><strong>Redução de erros em produção</strong>;</li>



<li><strong>Feedback imediato sobre falhas</strong>;</li>



<li><strong>Base sólida para práticas de CD (entrega contínua)</strong>.</li>
</ul>



<p class="wp-block-paragraph">Este é um passo essencial para garantir que a aplicação esteja sempre pronta para ser implantada, com qualidade e consistência.</p>



<h2 class="wp-block-heading">Entrega Contínua (CD) e Automação do Deploy</h2>



<p class="wp-block-paragraph">Após configurar a Integração Contínua (CI) para testar e construir a aplicação automaticamente, o próximo passo no fluxo DevOps é implementar a <strong>Entrega Contínua (CD – Continuous Delivery)</strong>. Essa etapa garante que o sistema esteja sempre pronto para ser implantado com segurança em produção, com processos automatizados e previsíveis.</p>



<h3 class="wp-block-heading">O que é Entrega Contínua?</h3>



<p class="wp-block-paragraph">A Entrega Contínua é uma extensão natural da Integração Contínua. Ela automatiza o processo de <strong>deploy em ambientes de teste, homologação ou produção</strong>, sempre que um novo build é aprovado. Em um fluxo bem configurado, é possível que o deploy aconteça automaticamente — ou com um simples clique de aprovação.</p>



<h3 class="wp-block-heading">Como funciona na prática?</h3>



<p class="wp-block-paragraph">Para automatizar o deploy, é comum configurar etapas adicionais no pipeline, como:</p>



<ul class="wp-block-list">
<li>Publicar a imagem Docker em um registro de containers (ex: Docker Hub, GitHub Container Registry, Amazon ECR);</li>



<li>Realizar o deploy em um ambiente controlado (ex: servidor de staging, Kubernetes, máquina virtual ou instância na nuvem);</li>



<li>Executar scripts de verificação pós-deploy (ex: health check ou rollback automático).</li>
</ul>



<h3 class="wp-block-heading">Continuando o exemplo com GitHub Actions</h3>



<p class="wp-block-paragraph">Vamos expandir o pipeline para que, após o sucesso dos testes e build, a imagem seja enviada para o Docker Hub:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="    - name: Login no Docker Hub
      run: echo &quot;${{ secrets.DOCKER_PASSWORD }}&quot; | docker login -u &quot;${{ secrets.DOCKER_USERNAME }}&quot; --password-stdin

    - name: Tag e push da imagem
      run: |
        docker tag app-devops:ci ${{ secrets.DOCKER_USERNAME }}/app-devops:latest
        docker push ${{ secrets.DOCKER_USERNAME }}/app-devops:latest
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Login</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">no</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Hub</span></span>
<span class="line"><span style="color: #D8DEE9FF">      run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">echo</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${{ secrets.DOCKER_PASSWORD }}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">login</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">u</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&quot;</span><span style="color: #A3BE8C">${{ secrets.DOCKER_USERNAME }}</span><span style="color: #ECEFF4">&quot;</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">--</span><span style="color: #D8DEE9">password</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">stdin</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">Tag</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">e</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">push</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">da</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">imagem</span></span>
<span class="line"><span style="color: #D8DEE9FF">      run</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">|</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">tag</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">ci</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">secrets</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">DOCKER_USERNAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">latest</span></span>
<span class="line"><span style="color: #D8DEE9FF">        </span><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">push</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$</span><span style="color: #ECEFF4">{{</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">secrets</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">DOCKER_USERNAME</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">}}</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">latest</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Essas etapas:</p>



<ol class="wp-block-list">
<li><strong>Autenticam-se no Docker Hub</strong> usando segredos seguros armazenados no GitHub (<code>secrets</code>).</li>



<li><strong>Tagueiam a imagem com <code>latest</code></strong> (ou uma versão, se preferir).</li>



<li><strong>Publicam a imagem no repositório Docker</strong>, tornando-a disponível para deploy em qualquer lugar.</li>
</ol>



<h3 class="wp-block-heading">Realizando o Deploy</h3>



<p class="wp-block-paragraph">Uma vez publicada, a imagem pode ser implantada com comandos simples, como:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker pull seu-usuario/app-devops:latest
docker run -d -p 80:5000 seu-usuario/app-devops:latest
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">pull</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">usuario</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">latest</span></span>
<span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">d</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">80</span><span style="color: #D8DEE9FF">:</span><span style="color: #B48EAD">5000</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">seu</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">usuario</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">app</span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF">devops</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9">latest</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Ou, em ambientes mais robustos, o deploy pode ser automatizado via:</p>



<ul class="wp-block-list">
<li><strong>Docker Compose</strong>;</li>



<li><strong>Kubernetes com Helm Charts</strong>;</li>



<li><strong>Plataformas de PaaS como Heroku, Render, ou Google Cloud Run</strong>.</li>
</ul>



<h3 class="wp-block-heading">Benefícios da Entrega Contínua</h3>



<ul class="wp-block-list">
<li><strong>Deploys mais frequentes e confiáveis</strong>;</li>



<li><strong>Menor risco de erro humano</strong>;</li>



<li><strong>Ambientes padronizados e rastreáveis</strong>;</li>



<li><strong>Maior rapidez na correção de bugs e lançamento de features</strong>.</li>
</ul>



<p class="wp-block-paragraph">A Entrega Contínua representa um marco na maturidade de equipes DevOps, sendo o elo entre o desenvolvimento ágil e a operação estável e segura.</p>



<h2 class="wp-block-heading">Monitoramento da Aplicação em Produção</h2>



<p class="wp-block-paragraph">Uma vez que a aplicação está em produção, torna-se essencial acompanhar seu comportamento em tempo real. O <strong>monitoramento contínuo</strong> permite identificar falhas rapidamente, antecipar problemas de desempenho e garantir que os usuários finais estejam tendo uma boa experiência.</p>



<p class="wp-block-paragraph">Essa prática é um dos fundamentos do DevOps moderno e deve ser implementada <strong>desde os primeiros estágios do projeto</strong>, e não apenas quando surgem erros em produção.</p>



<h3 class="wp-block-heading">O que é monitorar uma aplicação?</h3>



<p class="wp-block-paragraph">Monitorar é mais do que apenas verificar se a aplicação está “no ar”. Envolve:</p>



<ul class="wp-block-list">
<li><strong>Coleta de métricas</strong> como uso de CPU, memória, número de requisições, tempo de resposta e taxa de erro;</li>



<li><strong>Análise de logs</strong> para identificar falhas, mensagens de erro e comportamentos inesperados;</li>



<li><strong>Visualização e alertas</strong>, com dashboards e sistemas de notificação automática.</li>
</ul>



<h3 class="wp-block-heading">Ferramentas DevOps para Monitoramento</h3>



<p class="wp-block-paragraph">Algumas ferramentas populares que podem ser integradas a projetos Dockerizados e ambientes em nuvem incluem:</p>



<ul class="wp-block-list">
<li><strong>Prometheus</strong>: coleta e armazena métricas em séries temporais. Muito usado com Kubernetes.</li>



<li><strong>Grafana</strong>: cria dashboards interativos com base nos dados do Prometheus ou outras fontes.</li>



<li><strong>Loki</strong>: sistema de logs criado pelos mesmos desenvolvedores do Grafana, ideal para uso conjunto.</li>



<li><strong>ELK Stack (Elasticsearch + Logstash + Kibana)</strong>: usado para indexar e visualizar logs em larga escala.</li>
</ul>



<h3 class="wp-block-heading">Exemplo simples com Prometheus + Grafana</h3>



<p class="wp-block-paragraph">Se você está rodando a aplicação via Docker, pode usar <strong>exporters</strong> para coletar métricas. Um exemplo clássico é o <a href="https://github.com/prometheus/client_python">Prometheus Python Client</a>.</p>



<h4 class="wp-block-heading">1. Instalando o pacote no projeto</h4>



<p class="wp-block-paragraph">No <code>requirements.txt</code>, adicione:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="prometheus_client
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">prometheus_client</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">No <code>app.py</code>, adicione:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="from prometheus_client import start_http_server, Summary

REQUEST_TIME = Summary('request_processing_seconds', 'Tempo de processamento de requisições')

@app.before_first_request
def start_metrics():
    start_http_server(8000)  # Porta separada para Prometheus coletar métricas
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">from</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">prometheus_client</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">import</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">start_http_server</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Summary</span></span>
<span class="line"></span>
<span class="line"><span style="color: #8FBCBB">REQUEST_TIME</span><span style="color: #D8DEE9FF"> = </span><span style="color: #8FBCBB">Summary</span><span style="color: #D8DEE9FF">(</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">request_processing_seconds</span><span style="color: #ECEFF4">&#39;</span><span style="color: #ECEFF4">,</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">Tempo de processamento de requisições</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">)</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">@</span><span style="color: #8FBCBB">app</span><span style="color: #D8DEE9FF">.</span><span style="color: #8FBCBB">before_first_request</span></span>
<span class="line"><span style="color: #8FBCBB">def</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">start_metrics</span><span style="color: #D8DEE9FF">():</span></span>
<span class="line"><span style="color: #D8DEE9FF">    </span><span style="color: #8FBCBB">start_http_server</span><span style="color: #D8DEE9FF">(8000)  # </span><span style="color: #8FBCBB">Porta</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">separada</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">para</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">Prometheus</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">coletar</span><span style="color: #D8DEE9FF"> </span><span style="color: #8FBCBB">métricas</span></span>
<span class="line"></span></code></pre></div>



<h4 class="wp-block-heading">2. Configurando Prometheus</h4>



<p class="wp-block-paragraph">Crie um arquivo <code>prometheus.yml</code>:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="global:
  scrape_interval: 10s

scrape_configs:
  - job_name: 'flask-app'
    static_configs:
      - targets: ['localhost:8000']
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9FF">global</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  scrape_interval</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> 10</span><span style="color: #D8DEE9">s</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D8DEE9FF">scrape_configs</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">  </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> job_name</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> </span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">flask-app</span><span style="color: #ECEFF4">&#39;</span></span>
<span class="line"><span style="color: #D8DEE9FF">    static_configs</span><span style="color: #ECEFF4">:</span></span>
<span class="line"><span style="color: #D8DEE9FF">      </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9FF"> targets</span><span style="color: #ECEFF4">:</span><span style="color: #D8DEE9FF"> [</span><span style="color: #ECEFF4">&#39;</span><span style="color: #A3BE8C">localhost:8000</span><span style="color: #ECEFF4">&#39;</span><span style="color: #D8DEE9FF">]</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Inicie o Prometheus com Docker:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run -d -p 9090:9090 -v $PWD/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">d</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">9090</span><span style="color: #D8DEE9FF">:</span><span style="color: #B48EAD">9090</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">v</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">$PWD</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">prometheus</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">yml</span><span style="color: #D8DEE9FF">:</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">etc</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">prometheus</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">prometheus</span><span style="color: #ECEFF4">.</span><span style="color: #D8DEE9">yml</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">prom</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">prometheus</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Acesse <code>http://localhost:9090</code> para visualizar as métricas sendo coletadas.</p>



<h4 class="wp-block-heading">3. Visualizando com Grafana</h4>



<p class="wp-block-paragraph">Com Prometheus rodando, instale o Grafana:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#2e3440ff"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="docker run -d -p 3000:3000 grafana/grafana
" style="color:#d8dee9ff;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki nord" style="background-color: #2e3440ff" tabindex="0"><code><span class="line"><span style="color: #D8DEE9">docker</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">run</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">d</span><span style="color: #D8DEE9FF"> </span><span style="color: #81A1C1">-</span><span style="color: #D8DEE9">p</span><span style="color: #D8DEE9FF"> </span><span style="color: #B48EAD">3000</span><span style="color: #D8DEE9FF">:</span><span style="color: #B48EAD">3000</span><span style="color: #D8DEE9FF"> </span><span style="color: #D8DEE9">grafana</span><span style="color: #81A1C1">/</span><span style="color: #D8DEE9">grafana</span></span>
<span class="line"></span></code></pre></div>



<p class="wp-block-paragraph">Acesse <code>http://localhost:3000</code>, conecte ao Prometheus como fonte de dados e crie dashboards para acompanhar o tempo de resposta, volume de requisições, e muito mais.</p>



<h3 class="wp-block-heading">Por que monitorar desde o início?</h3>



<ul class="wp-block-list">
<li><strong>Reduz o tempo de detecção de falhas (MTTD)</strong>;</li>



<li><strong>Facilita decisões baseadas em dados reais</strong>;</li>



<li><strong>Melhora a experiência do usuário final</strong>;</li>



<li><strong>Ajuda a provar o valor do DevOps com indicadores claros</strong>.</li>
</ul>



<h2 class="wp-block-heading">Feedback Contínuo e Melhoria Constante</h2>



<p class="wp-block-paragraph">A última etapa — e talvez a mais crítica — do ciclo DevOps é o <strong>feedback contínuo</strong>. Sem ele, todo o esforço em automação, integração, entrega e monitoramento perde seu valor estratégico. O feedback contínuo conecta as experiências reais de uso com o time de desenvolvimento e operação, possibilitando <strong>aprendizado rápido</strong>, <strong>respostas ágeis</strong> e <strong>melhorias sustentáveis</strong> ao longo do tempo.</p>



<h3 class="wp-block-heading">O que é feedback contínuo?</h3>



<p class="wp-block-paragraph">No contexto DevOps, feedback contínuo é o processo de <strong>coletar informações em tempo real</strong> sobre o comportamento do sistema em produção e compartilhar essas informações com todos os envolvidos:</p>



<ul class="wp-block-list">
<li>Desenvolvedores;</li>



<li>Engenheiros de operações;</li>



<li>Analistas de negócios;</li>



<li>Responsáveis por produto;</li>



<li>E até usuários finais (indiretamente, por meio de métricas de uso).</li>
</ul>



<h3 class="wp-block-heading">Fontes de feedback no ciclo DevOps</h3>



<p class="wp-block-paragraph">O feedback pode vir de diversas fontes:</p>



<ul class="wp-block-list">
<li><strong>Logs e métricas</strong> (via Prometheus, Grafana, Loki, etc.);</li>



<li><strong>Alertas de monitoramento</strong> (ex: erros 500, lentidão, uso excessivo de CPU);</li>



<li><strong>Feedback dos usuários</strong> via canais de suporte, UX, redes sociais;</li>



<li><strong>Relatórios de CI/CD</strong>, como testes quebrando após merge;</li>



<li><strong>Acompanhamento de deploys e rollback</strong>.</li>
</ul>



<h3 class="wp-block-heading">Como utilizar o feedback de forma eficaz</h3>



<ol class="wp-block-list">
<li><strong>Automatize a coleta e exibição</strong>: dashboards claros, alertas inteligentes e integração com canais como Slack ou e-mail ajudam a manter o time informado.</li>



<li><strong>Integre o feedback à cultura da equipe</strong>: reuniões rápidas (como daily meetings) podem incluir uma visão rápida dos indicadores e eventos recentes.</li>



<li><strong>Aja rapidamente sobre os dados recebidos</strong>: não basta coletar — o mais importante é <strong>agir</strong> com base no que se aprende. Se uma feature nova aumentou o tempo de resposta, revise. Se um bug surgiu após um deploy, resolva e documente.</li>



<li><strong>Itere com base em dados, não suposições</strong>: DevOps é sobre melhoria contínua. Métricas reais substituem achismos e ajudam a tomar decisões mais sólidas.</li>
</ol>



<h3 class="wp-block-heading">Ferramentas que auxiliam o feedback contínuo</h3>



<ul class="wp-block-list">
<li><strong>Grafana</strong>: dashboards de métricas e alertas.</li>



<li><strong>Elastic/Kibana ou Loki</strong>: visualização e análise de logs.</li>



<li><strong>Sentry</strong>: rastreamento de exceções e falhas front-end/back-end.</li>



<li><strong>Google Analytics / Matomo</strong>: comportamento de usuários.</li>



<li><strong>GitHub Issues / Jira</strong>: rastreamento de feedback de usuários e bugs.</li>
</ul>



<h2 class="wp-block-heading">Conclusão do Tutorial</h2>



<p class="wp-block-paragraph">Com este ciclo completo — planejamento, desenvolvimento, integração, entrega, operação, monitoramento e feedback — você experimentou a essência do DevOps. Mais do que uma lista de ferramentas ou práticas, DevOps é uma <strong>cultura de colaboração e melhoria contínua</strong>, que ajuda organizações a entregarem <strong>mais valor com mais velocidade e menos riscos</strong>.</p>



<p class="wp-block-paragraph">Ao longo do tutorial, você:</p>



<ul class="wp-block-list">
<li>Criou uma aplicação Python e preparou seu ambiente;</li>



<li>Empacotou a aplicação com Docker;</li>



<li>Automatizou os testes e o build com CI;</li>



<li>Realizou o deploy com práticas de CD;</li>



<li>Monitorou a aplicação em produção;</li>



<li>E finalmente, fechou o ciclo com feedback contínuo.</li>
</ul>



<p class="wp-block-paragraph">Este é apenas o começo. A partir daqui, você pode explorar temas como:</p>



<ul class="wp-block-list">
<li>Orquestração com Kubernetes;</li>



<li>Pipelines avançadas de CI/CD com GitLab ou Jenkins;</li>



<li>Segurança DevSecOps;</li>



<li>Observabilidade com OpenTelemetry;</li>



<li>e muito mais.</li>
</ul>



<ul class="wp-block-list">
<li></li>
</ul>



<h2 class="wp-block-heading">Repositórios da Alura para este Tutorial:</h2>



<ul class="wp-block-list">
<li>https://github.com/guilhermeonrails/ellis</li>



<li>https://github.com/guilhermeonrails/refactored-octo-chainsaw</li>
</ul><p>The post <a href="https://mcu.tec.br/infraestrutura/tutorial-completo-de-cloud-devops-com-docker-ci-cd-e-monitoramento-parte-1/">Tutorial Completo de Cloud DevOps com Docker, CI/CD e Monitoramento – Parte 1</a> first appeared on <a href="https://mcu.tec.br">MCU & FPGA</a>.</p>]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">560</post-id>	</item>
	</channel>
</rss>
