<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Blog by Roxs]]></title><description><![CDATA[Blog técnico sobre DevOps, Cloud, Linux e IA donde comparto guías prácticas, automatización real y experiencias de despliegue en producción. Aprendé desde las bases hasta la nube, construyendo criterio y habilidades reales paso a paso.]]></description><link>https://blog.295devops.com</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1729291802071/55292506-6cd5-40ea-92cb-8a9be800d327.png</url><title>Blog by Roxs</title><link>https://blog.295devops.com</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 15:27:37 GMT</lastBuildDate><atom:link href="https://blog.295devops.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Terraform MCP Server: tu IA ya sabe leer el Registry (y vos podés tomar mate)]]></title><description><![CDATA[Acordate de la última vez que escribiste un recurso de Terraform que no usabas hace tres meses. Abriste el Registry. Buscaste el provider. Entraste a la doc. Chequeaste qué atributos eran requeridos e]]></description><link>https://blog.295devops.com/terraform-mcp-server-tu-ia-ya-sabe-leer-el-registry-y-vos-pod-s-tomar-mate</link><guid isPermaLink="true">https://blog.295devops.com/terraform-mcp-server-tu-ia-ya-sabe-leer-el-registry-y-vos-pod-s-tomar-mate</guid><category><![CDATA[Devops]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 18 Apr 2026 21:29:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/620c453d7cf10d2765e28b6c/c5e4c92b-6b70-49e9-b5d6-785b26785e9b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Acordate de la última vez que escribiste un recurso de Terraform que no usabas hace tres meses. Abriste el Registry. Buscaste el provider. Entraste a la doc. Chequeaste qué atributos eran requeridos en la versión actual. Volviste al editor. Escribiste mal el nombre. Volviste al Registry. Copiaste el snippet. El snippet estaba deprecado.</p>
<p>Eso se llama contexto switching. Y mata la productividad más silenciosamente que un merge conflict un viernes a las 6pm.</p>
<p>Hoy arrancamos una serie para erradicarlo. Y el primer episodio tiene protagonista: el <strong>Terraform MCP Server</strong>.</p>
<hr />
<h2>¿Qué es MCP y por qué te debería importar?</h2>
<p>MCP son las siglas de <strong>Model Context Protocol</strong> un estándar abierto que le permite a los modelos de AI conectarse de forma segura con herramientas externas, aplicaciones y fuentes de datos. La idea es simple y poderosa: en vez de que la IA trabaje solo con lo que aprendió hasta su fecha de corte, puede consultar información actualizada en tiempo real.</p>
<p>HashiCorp lanzó su propio MCP Server para Terraform y es exactamente lo que el nombre promete: un servidor que le da a tu IA acceso directo al Terraform Registry. Providers, módulos, políticas Sentinel, workspaces de HCP Terraform todo disponible en el momento en que lo necesitás, desde tu IDE, sin cambiar de pantalla.</p>
<blockquote>
<p>"En vez de que la IA adivine cómo se configura un <code>aws_s3_bucket</code> con la versión actual del provider, le pregunta al Registry directamente."</p>
</blockquote>
<p>Está en <strong>beta</strong> (v0.5.x), pero ya funciona muy bien para el día a día.</p>
<blockquote>
<p>Pensalo como el "USB-C" de los agentes de AI: un protocolo universal para enchufar contexto.</p>
</blockquote>
<p>Acá el diagrama de arquitectura completo:</p>
<img src="https://cdn.hashnode.com/uploads/covers/620c453d7cf10d2765e28b6c/70d12a4b-5250-48ee-a22e-e5a0ad3919ba.svg" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Cómo funciona por dentro</h2>
<p>El flujo es así:</p>
<pre><code class="language-plaintext">Vos escribís un prompt en tu IDE
         ↓
    IA Agent (Copilot / Cursor / Claude)
         ↓
    Terraform MCP Server
         ↓
    Terraform Registry (docs actualizadas, en vivo)
         ↓
    HCL correcto en tu editor
</code></pre>
<p>Los componentes clave que necesitás entender:</p>
<ul>
<li><p><strong>MCP Host</strong>: tu IDE (VS Code, Cursor) o app como Claude Desktop</p>
</li>
<li><p><strong>MCP Client</strong>: el agente de AI que interpreta tus prompts</p>
</li>
<li><p><strong>MCP Server</strong>: el servidor de Terraform que expone las herramientas</p>
</li>
<li><p><strong>Transport</strong>: cómo se comunican — por defecto usa <code>stdio</code> (stdin/stdout), también soporta HTTP streamable para deployments remotos</p>
</li>
</ul>
<p>El MCP Server tiene tres toolsets principales:</p>
<table>
<thead>
<tr>
<th>Toolset</th>
<th>Para qué sirve</th>
</tr>
</thead>
<tbody><tr>
<td><code>registry</code></td>
<td>Registry público de Terraform</td>
</tr>
<tr>
<td><code>registry-private</code></td>
<td>Registry privado de tu organización</td>
</tr>
<tr>
<td><code>terraform</code></td>
<td>HCP Terraform y Terraform Enterprise</td>
</tr>
</tbody></table>
<p>Y dentro de <code>registry</code>, los tools que vas a usar más seguido son:</p>
<ul>
<li><p><code>search_providers</code> — busca documentación por servicio</p>
</li>
<li><p><code>get_provider_details</code> — documentación completa de un recurso</p>
</li>
<li><p><code>search_modules</code> — encuentra módulos por nombre o funcionalidad</p>
</li>
<li><p><code>get_module_details</code> — inputs, outputs, ejemplos, submódulos</p>
</li>
</ul>
<p>Lo mejor: <strong>no los invocás manualmente</strong>. El agente los usa automáticamente cuando le hacés una pregunta relevante.</p>
<img src="https://cdn.hashnode.com/uploads/covers/620c453d7cf10d2765e28b6c/95e6806e-8a62-4d19-a477-d9b9d014f76f.svg" alt="" style="display:block;margin:0 auto" />

<blockquote>
<p><strong>Sin MCP</strong> → la AI es como un empleado muy listo que estudió todo de memoria antes de entrar, pero que lleva 6 meses sin actualizar su conocimiento. Si le preguntás por un provider de Terraform que cambió el mes pasado, te va a dar la versión vieja... o directamente inventar algo que suena bien pero no existe.</p>
<p><strong>Con MCP</strong> → ese mismo empleado ahora tiene una computadora conectada a internet, a tu GitLab, a AWS, al Terraform Registry. Antes de responderte, va y busca la información real. No adivina, no recuerda mal: consulta la fuente directamente.</p>
</blockquote>
<hr />
<h2>Setup en 5 minutos (en serio, 5 minutos)</h2>
<p>Tenés tres opciones de instalación:</p>
<table>
<thead>
<tr>
<th>Método</th>
<th>Cuándo usarlo</th>
</tr>
</thead>
<tbody><tr>
<td>Docker</td>
<td>La mayoría de los casos. Consistente en cualquier entorno</td>
</tr>
<tr>
<td>Binary compilado</td>
<td>Si no querés Docker en el mix</td>
</tr>
<tr>
<td>Desde source</td>
<td>Si querés tocar el código o contribuir</td>
</tr>
</tbody></table>
<p>Vamos con <strong>Docker</strong> que es la más portable.</p>
<h3>Prerequisitos</h3>
<ul>
<li><p>Docker corriendo</p>
</li>
<li><p>VS Code con la extensión GitHub Copilot en modo Agent, <strong>o</strong> Cursor con MCP habilitado</p>
</li>
<li><p>Ganas de dejar de abrir tabs</p>
</li>
</ul>
<h3>Paso 1: Pull de la imagen</h3>
<pre><code class="language-bash">docker pull hashicorp/terraform-mcp-server:latest
</code></pre>
<h3>Paso 2: Configuración en VS Code</h3>
<p>Creá la carpeta <code>.vscode</code> en tu proyecto y adentro el archivo <code>mcp.json</code>:</p>
<pre><code class="language-json">{
  "servers": {
    "terraform": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "hashicorp/terraform-mcp-server"
      ]
    }
  }
}
</code></pre>
<p>Guardás el archivo. VS Code te va a mostrar un link <code>start</code> debajo de <code>"servers"</code>. Lo clickeás. El container arranca.</p>
<blockquote>
<p>⚠️ <strong>Tip de campo:</strong> No uses el botón "Add Server..." de la UI de VS Code. La experiencia guiada es confusa y no siempre funciona bien. Pegá el JSON directamente.</p>
</blockquote>
<h3>Paso 3: Verificar que el agente lo ve</h3>
<p>Abrís GitHub Copilot Chat, te asegurás de estar en modo <strong>Agent</strong>, y clickeás el ícono de herramientas. Debería aparecerte <code>terraform-mcp-server</code> con todos sus tools habilitados.</p>
<h3>Configuración para Cursor</h3>
<p>En Cursor, editás tu <code>settings.json</code> de usuario:</p>
<pre><code class="language-json">{
  "mcp": {
    "servers": {
      "terraform": {
        "command": "docker",
        "args": [
          "run",
          "-i",
          "--rm",
          "hashicorp/terraform-mcp-server"
        ]
      }
    }
  }
}
</code></pre>
<p>Después: Settings → MCP → verificar que Terraform MCP Server aparezca con tools activos.</p>
<h3>¿Usás HCP Terraform o Terraform Enterprise?</h3>
<p>Agregás las variables de entorno en el config:</p>
<pre><code class="language-json">{
  "servers": {
    "terraform": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "TFE_TOKEN=tu-token-aqui",
        "-e", "TFE_ADDRESS=https://app.terraform.io",
        "hashicorp/terraform-mcp-server"
      ]
    }
  }
}
</code></pre>
<p>Con esto el MCP Server también puede listar tus workspaces, runs y módulos privados.</p>
<img src="https://cdn.hashnode.com/uploads/covers/620c453d7cf10d2765e28b6c/851ecc42-f036-4778-829a-fa32a4bc8cc4.gif" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Laboratorio: hacelo vos ahora mismo</h2>
<p>Ya tenés el MCP corriendo. Hora de probarlo con algo concreto y sin dependencias de nube sin AWS, sin credenciales, sin nada. Solo Terraform y tu filesystem local.</p>
<p>Copiá este prompt exacto en tu agente:</p>
<pre><code class="language-plaintext">Usa Terraform MCP para revisar el provider hashicorp/local 
y luego genera un ejemplo mínimo funcional en Terraform.
</code></pre>
<p>El agente va a llamar a <code>search_providers</code> con <code>hashicorp/local</code>, después a <code>get_provider_details</code> para ver los recursos disponibles, y te va a devolver algo así:</p>
<pre><code class="language-hcl">terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~&gt; 2.5"
    }
  }
}
 
# Crea un archivo de texto en tu sistema local
resource "local_file" "ejemplo" {
  content  = "Hola desde Terraform MCP 🔥"
  filename = "${path.module}/output.txt"
}
 
# Lee un archivo existente (data source)
data "local_file" "leeme" {
  filename = "${path.module}/output.txt"
}
 
output "contenido" {
  value = local_file.ejemplo.content
}
</code></pre>
<p>Guardás eso en un <code>main.tf</code>, y ejecutás:</p>
<pre><code class="language-bash">terraform init
terraform apply -auto-approve
cat output.txt
</code></pre>
<img src="https://cdn.hashnode.com/uploads/covers/620c453d7cf10d2765e28b6c/bbea5545-3066-4eca-b948-f73726da4e6d.gif" alt="" style="display:block;margin:0 auto" />

<p><strong>¿Qué acaba de pasar?</strong></p>
<p>El agente no usó su memoria de entrenamiento para saber qué atributos acepta <code>local_file</code>. Consultó el Registry en tiempo real vía MCP, obtuvo la documentación actualizada del provider <code>hashicorp/local</code> v2.5, y generó HCL válido contra esa versión específica.</p>
<p>Resultado: un archivo <code>output.txt</code> en tu directorio con el contenido que le pediste. Sin abrir el Registry. Sin chequear si <code>content</code> o <code>file_content</code> era el atributo correcto en esta versión.</p>
<blockquote>
<p>💡 <strong>Por qué este ejemplo importa:</strong> <code>hashicorp/local</code> es el provider más sencillo que existe en Terraform — no necesita credenciales de nube ni configuración extra. Si el MCP funciona acá, funciona en cualquier otro provider. Es el hello world perfecto para validar que el setup está bien antes de meterle AWS, GCP o Azure.</p>
</blockquote>
<hr />
<h2>Demo: S3 con versioning y lifecycle policy, sin abrir el Registry</h2>
<p>Este es el momento que justifica todo el setup.</p>
<p><strong>Antes del MCP Server</strong>, el workflow era así:</p>
<ol>
<li><p>Abrir el Terraform Registry</p>
</li>
<li><p>Buscar <code>aws_s3_bucket</code></p>
</li>
<li><p>Buscar <code>aws_s3_bucket_versioning</code> (porque ya no va en el mismo recurso, cambió en el provider v4)</p>
</li>
<li><p>Buscar <code>aws_s3_bucket_lifecycle_configuration</code></p>
</li>
<li><p>Copiar snippets</p>
</li>
<li><p>Pegar en el editor</p>
</li>
<li><p>Descubrir que estás usando atributos deprecados</p>
</li>
<li><p>Volver al Registry</p>
</li>
<li><p>Rezar</p>
</li>
</ol>
<p><strong>Con el MCP Server</strong>, le escribís esto a tu agente:</p>
<pre><code class="language-plaintext">How do I configure an AWS S3 bucket with versioning enabled and a 
lifecycle policy that moves objects to Glacier after 90 days?
Use the latest version of the AWS provider.
</code></pre>
<p>El agente llama a <code>search_providers</code> para encontrar el provider de AWS, después a <code>get_provider_details</code> para cada recurso relevante, y te devuelve esto:</p>
<pre><code class="language-hcl">terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&gt; 5.0"
    }
  }
}

resource "aws_s3_bucket" "example" {
  bucket = "mi-bucket-con-versioning"
}

resource "aws_s3_bucket_versioning" "example" {
  bucket = aws_s3_bucket.example.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_lifecycle_configuration" "example" {
  bucket = aws_s3_bucket.example.id

  rule {
    id     = "mover-a-glacier"
    status = "Enabled"

    transition {
      days          = 90
      storage_class = "GLACIER"
    }
  }
}
</code></pre>
<p>HCL correcto. Recursos separados según la estructura actual del provider v5. Sin atributos deprecados. Sin tabs extras abiertas.</p>
<p>¿La diferencia que más importa? Como el MCP consulta el Registry <strong>en tiempo real</strong>, no te va a devolver el esquema de la versión 3 del provider AWS que aprendió hace meses. Te da lo que está vigente hoy.</p>
<hr />
<h2>Una nota sobre seguridad (no la saltees)</h2>
<p>El MCP Server es una herramienta poderosa. Algunas consideraciones antes de usarlo en un entorno de equipo:</p>
<p><strong>Corrélo local.</strong> La recomendación oficial es correrlo en <code>127.0.0.1</code> vía STDIO o HTTP Streamable. No expongas el servidor directamente a internet.</p>
<p><strong>Permisos mínimos para el</strong> <code>TFE_TOKEN</code><strong>.</strong> Si lo configurás con HCP Terraform, dale al token solo los permisos que necesita. Nada más.</p>
<p><code>ENABLE_TF_OPERATIONS</code> <strong>está OFF por defecto, y con razón.</strong> Esta variable habilita operaciones destructivas como <code>auto_approve</code> y <code>is_destroy</code>. No la toques hasta entender bien qué hace. Lo cubrimos en detalle en el Episodio 6.</p>
<p><strong>Rate limiting.</strong> Si lo usás en equipo o de forma intensiva, configurá los límites de requests para no saturar el Registry:</p>
<pre><code class="language-bash">MCP_RATE_LIMIT_GLOBAL=10:20   # 10 req/seg, burst de 20
MCP_RATE_LIMIT_SESSION=5:10   # por sesión
</code></pre>
<hr />
<h2>Lo que acabás de conectar</h2>
<p>Con este setup tenés un agente que:</p>
<p>✅ Sabe qué resources existen en cualquier provider de Terraform, en la versión actual<br />✅ Puede buscar y recomendar módulos del Registry según lo que necesitás<br />✅ Genera HCL válido sin depender de datos de entrenamiento desactualizados<br />✅ Puede hablar con tus workspaces de HCP Terraform si lo configurás</p>
<p>Y todo desde tu IDE. Sin cambiar de pantalla. Sin abrir el Registry manualmente.</p>
<hr />
<p><a class="embed-card" href="https://youtu.be/UKrf6qyfyoo">https://youtu.be/UKrf6qyfyoo</a></p>

<h2>Próximo episodio</h2>
<p><strong>Episodio 2 → Escribí módulos de Terraform sin acordarte de la sintaxis</strong></p>
<p>Workflow completo con MCP + Cursor en modo Agent para crear módulos reutilizables desde cero. Inputs, outputs, variables — todo generado y validado contra el Registry en tiempo real. Y lo más importante: qué pasa cuando el agente se equivoca y cómo corregirlo sin perder el hilo.</p>
<hr />
<p><em>¿Te resultó útil? Compartilo con ese colega que todavía tiene 20 tabs del Registry abiertas.</em></p>
<p><em>Seguime en</em> <a href="https://blog.295devops.com">blog.295devops.com</a> <em>para el resto de la serie.</em></p>
<hr />
<p><strong>Recursos</strong></p>
<ul>
<li><p><a href="https://developer.hashicorp.com/terraform/mcp-server">Terraform MCP Server — Documentación oficial</a></p>
</li>
<li><p><a href="https://github.com/hashicorp/terraform-mcp-server">Repositorio en GitHub</a></p>
</li>
<li><p><a href="https://developer.hashicorp.com/terraform/mcp-server/reference">Referencia de tools y variables de entorno</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Agregar colores a los scripts de Bash]]></title><description><![CDATA[Cualquiera que haya trabajado con pipelines de CI/CD o scripts de automatización sabe lo frustrante que es leer un muro de texto blanco sobre negro tratando de encontrar dónde algo salió mal. Esto me ]]></description><link>https://blog.295devops.com/agregar-colores-a-los-scripts-de-bash</link><guid isPermaLink="true">https://blog.295devops.com/agregar-colores-a-los-scripts-de-bash</guid><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 21 Feb 2026 20:56:07 GMT</pubDate><enclosure url="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/620c453d7cf10d2765e28b6c/dd8c6f14-5891-47dd-9600-8e71345c07cb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cualquiera que haya trabajado con pipelines de CI/CD o scripts de automatización sabe lo frustrante que es leer un muro de texto blanco sobre negro tratando de encontrar dónde algo salió mal. Esto me llevó a explorar a fondo la coloración de salida en Bash, y lo que encontré fue sorprendentemente simple y poderoso.</p>
<p>En esta entrada vamos a cubrir todo lo que necesitas saber para darle vida a tus scripts con color: desde los fundamentos de los códigos ANSI hasta patrones avanzados que puedes reutilizar en tus proyectos.</p>
<hr />
<h2>¿Por qué colorear la salida de tus scripts?</h2>
<p>Antes de entrar en el código, vale la pena reflexionar sobre por qué esto importa. Cuando ejecutas un script que despliega infraestructura, corre pruebas o gestiona contenedores, la cantidad de output puede ser abrumadora. Los colores te permiten:</p>
<ul>
<li><p><strong>Identificar errores al instante</strong>: rojo para fallos, verde para éxito.</p>
</li>
<li><p><strong>Separar secciones lógicas</strong>: cada fase de tu pipeline puede tener su propio color.</p>
</li>
<li><p><strong>Mejorar la experiencia del usuario</strong>: si otros desarrolladores usan tus scripts, agradecerán la claridad visual.</p>
</li>
<li><p><strong>Reducir el tiempo de depuración</strong>: encontrar el problema en un log colorizado es exponencialmente más rápido.</p>
</li>
</ul>
<blockquote>
<p>En el contexto de DevOps, donde la automatización es el pan de cada día, esto no es un lujo — es productividad real.</p>
</blockquote>
<hr />
<h2>Los códigos de escape ANSI: la base de todo</h2>
<p>La magia detrás de los colores en la terminal son los <strong>códigos de escape ANSI</strong>. El estándar ANSI (American National Standards Institute) define una serie de secuencias de caracteres que las terminales interpretan como instrucciones de formato en lugar de texto visible.</p>
<p>La estructura básica de una secuencia de escape es:</p>
<pre><code class="language-plaintext">\e[CODIGOm
</code></pre>
<p>Donde:</p>
<ul>
<li><p><code>\e</code> (o <code>\033</code> en octal, o <code>\x1b</code> en hexadecimal) inicia la secuencia de escape.</p>
</li>
<li><p><code>[</code> abre la secuencia CSI (Control Sequence Introducer).</p>
</li>
<li><p><code>CODIGO</code> es el número que define el color o estilo.</p>
</li>
<li><p><code>m</code> cierra la secuencia.</p>
</li>
</ul>
<h3>Tabla de colores de primer plano (texto)</h3>
<table style="min-width:75px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Color</p></th><th><p>Código de primer plano</p></th><th><p>Código de fondo</p></th></tr><tr><td><p>Negro</p></td><td><p>30</p></td><td><p>40</p></td></tr><tr><td><p>Rojo</p></td><td><p>31</p></td><td><p>41</p></td></tr><tr><td><p>Verde</p></td><td><p>32</p></td><td><p>42</p></td></tr><tr><td><p>Amarillo</p></td><td><p>33</p></td><td><p>43</p></td></tr><tr><td><p>Azul</p></td><td><p>34</p></td><td><p>44</p></td></tr><tr><td><p>Magenta</p></td><td><p>35</p></td><td><p>45</p></td></tr><tr><td><p>Cian</p></td><td><p>36</p></td><td><p>46</p></td></tr><tr><td><p>Gris claro</p></td><td><p>37</p></td><td><p>47</p></td></tr><tr><td><p>Gris oscuro</p></td><td><p>90</p></td><td><p>100</p></td></tr><tr><td><p>Rojo claro</p></td><td><p>91</p></td><td><p>101</p></td></tr><tr><td><p>Verde claro</p></td><td><p>92</p></td><td><p>102</p></td></tr><tr><td><p>Amarillo claro</p></td><td><p>93</p></td><td><p>103</p></td></tr><tr><td><p>Azul claro</p></td><td><p>94</p></td><td><p>104</p></td></tr><tr><td><p>Magenta claro</p></td><td><p>95</p></td><td><p>105</p></td></tr><tr><td><p>Cian claro</p></td><td><p>96</p></td><td><p>106</p></td></tr><tr><td><p>Blanco</p></td><td><p>97</p></td><td><p>107</p></td></tr></tbody></table>

<h3>Códigos de estilo (no relacionados con color)</h3>
<table style="min-width:50px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Código</p></th><th><p>Descripción</p></th></tr><tr><td><p>0</p></td><td><p>Restablecer/Normal</p></td></tr><tr><td><p>1</p></td><td><p>Texto en <strong>negrita</strong></p></td></tr><tr><td><p>2</p></td><td><p>Texto tenue</p></td></tr><tr><td><p>3</p></td><td><p>Texto en <em>cursiva</em></p></td></tr><tr><td><p>4</p></td><td><p>Texto subrayado</p></td></tr><tr><td><p>5</p></td><td><p>Texto parpadeante</p></td></tr><tr><td><p>7</p></td><td><p>Invertir colores</p></td></tr><tr><td><p>8</p></td><td><p>Texto oculto</p></td></tr><tr><td><p>9</p></td><td><p>Texto tachado</p></td></tr></tbody></table>

<hr />
<h2>Tu primer texto en color</h2>
<p>El comando <code>echo</code> imprime texto en la terminal. Para que interprete las secuencias de escape ANSI, necesitamos la opción <code>-e</code>:</p>
<pre><code class="language-bash">echo -e "\e[31mTexto en rojo\e[0m"
</code></pre>
<p>Desglosemos esto:</p>
<ul>
<li><p><code>\e[31m</code> → Activa el color rojo (código 31 de primer plano).</p>
</li>
<li><p><code>Texto en rojo</code> → El contenido que se mostrará en rojo.</p>
</li>
<li><p><code>\e[0m</code> → Restablece el formato a la normalidad (código 0).</p>
</li>
</ul>
<blockquote>
<p>⚠️ <strong>Importante</strong>: El <code>\e[0m</code> al final es crucial. Sin él, todo el texto que imprimas después en esa sesión de terminal aparecerá en rojo. Siempre cierra tus secuencias de color.</p>
</blockquote>
<hr />
<h2>Usando variables para mayor legibilidad</h2>
<p>Escribir <code>\e[31m</code> cada vez que quieres rojo no es práctico ni legible. La solución es almacenar los códigos en variables:</p>
<pre><code class="language-bash">RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
MAGENTA="\e[35m"
CYAN="\e[36m"
ENDCOLOR="\e[0m"

echo -e "\({RED}Error: algo salió mal\){ENDCOLOR}"
echo -e "\({GREEN}Éxito: despliegue completado\){ENDCOLOR}"
echo -e "\({YELLOW}Advertencia: revisa la configuración\){ENDCOLOR}"
</code></pre>
<p>Ahora el código es mucho más expresivo. Cualquiera que lo lea entiende inmediatamente la intención.</p>
<h3>Script básico completo</h3>
<pre><code class="language-bash">#! /usr/bin/env bash

RED="\e[31m"
GREEN="\e[32m"
ENDCOLOR="\e[0m"

echo -e "\({RED}This is some red text, \){ENDCOLOR}"
echo -e "\({GREEN}And this is some green text\){ENDCOLOR}"
</code></pre>
<hr />
<h2>Combinando estilos y colores</h2>
<p>Aquí es donde la cosa se pone interesante. Puedes combinar múltiples códigos separándolos con punto y coma (<code>;</code>) dentro de una sola secuencia de escape:</p>
<pre><code class="language-plaintext">\e[ESTILO;COLORm
</code></pre>
<p>Por ejemplo:</p>
<pre><code class="language-bash">#! /usr/bin/env bash

RED="31"
GREEN="32"
BOLDGREEN="\e[1;${GREEN}m"
ITALICRED="\e[3;${RED}m"
ENDCOLOR="\e[0m"

echo -e "\({BOLDGREEN}Behold! Bold, green text.\){ENDCOLOR}"
echo -e "\({ITALICRED}Italian italics\){ENDCOLOR}"
</code></pre>
<p>Observa cómo separamos el código de estilo del código de color: <code>1;32</code> significa "negrita + verde". Puedes incluso combinar tres o más códigos: <code>\e[1;4;31m</code> te daría texto <strong>rojo, negrita y subrayado</strong>.</p>
<h3>Más combinaciones útiles</h3>
<pre><code class="language-bash">BOLD="\e[1m"
DIM="\e[2m"
UNDERLINE="\e[4m"
BLINK="\e[5m"
REVERSE="\e[7m"
STRIKETHROUGH="\e[9m"

BOLD_RED="\e[1;31m"
UNDERLINE_BLUE="\e[4;34m"
BOLD_YELLOW_ON_RED="\e[1;33;41m"  # Texto amarillo negrita sobre fondo rojo
</code></pre>
<hr />
<h2>Color de fondo</h2>
<p>Los códigos de fondo (40-47 y 100-107) se usan de la misma forma. Puedes combinarlos con colores de texto:</p>
<pre><code class="language-bash"># Texto blanco sobre fondo rojo (ideal para errores críticos)
echo -e "\e[97;41m CRITICAL ERROR \e[0m Something broke badly"

# Texto negro sobre fondo amarillo (ideal para advertencias)
echo -e "\e[30;43m WARNING \e[0m Check your configuration"

# Texto negro sobre fondo verde (ideal para éxito)
echo -e "\e[30;42m SUCCESS \e[0m Deployment completed"
</code></pre>
<p>Este patrón de "badges" o etiquetas de color es muy común en herramientas CLI profesionales.</p>
<hr />
<h2>Colores de 256 colores y RGB (True Color)</h2>
<p>Las terminales modernas soportan más que los 16 colores básicos ANSI.</p>
<h3>256 colores</h3>
<p>Puedes acceder a una paleta de 256 colores usando:</p>
<pre><code class="language-bash"># Primer plano: \e[38;5;COLORm
# Fondo:        \e[48;5;COLORm

echo -e "\e[38;5;208mTexto naranja (color 208)\e[0m"
echo -e "\e[48;5;27mFondo azul intenso\e[0m"
</code></pre>
<p>Los valores van de 0 a 255, donde 0-7 son los colores estándar, 8-15 son los colores brillantes, 16-231 es un cubo de color 6×6×6, y 232-255 son tonos de gris.</p>
<h3>True Color (24-bit RGB)</h3>
<p>Si tu terminal lo soporta (la mayoría de las modernas lo hacen), puedes usar colores RGB exactos:</p>
<pre><code class="language-bash"># Primer plano: \e[38;2;R;G;Bm
# Fondo:        \e[48;2;R;G;Bm

echo -e "\e[38;2;255;100;0mNaranja personalizado\e[0m"
echo -e "\e[38;2;0;200;255mAzul cielo\e[0m"
</code></pre>
<p>Esto te da acceso a más de 16 millones de colores.</p>
<hr />
<h2>Alternativas a <code>\e</code>: compatibilidad entre terminales</h2>
<p>Aunque <code>\e</code> funciona en la mayoría de las terminales modernas, existen alternativas más portables:</p>
<table style="min-width:50px"><colgroup><col style="min-width:25px"></col><col style="min-width:25px"></col></colgroup><tbody><tr><th><p>Secuencia</p></th><th><p>Descripción</p></th></tr><tr><td><p><code>\e</code></p></td><td><p>Funciona en la mayoría de terminales modernas</p></td></tr><tr><td><p><code>\033</code></p></td><td><p>Notación octal, más portable</p></td></tr><tr><td><p><code>\x1b</code></p></td><td><p>Notación hexadecimal</p></td></tr><tr><td><p><code>$'\e'</code></p></td><td><p>Sintaxis ANSI-C quoting de Bash</p></td></tr></tbody></table>

<p>Si necesitas máxima compatibilidad, usa <code>\033</code>:</p>
<pre><code class="language-bash">RED="\033[31m"
ENDCOLOR="\033[0m"
echo -e "\({RED}Compatible con más terminales\){ENDCOLOR}"
</code></pre>
<p>O usa el comando <code>tput</code>, que consulta la base de datos terminfo de tu sistema:</p>
<pre><code class="language-bash">RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
BOLD=$(tput bold)
RESET=$(tput sgr0)

echo "\({RED}Rojo con tput\){RESET}"
echo "\({BOLD}\){GREEN}Verde negrita${RESET}"
</code></pre>
<p>La ventaja de <code>tput</code> es que genera la secuencia correcta para cada terminal automáticamente.</p>
<hr />
<h2>Patrón práctico: funciones de logging con color</h2>
<p>En lugar de usar variables sueltas, un patrón más profesional es crear funciones de logging reutilizables:</p>
<pre><code class="language-bash">#! /usr/bin/env bash

# --- Colores ---
RED="\e[31m"
GREEN="\e[32m"
YELLOW="\e[33m"
BLUE="\e[34m"
BOLD="\e[1m"
DIM="\e[2m"
ENDCOLOR="\e[0m"

# --- Funciones de logging ---
log_info() {
    echo -e "\({BLUE}[INFO]\){ENDCOLOR} $1"
}

log_success() {
    echo -e "\({GREEN}[OK]\){ENDCOLOR} $1"
}

log_warning() {
    echo -e "\({YELLOW}[WARN]\){ENDCOLOR} $1"
}

log_error() {
    echo -e "\({RED}[ERROR]\){ENDCOLOR} $1"
}

log_step() {
    echo -e "\({BOLD}\){BLUE}==&gt;\({ENDCOLOR}\){BOLD} \(1\){ENDCOLOR}"
}

# --- Uso ---
log_step "Iniciando despliegue..."
log_info "Conectando al cluster de Kubernetes..."
log_success "Conexión establecida"
log_warning "La imagen no tiene tag específico, usando :latest"
log_error "Fallo al aplicar el manifiesto: timeout después de 30s"
</code></pre>
<p>Este patrón es extremadamente útil para scripts de CI/CD, hooks de Git y herramientas de automatización.</p>
<hr />
<h2>Detectando soporte de color</h2>
<p>No todas las terminales soportan colores (piensa en logs redirigidos a archivos o terminales mínimas). Es buena práctica verificar:</p>
<pre><code class="language-bash">#! /usr/bin/env bash

# Desactivar colores si no estamos en una terminal interactiva
if [[ -t 1 ]]; then
    RED="\e[31m"
    GREEN="\e[32m"
    YELLOW="\e[33m"
    ENDCOLOR="\e[0m"
else
    RED=""
    GREEN=""
    YELLOW=""
    ENDCOLOR=""
fi

echo -e "\({GREEN}Esto se ve verde en terminal, y normal en un archivo\){ENDCOLOR}"
</code></pre>
<p>El test <code>-t 1</code> verifica si el file descriptor 1 (stdout) está conectado a una terminal. Si el output se redirige a un archivo (<code>script.sh &gt; log.txt</code>), los códigos de color se omiten, evitando ensuciar los logs con caracteres de escape ilegibles.</p>
<p>También puedes respetar la variable de entorno <code>NO_COLOR</code> (estándar de la comunidad: <a href="https://no-color.org/">no-color.org</a>):</p>
<pre><code class="language-bash">if [[ -n "${NO_COLOR:-}" ]]; then
    RED=""
    GREEN=""
    ENDCOLOR=""
fi
</code></pre>
<hr />
<h2>Ejemplo completo: script de despliegue con salida colorizada</h2>
<p>Para cerrar, aquí tienes un ejemplo más realista que podrías adaptar para tus propios scripts de despliegue o hooks de Git:</p>
<pre><code class="language-shell">#! /usr/bin/env bash
set -euo pipefail

# ============================================================
# Colores y estilos
# ============================================================
if [[ -t 1 ]]; then
    RED="\e[31m"
    GREEN="\e[32m"
    YELLOW="\e[33m"
    BLUE="\e[34m"
    CYAN="\e[36m"
    BOLD="\e[1m"
    DIM="\e[2m"
    NC="\e[0m"  # No Color
else
    RED="" GREEN="" YELLOW="" BLUE="" CYAN="" BOLD="" DIM="" NC=""
fi

# ============================================================
# Funciones de utilidad
# ============================================================
header() {
    echo ""
    echo -e "\({BOLD}\){CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
    echo -e "\({BOLD}\){CYAN}  \(1\){NC}"
    echo -e "\({BOLD}\){CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
}

info()    { echo -e "  \({BLUE}ℹ\){NC}  $1"; }
success() { echo -e "  \({GREEN}✔\){NC}  $1"; }
warn()    { echo -e "  \({YELLOW}⚠\){NC}  $1"; }
error()   { echo -e "  \({RED}✘\){NC}  $1"; }
step()    { echo -e "  \({DIM}→\){NC}  $1"; }

# ============================================================
# Script principal
# ============================================================
header "DEPLOY v2.4.1 → production"

info "Verificando pre-requisitos..."
step "kubectl configurado: $(kubectl config current-context 2&gt;/dev/null || echo 'N/A')"
step "Docker version: $(docker --version 2&gt;/dev/null | cut -d' ' -f3 || echo 'N/A')"
success "Pre-requisitos verificados"

info "Construyendo imagen Docker..."
if docker build -t myapp:v2.4.1 . &gt; /dev/null 2&gt;&amp;1; then
    success "Imagen construida exitosamente"
else
    error "Fallo al construir la imagen"
    exit 1
fi

info "Aplicando manifiestos de Kubernetes..."
warn "Usando namespace: production (¡cuidado!)"
success "Despliegue completado"

header "RESUMEN"
echo -e "  Estado:  \({GREEN}\){BOLD}EXITOSO${NC}"
echo -e "  Versión: \({CYAN}v2.4.1\){NC}"
echo -e "  Tiempo:  \({DIM}12.4s\){NC}"
echo ""
</code></pre>
<img src="https://cloudmate-test.s3.us-east-1.amazonaws.com/uploads/covers/620c453d7cf10d2765e28b6c/c215576b-6b3e-44e6-b6fa-624b0ae6ea9e.png" alt="" style="display:block;margin:0 auto" />

<hr />
<h2>Consejos finales</h2>
<ol>
<li><p><strong>Siempre resetea con</strong> <code>\e[0m</code> al final de cada línea coloreada. No hacerlo es la fuente número uno de bugs visuales.</p>
</li>
<li><p><strong>Usa funciones, no variables sueltas</strong> en scripts de producción. Son más mantenibles y puedes agregar timestamps, redirección a archivo, y otras mejoras en un solo lugar.</p>
</li>
<li><p><strong>Respeta</strong> <code>NO_COLOR</code> <strong>y</strong> <code>-t 1</code>. Tus scripts serán ciudadanos de primera clase en pipelines automatizados.</p>
</li>
<li><p><strong>No abuses del color</strong>. Si todo es colorido, nada destaca. Usa rojo solo para errores reales, amarillo para advertencias, y verde para confirmaciones de éxito.</p>
</li>
<li><p><code>printf</code> <strong>vs</strong> <code>echo -e</code>: Si buscas portabilidad máxima, <code>printf</code> maneja secuencias de escape sin necesidad de flags adicionales:</p>
<pre><code class="language-bash">printf "\({RED}Error: %s\){ENDCOLOR}\n" "algo falló"
</code></pre>
</li>
<li><p><strong>Prueba en múltiples terminales</strong>. Lo que se ve perfecto en tu iTerm2 o Alacritty puede verse diferente en una terminal más básica.</p>
</li>
</ol>
<p>Las combinaciones son infinitas y son tuyas. Ahora que tienes las herramientas, dale personalidad a tus scripts y haz que la terminal sea un lugar más amigable para trabajar.</p>
]]></content:encoded></item><item><title><![CDATA[El verdadero superpoder no está en lo que logras, sino en lo que inspiras]]></title><description><![CDATA[Todos celebran cuando alguien cumple un objetivo o supera un reto. Pero la verdadera magia no está en cruzar la meta, sino en lo que pasa después… cuando tu historia inspira a otra persona a dar su primer paso, a dejar el miedo atrás y a empezar su p...]]></description><link>https://blog.295devops.com/el-verdadero-superpoder-no-esta-en-lo-que-logras-sino-en-lo-que-inspiras</link><guid isPermaLink="true">https://blog.295devops.com/el-verdadero-superpoder-no-esta-en-lo-que-logras-sino-en-lo-que-inspiras</guid><category><![CDATA[motivation]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 09 Aug 2025 20:47:20 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754772186426/87fdbdde-0ed4-4499-ac81-954a717725e3.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Todos celebran cuando alguien cumple un objetivo o supera un reto. Pero la verdadera magia no está en cruzar la meta, sino en lo que pasa después… cuando tu historia inspira a otra persona a dar su primer paso, a dejar el miedo atrás y a empezar su propio camino. Este no es un artículo sobre ganar, sino sobre algo mucho más grande: <strong>cómo convertir tu experiencia en el motor que impulsa a otros a atreverse</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754772286389/20716f45-461e-4865-a9b9-69000bcb7645.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-la-meta-es-la-excusa"><strong>La meta es la excusa</strong></h3>
<p>Escribir un libro, empezar un proyecto o mudarte a otro país…<br />Sí, son metas enormes, pero lo más valioso no está en la meta, sino en <strong>la historia que inspira a otros a soñar y a moverse</strong>.</p>
<p>Cuando compartís tu proceso con errores, dudas y victorias mostrás que <strong>no hay que ser extraordinario para hacer algo extraordinario</strong>.</p>
<h3 id="heading-tienes-superpoderes"><strong>¿Tienes superpoderes?</strong></h3>
<p>No vienen de ser un héroe de película ni de haber nacido con un don especial.<br />💪 Tus superpoderes vienen de lo que <strong>elegís hacer</strong>… y más aún, de lo que <strong>elegís dar a los demás</strong>.</p>
<p>Ser optimista, feliz y agradecido está bien, pero ayudar a que otras personas también lo sean… eso es un nivel más alto.</p>
<h3 id="heading-personas-comunes-logros-increibles"><strong>Personas comunes, logros increíbles</strong></h3>
<p>No suelo ver a gente “perfecta” haciendo lo imposible.<br />Lo que veo cada día son <strong>personas normales</strong> que:</p>
<ul>
<li><p>Dan un paso cuando nadie se atreve.</p>
</li>
<li><p>Vuelven a intentar después de fallar.</p>
</li>
<li><p>Inspiran con pequeños gestos que cambian mucho.</p>
</li>
</ul>
<p><strong>No es magia. Es voluntad.<br />No es suerte. Es decisión.</strong></p>
<h3 id="heading-la-chispa-que-enciende-todo"><strong>La chispa que enciende todo</strong></h3>
<p>Tu historia, por simple que te parezca, puede ser la señal que alguien estaba esperando.<br />Un post, una charla, una conversación… y de pronto, esa persona se anima.</p>
<p>🌍 Si cada uno de nosotros comparte, inspira y ayuda, el mundo no va a necesitar superhéroes:<br />Va a estar lleno de <strong>personas con superpoderes reales</strong>.</p>
<h3 id="heading-reflexion-final">💬 <strong>Reflexión final:</strong></h3>
<p>No importa si tu meta es correr, emprender, aprender o cambiar de rumbo.<br />Lo importante es <strong>a quién ayudas a creer que también puede hacerlo</strong>.</p>
<p>Ese sí es un verdadero <strong>superpoder</strong>. 🔥</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754772368721/ab9ed389-9817-4e19-8f73-3a443540484a.png" alt class="image--center mx-auto" /></p>
<p>Al final, no se trata solo de lo que logras, sino de lo que despiertas en los demás.<br />Tus metas y retos son importantes, pero tu verdadero legado es la huella que dejas en las personas que, gracias a tu ejemplo, deciden avanzar.<br />Cada palabra, cada gesto y cada historia que compartes puede ser el impulso que alguien necesitaba para creer que también es posible.<br />Ese es el superpoder que todos podemos elegir: <strong>inspirar y encender caminos</strong>. 🔥</p>
]]></content:encoded></item><item><title><![CDATA[🔥 Cómo aprendo y crezco cada día]]></title><description><![CDATA[Hace unos días viví una de esas experiencias increibles. Me invitaron a tener un espacio tipo mentoría individual, pero terminó siendo mucho más que eso… Fue un momento donde no fui speaker, ni ingeniera, ni formadora. Fui Dra Roxs 💬: una versión mí...]]></description><link>https://blog.295devops.com/como-aprendo-y-crezco-cada-dia</link><guid isPermaLink="true">https://blog.295devops.com/como-aprendo-y-crezco-cada-dia</guid><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Fri, 01 Aug 2025 01:38:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754012279141/f36148ab-4dfa-4cbe-a033-6fc100c4aed6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hace unos días viví una de esas experiencias increibles. Me invitaron a tener un espacio tipo mentoría individual, pero terminó siendo mucho más que eso… Fue un momento donde no fui speaker, ni ingeniera, ni formadora. Fui <strong>Dra Roxs</strong> 💬: una versión mía que escucha, que acompaña desde la empatía y que, por un rato, se convierte en espejo y antorcha para otros.</p>
<p>Y aunque suene gracioso eso de “Dra Roxs”, descubrí que <strong>muchas personas no necesitan una receta técnica</strong>, sino un espacio humano para poder decir:</p>
<blockquote>
<h3 id="heading-estoy-perdida-como-encuentro-mi-camino-en-este-mundo-tech"><em>"Estoy perdida, ¿cómo encuentro mi camino en este mundo tech?"</em></h3>
</blockquote>
<p><mark>Y ahí entendí algo importante que quiero compartirte hoy</mark></p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754012118527/a12e1210-47d8-4a71-9621-71263fe31da6.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-cada-persona-florece-distinto">🌸 Cada persona florece distinto</h2>
<p>Durante la charla, me preguntaron:</p>
<blockquote>
<p><em>"Roxs, ¿cuál es tu especialidad para poder guiar a otros?"</em></p>
</blockquote>
<p>Y mi respuesta fue simple, pero honesta: <strong>No tengo una única especialidad, porque cada persona es distinta.</strong></p>
<p>Lo que a mí me funciona puede no encenderte a vos. A mí me enciende la rosa 🌹 porque la siento potente, vibrante, intensa. Pero quizás a vos te conmueve la margarita 🌼: más simple, más serena, igual de hermosa. <strong>Ambas son flores. Ambas son caminos válidos.</strong></p>
<p>Y ahí está la clave: no se trata de imitar a otros, sino de descubrir tu propia flor, tu propio fuego, tu propio crecimiento.</p>
<hr />
<h2 id="heading-crecer-cada-dia-6-estrategias-que-me-sostienen">🔥 Crecer cada día: 6 estrategias que me sostienen</h2>
<p>En este mundo que corre a mil por hora, donde la presión por “estar al día” nos puede abrumar, <strong>necesito anclas</strong>. Pequeñas acciones que me conecten con mi propósito y que me permitan evolucionar sin perderme en el caos. Estas son mis 6 estrategias personales para aprender y crecer todos los días, incluso en los días nublados:</p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754012066875/1d4b82b6-6cc9-43bd-8240-b6458edb5984.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-1-planifica-lo-que-queres-aprender">1️⃣ <strong>Planificá lo que querés aprender</strong></h3>
<p>No dejo mi aprendizaje al azar. Antes de arrancar una semana, me pregunto:</p>
<ul>
<li><p>¿Qué habilidad quiero mejorar?</p>
</li>
<li><p>¿Qué concepto quiero explorar más allá de lo básico?</p>
</li>
</ul>
<p>No todo lo que aprendo tiene que estar ligado al trabajo. A veces es sobre comunicación, empatía, o incluso cómo descansar mejor.</p>
<hr />
<h3 id="heading-2-practica-con-intencion-no-en-automatico">2️⃣ <strong>Practicá con intención, no en automático</strong></h3>
<p>Hacer las cosas por rutina no siempre significa que estás creciendo. La <strong>práctica deliberada</strong> significa poner foco, evaluar, ajustar.</p>
<p>Por ejemplo, si estoy mejorando una charla o una aplicación que estoy automatizando, me grabo, me escucho, pido feedback. <strong>No para criticarme, sino para evolucionar.</strong></p>
<hr />
<h3 id="heading-3-procesar-ideas-reflexionar-en-movimiento">3️⃣ <strong>Procesar Ideas (reflexionar en movimiento)</strong></h3>
<p>Hay días donde necesito salir a caminar, auriculares puestos, hablando sola. Sí, suena raro. Pero funciona.</p>
<p>Esa conversación conmigo misma me ayuda a acomodar ideas, a detectar lo que me vibra o lo que ya no me representa. <strong>Reflexionar también es crecer.</strong></p>
<hr />
<h3 id="heading-4-crea-espacios-para-aprender">4️⃣ <strong>Creá espacios para aprender</strong></h3>
<p>No siempre tengo una hora libre para sentarme a leer, pero <strong>me creo mini espacios</strong>:</p>
<ul>
<li><p>10 minutos para escuchar un podcast mientras desayuno</p>
</li>
<li><p>15 minutos de newsletter técnica antes de dormir</p>
</li>
<li><p>O una charla con alguien que admiro</p>
</li>
</ul>
<p>El aprendizaje también se nutre de lo cotidiano.</p>
<hr />
<h3 id="heading-5-resolve-los-problemas-en-el-momento-no-despues">5️⃣ <strong>Resolvé los problemas en el momento, no después</strong></h3>
<p>Muchas veces escondemos los errores bajo la alfombra. Pero lo pequeño que se ignora hoy, <strong>explota mañana</strong>.</p>
<p>Tener espacios en blanco en el día (sin reuniones, sin distracciones) me permite <strong>detectar fricciones</strong>, ruidos, incomodidades. Y resolver antes de que se vuelva un incendio.</p>
<hr />
<h3 id="heading-6-experimenta-incluso-si-falla">6️⃣ <strong>Experimentá, incluso si falla</strong></h3>
<p>Hago mini-experimentos todo el tiempo. En mi comunidad, en mi lab de CI/CD, en cómo enseño, en cómo vivo.</p>
<p>Algunos salen increíbles. Otros me enseñan lo que <em>no</em> quiero hacer.</p>
<p>Pero todos me dan algo: <strong>perspectiva, valentía y evolución.</strong></p>
<hr />
<h2 id="heading-la-leccion-mas-linda-de-ser-dra-fuego-roxs">💬 La lección más linda de ser Dra “Fuego” Roxs</h2>
<p>Ese día no resolví todos los dilemas de la persona que me escribió. No le di un "camino seguro" ni una receta mágica. Le mostré cómo buscar su <em>propio camino</em>.</p>
<p>Le dije:</p>
<blockquote>
<p><em>"Si te gusta la margarita, no te esfuerces en parecerte a la rosa. Tu luz está en florecer a tu manera."</em></p>
</blockquote>
<p>Y ese fue el momento superpower. Que crecer es más lindo cuando <strong>se hace desde lo auténtico, no desde lo impuesto</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754011963592/48bf1197-33fb-45f4-a04d-395fe8e34792.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-y-recuerda">🚀 Y recuerda…</h2>
<p>Crecer <strong>no siempre es cómodo</strong>. A veces duele, a veces confunde, a veces cansa. Pero también <strong>libera, transforma y enciende</strong>.</p>
<p>Y en ese camino, <strong>no estás sola</strong>. Estamos floreciendo juntas, con espinas, colores, tierra y sol.</p>
<p>Gracias por leer. Gracias por crecer.</p>
<p>Con fuego, <strong>Roxs 🔥</strong></p>
]]></content:encoded></item><item><title><![CDATA[🎉 ¡Certifícate GRATIS en AWS! Vouchers 100% Free para niveles Foundational y Associate 🎓🚀 (Hasta el 31 Agosto 2025)]]></title><description><![CDATA[Tanto si estás dando tus primeros pasos en la nube como si querés dar el siguiente salto en tu carrera tech, AWS Educate te da una mano gigante:¡vouchers 100% gratuitos para rendir certificaciones AWS de nivel Foundational y Associate!
Sí, leíste bie...]]></description><link>https://blog.295devops.com/certificate-gratis-en-aws-vouchers-100-free-para-niveles-foundational-y-associate-hasta-el-31-agosto-2025</link><guid isPermaLink="true">https://blog.295devops.com/certificate-gratis-en-aws-vouchers-100-free-para-niveles-foundational-y-associate-hasta-el-31-agosto-2025</guid><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Wed, 30 Jul 2025 01:31:10 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753838901832/8b9e8bd1-867b-423a-8d2d-75a85309f212.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Tanto si estás dando tus primeros pasos en la nube como si querés dar el siguiente salto en tu carrera tech, <strong>AWS Educate</strong> te da una mano gigante:<br /><strong>¡vouchers 100% gratuitos para rendir certificaciones AWS de nivel Foundational y Associate!</strong></p>
<p>Sí, leíste bien: <strong>AWS te paga el examen</strong>.<br />En este blog te cuento paso a paso cómo acceder a esta oportunidad, sumar puntos, y canjear tu voucher antes que se agoten.</p>
<p>🔥 Spoiler: si seguís bien los pasos, ¡vas a poder rendir tu certificación sin pagar ni un dólar!</p>
<hr />
<h2 id="heading-que-vouchers-estan-disponibles">🧾 ¿Qué vouchers están disponibles?</h2>
<h3 id="heading-foundational-level-4500-puntos">🔹 Foundational Level – 4,500 puntos</h3>
<ul>
<li><p><strong>AWS Certified Cloud Practitioner (CLF-C01)</strong></p>
</li>
<li><p><strong>AWS Certified AI Practitioner</strong><br />  📅 <strong>Válido hasta:</strong> 31 de Agosto de 2025</p>
</li>
</ul>
<h3 id="heading-associate-level-5200-puntos">🔹 Associate Level – 5,200 puntos</h3>
<ul>
<li><p><strong>Solutions Architect</strong></p>
</li>
<li><p><strong>Developer Associate</strong></p>
</li>
<li><p><strong>SysOps Administrator</strong></p>
</li>
<li><p><strong>Data Engineer</strong></p>
</li>
<li><p><strong>Machine Learning Engineer</strong><br />  📅 <strong>Válido hasta:</strong> 31 de Agosto de 2025</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753839676390/e71cde08-7a71-49c9-8826-a3838209ad47.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-como-obtengo-mi-voucher-100-gratis">🌟 ¿Cómo obtengo mi voucher 100% GRATIS?</h2>
<h3 id="heading-1-crea-tu-cuenta-en-aws-educatehttpswwwawseducatecom">1️⃣ Crea tu cuenta en <a target="_blank" href="https://www.awseducate.com/"><strong>AWS Educate</strong></a></h3>
<p>Es la plataforma para estudiantes y profesionales que quieren formarse con contenido oficial de AWS.</p>
<h3 id="heading-2-registrate-tambien-en-aws-skill-builderhttpsskillbuilderaws">2️⃣ Regístrate también en <a target="_blank" href="https://skillbuilder.aws/"><strong>AWS Skill Builder</strong></a></h3>
<p>Usá el mismo email que en AWS Educate.</p>
<h3 id="heading-3-completa-un-badge-por-ejemplo-introduction-to-cloud-101">3️⃣ Completá un badge (por ejemplo, “Introduction to Cloud 101”)</h3>
<p>Esto te habilita a entrar al <strong>Emerging Talent Community (ETC)</strong>, la comunidad donde se acumulan puntos para canjear recompensas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753838510809/3baa7364-1e69-434f-b235-b9bfbccc8df8.png" alt class="image--center mx-auto" /></p>
<p><img src="https://substackcdn.com/image/fetch/$s_!-O50!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a41ed90-93a4-4260-b1f3-90ce8b696956_1445x601.jpeg" alt /></p>
<p><img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3biilspd5aye5wjogh1j.png" alt="Image description" /></p>
<p><img src="https://substackcdn.com/image/fetch/$s_!DAEh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440db221-2686-4120-971b-75a0d6733dc0_3061x1318.jpeg" alt /></p>
<h3 id="heading-4-suma-puntos-completando-contenido-videos-quizzes-articulos-en-etc">4️⃣ Sumá puntos completando contenido (videos, quizzes, artículos) en ETC</h3>
<p>💎 Cada actividad suma puntos que se muestran con un ícono de gema.</p>
<p><img src="https://substackcdn.com/image/fetch/$s_!0W3N!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35b88c7e-3def-411a-9b7a-9dfe7a4285d1_2448x1054.jpeg" alt /></p>
<h3 id="heading-5-prepara-tu-examen-con-skill-builder">5️⃣ Prepará tu examen con Skill Builder</h3>
<p>Debés:</p>
<ul>
<li><p>Completar un <strong>curso de preparación</strong> (score mínimo: 70%)</p>
</li>
<li><p>Rendir el <strong>badge assessment</strong> con un <strong>score de al menos 80%</strong></p>
</li>
</ul>
<h3 id="heading-6-canjea-tu-voucher-desde-la-seccion-rewards-en-el-etc">6️⃣ ¡Canjeá tu voucher desde la sección “Rewards” en el ETC!</h3>
<p>La revisión de la solicitud tarda hasta 3 días hábiles.</p>
<p><img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7no9ia9oj2rlgq6jr7yd.png" alt="Image description" /></p>
<hr />
<h2 id="heading-tips-clave-para-no-perderte">🧠 Tips clave para no perderte:</h2>
<p>✅ Debés tener <strong>+18 años</strong> para acceder al ETC<br />✅ Usá el <strong>mismo email</strong> en todas las plataformas<br />✅ Repetí quizzes para subir tu puntaje<br />✅ Revisa el catálogo en Skill Builder buscando tu certificación<br />✅ ¡Visitá el ETC seguido! Hay contenido nuevo 6 veces por semana 😮</p>
<hr />
<h2 id="heading-por-que-deberias-aprovechar-esto">🔥 ¿Por qué deberías aprovechar esto?</h2>
<ul>
<li><p>No todos los días podés certificarte en AWS sin pagar ni un centavo.</p>
</li>
<li><p>Aumenta tu empleabilidad y salario potencial.</p>
</li>
<li><p>Es una manera increíble de comenzar tu carrera en la nube.</p>
</li>
</ul>
<p><img src="https://substackcdn.com/image/fetch/$s_!9oPz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f209520-b3a5-4e39-8c47-764d823a9d70_754x604.png" alt /></p>
<p><img src="https://substackcdn.com/image/fetch/$s_!vfCB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d13d2f8-d84f-4de5-b8bd-6a81b4fa2055_882x810.png" alt /></p>
<hr />
<h2 id="heading-enlaces-utiles">📌 Enlaces útiles</h2>
<p>➡️ <a target="_blank" href="https://www.awseducate.com/">AWS Educate</a><br />➡️ <a target="_blank" href="https://skillbuilder.aws/">AWS Skill Builder</a><br />➡️ <a target="_blank" href="https://www.awseducate.com/student/s/learner-faqs#emerging-talent-community">Emerging Talent Community FAQs</a></p>
<hr />
<h2 id="heading-resumen-final-que-necesito-para-reclamar-mi-voucher-gratuito">Resumen Final: ¿Qué necesito para reclamar mi voucher gratuito?</h2>
<p>Para obtener tu voucher 100% free y certificarte en AWS, asegurate de cumplir con estos requisitos:</p>
<ol>
<li><p><strong>Completá un curso de preparación</strong> en AWS Skill Builder para la certificación que elegiste.</p>
</li>
<li><p><strong>Aprobá un examen práctico</strong> (practice test o question set oficial) con al menos <strong>70%</strong> de puntaje.</p>
</li>
<li><p>Usá <strong>el mismo correo electrónico</strong> en AWS Educate y AWS Skill Builder para evitar errores.</p>
</li>
<li><p><strong>Reclamá tu voucher antes del 31 de agosto de 2025</strong> — tu examen debe rendirse <strong>antes de esa fecha</strong>.</p>
</li>
<li><p>El equipo de AWS ETC <strong>validará que hayas cumplido los pasos</strong>, así que revisá bien tu progreso antes de solicitarlo.</p>
</li>
<li><p>Tené acceso al correo que usaste en AWS Educate — <strong>el voucher no se reenvía ni se reemplaza</strong> si se pierde.</p>
</li>
</ol>
<hr />
<p>🎯 ¡Y listo! Seguí estos pasos, reclamá tu voucher y presentá tu examen de certificación AWS…<br /><strong>¡totalmente GRATIS!</strong> 🚀</p>
<hr />
<h2 id="heading-corre-que-se-agotan">🚨 ¡Corre, que se agotan!</h2>
<p>Esta es una oportunidad de oro para certificarte con uno de los líderes globales en la nube.<br />Aunque esta edición ya cerró, el programa <strong>ETC</strong> sigue activo y es una fuente constante de recompensas, vouchers y formación de primer nivel.</p>
<p>🗓️ <strong>Estate atento a futuras ediciones y preparate desde ya.</strong></p>
<hr />
<p><strong>¿Querés más tips sobre certificaciones, DevOps, cloud y recursos gratuitos?<br />🔥 Seguime en LinkedIn:</strong> <a target="_blank" href="https://www.linkedin.com/in/roxsross"><strong>Roxs | 295DevOps</strong></a></p>
]]></content:encoded></item><item><title><![CDATA[Despliega tu Portafolio Web Localmente en Minutos con Vagrant, Nginx y sslip.io]]></title><description><![CDATA[Configurar un entorno de desarrollo local es complicado. Desde lidiar con configuraciones complejas hasta enfrentarse a certificados que el navegador rechaza, la mayoría de nosotros ha pasado por ello. Pero, ¿y si te dijera que puedes hacer todo much...]]></description><link>https://blog.295devops.com/despliega-tu-portafolio-web-localmente-en-minutos-con-vagrant-nginx-y-sslipio</link><guid isPermaLink="true">https://blog.295devops.com/despliega-tu-portafolio-web-localmente-en-minutos-con-vagrant-nginx-y-sslipio</guid><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Linux]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Fri, 04 Jul 2025 01:58:13 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751583252345/daf3661a-bd14-43e5-b162-0106efc18d62.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Configurar un entorno de desarrollo local es complicado. Desde lidiar con configuraciones complejas hasta enfrentarse a certificados que el navegador rechaza, la mayoría de nosotros ha pasado por ello. Pero, <strong>¿y si te dijera que puedes hacer todo mucho más fácil?</strong></p>
<p>En este post, te mostraré cómo desplegar tu portafolio web localmente, sin complicaciones y en solo unos minutos, utilizando <strong>Vagrant</strong>, <strong>Nginx</strong> y <a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a>. Olvídate de las configuraciones interminables y empieza a trabajar de forma rápida y eficiente.</p>
<h3 id="heading-arquitectura-local-para-portafolio-web-con-vagrant-nginx">Arquitectura Local para Portafolio Web con Vagrant + Nginx</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751594506599/44aa0a7d-8cb7-4be0-a4bb-ce363bc88027.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-descripcion-del-flujo">Descripción del flujo:</h3>
<ol>
<li><p><strong>Vagrant</strong> gestionará la creación de la máquina virtual, con un entorno basado en Ubuntu.</p>
</li>
<li><p><strong>Nginx</strong> servirá el portafolio web estático. Este se colocará en el directorio <code>/var/www/portfolio</code> y será accesible mediante el subdominio proporcionado por <a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a> (ej. <a target="_blank" href="http://192.168.56.10.sslip.io"><code>192.168.56.10.sslip.io</code></a>).</p>
</li>
<li><p>El proceso de aprovisionamiento automatizado mediante <strong>Vagrant</strong> garantizará que el entorno de desarrollo se configure rápidamente.</p>
</li>
</ol>
<hr />
<h3 id="heading-el-portafolio-web">El Portafolio web</h3>
<p>Este <strong>portafolio DevOps</strong> está construido utilizando <strong>HTML5</strong>, <strong>CSS3</strong> y <strong>JavaScript</strong> (vanilla), y está diseñado para mostrar tus habilidades en la implementación de un entorno de desarrollo local. Usando <strong>Vagrant</strong>, puedes levantar una máquina virtual que ejecuta <strong>Nginx</strong> para servir tu portafolio web estático de manera eficiente. Con <a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a>, asignas un dominio dinámico a tu entorno local. Este enfoque simplifica la configuración y te permite enfocarte en lo que realmente importa: <a target="_blank" href="https://github.com/roxsross/devops-static-web/raw/portafolio-web/portafolio-web.zip">¡tu portafolio!</a></p>
<p><img src="https://pbs.twimg.com/media/GuveH7TWUAAdDua?format=jpg&amp;name=large" alt="Imagen" /></p>
<hr />
<h3 id="heading-que-es-nginx-y-como-funciona">¿Qué es Nginx y cómo funciona?</h3>
<p>Nginx es un servidor web de alto rendimiento que también puede funcionar como proxy inverso, balanceador de carga, servidor de correo y caché HTTP. Su arquitectura basada en eventos lo hace especialmente eficiente en el manejo de múltiples conexiones simultáneas, lo que lo convierte en una opción popular para servir aplicaciones web modernas.</p>
<p>Una de sus principales ventajas es su eficiencia al manejar tráfico concurrente. A diferencia de servidores tradicionales como Apache, Nginx usa un enfoque asincrónico para manejar las conexiones. Esto significa que, en lugar de abrir un nuevo hilo para cada solicitud, Nginx usa un solo hilo para manejar miles de conexiones, lo que mejora el rendimiento y la escalabilidad.</p>
<h3 id="heading-que-es-sslipiohttpsslipio">¿Qué es <a target="_blank" href="http://sslip.io">sslip.io</a>?</h3>
<p><a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a> es un servicio gratuito que permite asignar un dominio dinámico a una dirección IP local. Esto es útil para desarrolladores que quieren exponer su entorno local a Internet sin tener que configurar un servidor DNS completo. Con <a target="_blank" href="http://sslip.io">sslip.io</a>, simplemente añades una cadena de texto en tu dirección IP local (como <code>.</code><a target="_blank" href="http://sslip.io"><code>sslip.io</code></a>) y el dominio se resuelve automáticamente a la dirección IP que especificas.</p>
<p>Además, <a target="_blank" href="http://sslip.io">sslip.io</a> incluye certificados SSL válidos para cada subdominio generado, lo que te permite probar aplicaciones locales de forma segura sin tener que lidiar con certificados autofirmados. En resumen, <a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a> resuelve las direcciones locales de manera eficiente y segura, haciendo que el desarrollo sea mucho más rápido.</p>
<p><mark>Estos servicios geniales resuelven automáticamente cualquier subdominio a la IP que especifiques:</mark></p>
<pre><code class="lang-bash"><span class="hljs-comment"># Ejemplos de resolución automática</span>
192.168.1.100.sslip.io → 192.168.1.100
localhost.sslip.io → 127.0.0.1
10.0.0.5.nip.io → 10.0.0.5
</code></pre>
<p><mark>Lo mejor: </mark> <strong><mark>incluyen certificados SSL válidos</mark></strong> <mark>sin configuración adicional.</mark></p>
<hr />
<h2 id="heading-configurando-el-entorno-con-vagrant">Configurando el entorno con Vagrant</h2>
<h4 id="heading-1-instalar-vagrant-y-virtualbox">1. <strong>Instalar Vagrant y VirtualBox</strong></h4>
<ul>
<li><p><strong><mark>Vagrant</mark></strong>:<br />  Vagrant es una herramienta para crear y gestionar máquinas virtuales. <a target="_blank" href="https://developer.hashicorp.com/vagrant/install">Para instalarla en este enlace</a></p>
</li>
<li><p><strong><mark>VirtualBox</mark></strong>:<br />  <strong>VirtualBox</strong> es un proveedor de máquinas virtuales compatible con Vagrant. <a target="_blank" href="https://www.virtualbox.org/wiki/Downloads">Puedes instalarlo en este enlace</a></p>
</li>
</ul>
<h4 id="heading-2-verificar-la-instalacion">2. <strong>Verificar la instalación</strong></h4>
<p>Una vez instalados Vagrant y VirtualBox, puedes verificar que todo esté funcionando co<a target="_blank" href="https://www.virtualbox.org/">rrec</a>tamente ejecutando:</p>
<pre><code class="lang-bash">vagrant --version
</code></pre>
<p>Deberías ver la versión instalada de <strong>Vagrant</strong> en la salida. Si también tienes <strong>VirtualBox</strong> instalado, puedes verificarlo ejecutando:</p>
<pre><code class="lang-bash">vboxmanage --version
</code></pre>
<h4 id="heading-3-crear-y-configurar-la-maquina-virtual">3. <strong>Crear y configurar la máquina virtual</strong></h4>
<p>Ahora que tienes Vagrant y VirtualBox instalados, puedes crear y configurar tu máquina virtual para el portafolio web.</p>
<hr />
<h3 id="heading-configuracion-del-vagrantfile">Configuración del Vagrantfile</h3>
<p>Primero, creamos nuestro <code>Vagrantfile</code>:</p>
<pre><code class="lang-ruby"><span class="hljs-comment"># -*- mode: ruby -*-</span>
<span class="hljs-comment"># vi: set ft=ruby :</span>

<span class="hljs-comment"># 🚀 HTTP Local con sslip.io + Nginx + Vagrant</span>
<span class="hljs-comment"># 📝 Blog: Desarrollo local</span>
<span class="hljs-comment"># 🎯 Objetivo: Demostrar cómo usar sslip.io para HTTP local sin complicaciones</span>
<span class="hljs-comment"># 🔗 Acceso: http://192.168.56.10.sslip.io</span>

Vagrant.configure(<span class="hljs-string">"2"</span>) <span class="hljs-keyword">do</span> <span class="hljs-params">|config|</span>
  <span class="hljs-comment"># 📦 Box base: Ubuntu 24.04 LTS compatible con mac soporta amd64/arm64</span>
  config.vm.box = <span class="hljs-string">"bento/ubuntu-24.04"</span>
  config.vm.box_check_update = <span class="hljs-literal">true</span>
  config.vm.hostname = <span class="hljs-string">"portafolio-ssl-local"</span>

  <span class="hljs-comment"># 🌐 Configuración de red</span>
  <span class="hljs-comment"># IP privada para acceso directo desde el host</span>
  config.vm.network <span class="hljs-string">"private_network"</span>, <span class="hljs-symbol">ip:</span> <span class="hljs-string">"192.168.56.10"</span>
  config.vm.network <span class="hljs-string">"forwarded_port"</span>, <span class="hljs-symbol">guest:</span> <span class="hljs-number">80</span>, <span class="hljs-symbol">host:</span> <span class="hljs-number">8080</span>, 
    <span class="hljs-symbol">auto_correct:</span> <span class="hljs-literal">true</span>, <span class="hljs-symbol">id:</span> <span class="hljs-string">"http"</span>

  <span class="hljs-comment"># 💻 Configuración del proveedor VirtualBox</span>
  config.vm.provider <span class="hljs-string">"virtualbox"</span> <span class="hljs-keyword">do</span> <span class="hljs-params">|vb|</span>
    vb.name = <span class="hljs-string">"devops-local"</span>
    vb.memory = <span class="hljs-string">"1024"</span>  
    vb.cpus = <span class="hljs-number">2</span>
  <span class="hljs-keyword">end</span>

  <span class="hljs-comment"># 🚀 Aprovisionamiento principal</span>
  config.vm.provision <span class="hljs-string">"shell"</span>, <span class="hljs-symbol">path:</span> <span class="hljs-string">"provision.sh"</span>, <span class="hljs-symbol">privileged:</span> <span class="hljs-literal">true</span>

  <span class="hljs-comment"># 📋 Mensaje de bienvenida post-instalación</span>
  config.vm.provision <span class="hljs-string">"shell"</span>, <span class="hljs-symbol">inline:</span> <span class="hljs-string">&lt;&lt;-SHELL
    echo ""
    echo "🎉 ¡Configuración completada exitosamente!"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo "💼 Portafolio Web disponible en:"
    echo "   🔗 http://192.168.56.10.sslip.io"
    echo ""
    echo ""
    echo "📝 HTTP Local con sslip.io"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    echo ""
  SHELL</span>
<span class="hljs-keyword">end</span>
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Podes revisar el catalogo de Boxes de Vagrant disponible, recuerda revisar proveedor y arquitectura <strong>ya sea arm64 o amd64</strong> <a target="_self" href="https://portal.cloud.hashicorp.com/vagrant/discover">https://portal.cloud.hashicorp.com/vagrant/discover</a></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749568819077/7307b447-1604-466c-9472-8a4bc8716c90.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-script-de-aprovisionamiento">Script de aprovisionamiento</h2>
<p>Creamos <code>provision.sh</code> para automatizar toda la configuración:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Simple Local Development with sslip.io + Nginx + Vagrant</span>
<span class="hljs-comment"># HTTP-only setup for fast and simple local development</span>
<span class="hljs-comment"># Objective: Deploy web portfolio with sslip.io domain (HTTP only)</span>

<span class="hljs-built_in">set</span> -euo pipefail  <span class="hljs-comment"># Exit on any error</span>

<span class="hljs-comment"># Colors for output</span>
RED=<span class="hljs-string">'\033[0;31m'</span>
GREEN=<span class="hljs-string">'\033[0;32m'</span>
YELLOW=<span class="hljs-string">'\033[1;33m'</span>
BLUE=<span class="hljs-string">'\033[0;34m'</span>
NC=<span class="hljs-string">'\033[0m'</span> <span class="hljs-comment"># No Color</span>

<span class="hljs-comment"># Function to show progress</span>
<span class="hljs-function"><span class="hljs-title">show_progress</span></span>() {
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>[INFO]<span class="hljs-variable">${NC}</span> <span class="hljs-variable">$1</span>"</span>
}

<span class="hljs-comment"># Function to show success</span>
<span class="hljs-function"><span class="hljs-title">show_success</span></span>() {
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>[SUCCESS]<span class="hljs-variable">${NC}</span> <span class="hljs-variable">$1</span>"</span>
}

<span class="hljs-comment"># Function to show warnings</span>
<span class="hljs-function"><span class="hljs-title">show_warning</span></span>() {
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${YELLOW}</span>[WARNING]<span class="hljs-variable">${NC}</span> <span class="hljs-variable">$1</span>"</span>
}

<span class="hljs-comment"># Function to show errors</span>
<span class="hljs-function"><span class="hljs-title">show_error</span></span>() {
    <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${RED}</span>[ERROR]<span class="hljs-variable">${NC}</span> <span class="hljs-variable">$1</span>"</span>
}

<span class="hljs-comment"># Welcome banner</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"=================================================================="</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"          Simple Local Development with sslip.io                 "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"    HTTP + Nginx + Vagrant = Quick Development Setup             "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"=================================================================="</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${NC}</span>"</span>

<span class="hljs-comment"># Verify if it's Ubuntu</span>
<span class="hljs-keyword">if</span> ! grep -q <span class="hljs-string">"Ubuntu"</span> /etc/os-release; <span class="hljs-keyword">then</span>
    show_error <span class="hljs-string">"This script is designed for Ubuntu. Exiting..."</span>
    <span class="hljs-built_in">exit</span> 1
<span class="hljs-keyword">fi</span>

show_progress <span class="hljs-string">"Updating Ubuntu system"</span>
<span class="hljs-built_in">export</span> DEBIAN_FRONTEND=noninteractive
apt-get update -qq
show_success <span class="hljs-string">"System updated successfully"</span>

show_progress <span class="hljs-string">"Installing essential dependencies"</span>
apt-get install -y -qq \
    nginx \
    curl \
    wget \
    git \
    unzip \
    htop \
    tree \
    net-tools
show_success <span class="hljs-string">"Dependencies installed"</span>

show_progress <span class="hljs-string">"Setting up web directory"</span>
WEB_ROOT=<span class="hljs-string">"/var/www/portfolio"</span>
mkdir -p <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>
chown -R www-data:www-data <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>
chmod -R 755 <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>


<span class="hljs-comment"># Descarga y descomprime el portafolio web desde GitHub</span>
<span class="hljs-function"><span class="hljs-title">download_and_extract_portfolio</span></span>() {
    <span class="hljs-built_in">local</span> ZIP_URL=<span class="hljs-string">"https://github.com/roxsross/devops-static-web/raw/portafolio-web/portafolio-web.zip"</span>
    <span class="hljs-built_in">local</span> TMP_ZIP=<span class="hljs-string">"/tmp/portfolio.zip"</span>

    show_progress <span class="hljs-string">"Descargando portafolio web desde GitHub..."</span>
    <span class="hljs-keyword">if</span> curl -L --fail -o <span class="hljs-string">"<span class="hljs-variable">$TMP_ZIP</span>"</span> <span class="hljs-string">"<span class="hljs-variable">$ZIP_URL</span>"</span>; <span class="hljs-keyword">then</span>
        show_success <span class="hljs-string">"ZIP descargado correctamente."</span>
        show_progress <span class="hljs-string">"Descomprimiendo portafolio en <span class="hljs-variable">$WEB_ROOT</span>..."</span>
        <span class="hljs-keyword">if</span> unzip -o <span class="hljs-string">"<span class="hljs-variable">$TMP_ZIP</span>"</span> -d <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>; <span class="hljs-keyword">then</span>
            show_success <span class="hljs-string">"Portafolio descomprimido en <span class="hljs-variable">$WEB_ROOT</span>."</span>
            <span class="hljs-built_in">local</span> SUBDIR=$(find <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span> -mindepth 1 -maxdepth 1 -<span class="hljs-built_in">type</span> d | head -n1)
            <span class="hljs-keyword">if</span> [ -d <span class="hljs-string">"<span class="hljs-variable">$SUBDIR</span>"</span> ] &amp;&amp; [ <span class="hljs-string">"<span class="hljs-variable">$SUBDIR</span>"</span> != <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span> ]; <span class="hljs-keyword">then</span>
                mv <span class="hljs-string">"<span class="hljs-variable">$SUBDIR</span>"</span>/* <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>/
                rmdir <span class="hljs-string">"<span class="hljs-variable">$SUBDIR</span>"</span>
            <span class="hljs-keyword">fi</span>
        <span class="hljs-keyword">else</span>
            show_error <span class="hljs-string">"Error al descomprimir el portafolio. Se dejará el directorio vacío."</span>
            rm -rf <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>/*
        <span class="hljs-keyword">fi</span>
        rm -f <span class="hljs-string">"<span class="hljs-variable">$TMP_ZIP</span>"</span>
    <span class="hljs-keyword">else</span>
        show_error <span class="hljs-string">"No se pudo descargar el portafolio. Se creará un index.html de emergencia."</span>
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"&lt;html&gt;&lt;body&gt;&lt;h1&gt;Error: No se pudo descargar el portafolio web.&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;"</span> &gt; <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>/index.html"</span>
    <span class="hljs-keyword">fi</span>
}

download_and_extract_portfolio

chown -R www-data:www-data <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span>
find <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span> -<span class="hljs-built_in">type</span> f -<span class="hljs-built_in">exec</span> chmod 644 {} \;
find <span class="hljs-string">"<span class="hljs-variable">$WEB_ROOT</span>"</span> -<span class="hljs-built_in">type</span> d -<span class="hljs-built_in">exec</span> chmod 755 {} \;

show_progress <span class="hljs-string">"Configuring Nginx"</span>

cat &gt; /etc/nginx/sites-available/portfolio &lt;&lt; <span class="hljs-string">'EOF'</span>
server {
    listen 80;
    server_name *.sslip.io sslip.io *.192.168.56.10.sslip.io 192.168.56.10.sslip.io;

    root /var/www/portfolio;
    index index.html index.htm;

    <span class="hljs-comment"># Basic security headers</span>
    add_header X-Frame-Options DENY always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-XSS-Protection <span class="hljs-string">"1; mode=block"</span> always;

    <span class="hljs-comment"># Gzip compression</span>
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;

    location / {
        try_files <span class="hljs-variable">$uri</span> <span class="hljs-variable">$uri</span>/ =404;
    }

    <span class="hljs-comment"># Static files caching</span>
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
        expires 1y;
        add_header Cache-Control <span class="hljs-string">"public, immutable"</span>;
    }

    <span class="hljs-comment"># Security</span>
    location ~ /\. {
        deny all;
    }
}
EOF


ln -sf /etc/nginx/sites-available/portfolio /etc/nginx/sites-enabled/
rm -f /etc/nginx/sites-enabled/default


<span class="hljs-keyword">if</span> nginx -t; <span class="hljs-keyword">then</span>
    show_success <span class="hljs-string">"Nginx configuration is valid"</span>
<span class="hljs-keyword">else</span>
    show_error <span class="hljs-string">"Nginx configuration has errors"</span>
    <span class="hljs-built_in">exit</span> 1
<span class="hljs-keyword">fi</span>


systemctl restart nginx
systemctl <span class="hljs-built_in">enable</span> nginx

show_progress <span class="hljs-string">"Setting up firewall rules"</span>
ufw allow 22/tcp
ufw allow 80/tcp
ufw --force <span class="hljs-built_in">enable</span>

VM_IP=<span class="hljs-string">"192.168.56.10"</span>
SSLIP_DOMAIN=<span class="hljs-string">"<span class="hljs-variable">${VM_IP}</span>.sslip.io"</span>

show_progress <span class="hljs-string">"Verifying installation"</span>

sleep 3

<span class="hljs-comment"># Test HTTP</span>
<span class="hljs-keyword">if</span> curl -s -o /dev/null -w <span class="hljs-string">"%{http_code}"</span> <span class="hljs-string">"http://<span class="hljs-variable">${SSLIP_DOMAIN}</span>"</span> | grep -q <span class="hljs-string">"200"</span>; <span class="hljs-keyword">then</span>
    show_success <span class="hljs-string">"HTTP site is responding correctly"</span>
<span class="hljs-keyword">else</span>
    show_warning <span class="hljs-string">"HTTP site might not be responding correctly"</span>
<span class="hljs-keyword">fi</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">""</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${GREEN}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"=================================================================="</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"             🚀 DEPLOY LISTO! 🚀                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"  🌐 Sitio de desarrollo simple listo                             "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"  🔗 HTTP + dominio sslip.io configurado                          "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"                                                                  "</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"=================================================================="</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${NC}</span>"</span>

<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${BLUE}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"📋 Access Guide:"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">""</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"🌐 Site URL: http://<span class="hljs-variable">${SSLIP_DOMAIN}</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"📝 VM IP: <span class="hljs-variable">$VM_IP</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"🔗 sslip.io domain: <span class="hljs-variable">$SSLIP_DOMAIN</span>"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">""</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"💡 Features:"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"• Simple HTTP setup"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"• No SSL complexity"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"• sslip.io automatic domain mapping"</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"• Ready for immediate development"</span>
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"<span class="hljs-variable">${NC}</span>"</span>

show_success <span class="hljs-string">"Simple development environment ready!"</span>
</code></pre>
<hr />
<h2 id="heading-ejemplo-practico-desplegando-el-portafolio">Ejemplo práctico: Desplegando el Portafolio</h2>
<p>Para hacer esto más divertido, vamos a desplegar el <strong>portafolio devops</strong></p>
<h2 id="heading-desplegando-el-entorno">Desplegando el entorno</h2>
<pre><code class="lang-bash"><span class="hljs-comment"># Clonar o crear los archivos</span>
mkdir vagrant-https-demo
<span class="hljs-built_in">cd</span> vagrant-https-demo

<span class="hljs-comment"># Crear archivos Vagrantfile y provision.sh</span>
<span class="hljs-comment"># (copiar contenido de arriba)</span>

<span class="hljs-comment"># Levantar la VM</span>
vagrant up

<span class="hljs-comment"># Verificar estado</span>
vagrant status
</code></pre>
<h2 id="heading-verificacion-y-pruebas">Verificación y pruebas</h2>
<p>Una vez desplegado, puedes probar:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Desde tu máquina host - Acceder al juego</span>
open http://192.168.56.10.sslip.io
</code></pre>
<h2 id="heading-ventajas-de-este-enfoque">Ventajas de este enfoque</h2>
<h3 id="heading-para-devops">Para DevOps:</h3>
<ul>
<li><p><strong>Infraestructura como código</strong> con Vagrant</p>
</li>
<li><p><strong>Aprovisionamiento automático</strong> repetible</p>
</li>
<li><p><strong>Entorno aislado</strong> que no afecta tu máquina</p>
</li>
<li><p><strong>Fácil destrucción y recreación</strong> (<code>vagrant destroy &amp;&amp; vagrant up</code>)</p>
</li>
</ul>
<hr />
<h2 id="heading-limpieza-y-comandos-utiles">Limpieza y comandos útiles</h2>
<pre><code class="lang-bash">bash<span class="hljs-comment"># Ver logs de Nginx</span>
vagrant ssh -c <span class="hljs-string">"sudo tail -f /var/log/nginx/error.log"</span>

<span class="hljs-comment"># Reiniciar servicios</span>
vagrant ssh -c <span class="hljs-string">"sudo systemctl restart nginx"</span>

<span class="hljs-comment"># Destruir entorno</span>
vagrant destroy -f
</code></pre>
<hr />
<h3 id="heading-conclusion">Conclusión</h3>
<p>Configurar un entorno de desarrollo local para tu portafolio web no tiene por qué ser complicado. Con <strong>Vagrant</strong>, <strong>Nginx</strong> y <a target="_blank" href="http://sslip.io"><strong>sslip.io</strong></a>, puedes levantar un servidor local funcional en cuestión de minutos, sin preocuparte por configuraciones complejas. Este flujo te permite concentrarte en lo que realmente importa: ¡tu proyecto!</p>
<p>Recuerda que la automatización y la reutilización de entornos es clave para mantener tu desarrollo ágil y eficiente. Con herramientas como <strong>Vagrant</strong> y <strong>Nginx</strong>, puedes replicar fácilmente tu configuración en cualquier máquina y compartir tu trabajo con otros sin problemas.</p>
<p>Si quieres seguir aprendiendo y profundizando en DevOps, te invito a unirte a mi <strong>Reto 90 Días de DevOps con Roxs</strong>, donde exploraremos aún más herramientas y prácticas que te ayudarán a llevar tus habilidades al siguiente nivel. ¡Nos vemos en el camino hacia un futuro DevOps más eficiente!</p>
<hr />
<h3 id="heading-nos-vemos-en-el-proximo-experimento-devops">🤘 ¡Nos vemos en el próximo experimento DevOps!</h3>
]]></content:encoded></item><item><title><![CDATA[De Cero a Roxs: Cómo Superé los Obstáculos]]></title><description><![CDATA[Cuando comencé a aprender sobre DevOps, mi entusiasmo me llevó a intentar aprenderlo todo a la vez. Docker, Kubernetes, Jenkins, Ansible, Terraform, y más… pensé que entre más rápido dominara todas las herramientas, mejor. Pero pronto me di cuenta de...]]></description><link>https://blog.295devops.com/de-cero-a-roxs-como-supere-los-obstaculos</link><guid isPermaLink="true">https://blog.295devops.com/de-cero-a-roxs-como-supere-los-obstaculos</guid><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Thu, 03 Jul 2025 16:42:23 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751559342489/6b0d1158-7074-4f17-a4ba-de6f39b6ead7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Cuando <strong>comencé a aprender sobre DevOps</strong>, mi entusiasmo me llevó a intentar aprenderlo todo a la vez. Docker, Kubernetes, Jenkins, Ansible, Terraform, y más… pensé que entre más rápido dominara todas las herramientas, mejor. Pero pronto me di cuenta de algo fundamental: <strong><mark>no todo se trata de aprender herramientas</mark></strong><mark>, se trata de comprender la visión</mark> <strong><mark> como un todo</mark></strong><mark>.</mark></p>
<p>Y esto no solo aplica en DevOps, sino en todos los desafíos que enfrentamos en la vida.</p>
<p>Hoy quiero contarte las lecciones más valiosas que aprendí durante este proceso, para que tu camino sea más claro, enfocado y, sobre todo, más eficaz. Aquí no te hablaré de atajos o fórmulas mágicas. <mark>Mi historia es sobre </mark> <strong><mark>aprender de forma constante, con la mente abierta</mark></strong><mark>, y adaptarme en cada etapa del camino.</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751559588112/78920bb4-d1ea-47bb-b81d-dc6dd5af0320.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-de-isla-de-margarita-a-devops-mi-camino-personal"><strong>De Isla de Margarita a DevOps: Mi Camino Personal</strong></h3>
<p><strong>Antes de ser “Roxs”, mi historia comenzó de una manera bastante diferente.</strong> Estudiaba <strong>Licenciatura en Informática</strong> en Isla de Margarita, Venezuela. Al principio, todo me parecía <strong>tan complejo</strong> que llegué a pensar que no era <strong>buena en eso</strong>, y me cuestioné muchas veces. La carrera me resultaba extremadamente difícil: la <strong>teoría</strong>, los <strong>profesores</strong> y los <strong>compañeros</strong> con sus grupitos, que nunca me integraban. Además, mi familia no tenía muchos recursos. Recuerdo que <strong>mi papá tuvo que vender algunas cosas</strong> para poder inscribirme en la universidad, lo que me hacía sentir aún más presionada. <strong>Mi situación económica era nada fácil</strong> y, sumado sentir que no pertenecía al mundo universitario, me sentía completamente <strong>perdida</strong>. A mitad de carrera, <strong>abandoné</strong>. Pensaba que <strong>era imposible para mí</strong> seguir en ese camino.</p>
<p>Pero la vida, como siempre, me dio una segunda oportunidad. En lugar de rendirme, comencé a trabajar en <strong>marketing digital y redes sociales</strong>, apoyando a periodistas cubriendo noticias en toda la Isla de Margarita, y fue ahí donde, casi sin darme cuenta, me acerqué a la <strong>automatización otra vez “Estaba buscando como mejorar y agilizar publicar fotos y noticias en las redes sociales</strong>.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751557892005/569a2f56-248d-4c6a-8677-62b1c2e034c1.png" alt class="image--center mx-auto" /></p>
<p>Después de ese desvío, decidí <strong>volver a estudiar y seguir en este caso con Ingeniería en Sistemas, en universidad privada para poder estudiar a la noche</strong>, pero esta vez con una nueva visión, comencé hacer aplicaciones en el mismo trabajo en el que estaba y cada vez me sentía motivada, un paso a la vez.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751557464803/1c7d198d-bb10-4580-ad71-2b75656a57b7.jpeg" alt class="image--center mx-auto" /></p>
<p><strong>Terminé mis estudios</strong> con un enfoque renovado, <strong>Roxs</strong> es Ingeniera en Sistemas</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751557738932/a52bef60-6e7a-4d2a-92d3-e97e1b5966b1.png" alt class="image--center mx-auto" /></p>
<p>El <strong>gran giro</strong> en mi historia llegó cuando tomé la decisión de mudarme a <strong>Argentina</strong>. Un nuevo país, un nuevo comienzo, y otra vez, comenzar desde cero. <mark>Aunque esta parte de la historia tiene más detalles que compartir, te contaré más adelante.</mark></p>
<p>En este nuevo capítulo, descubrí una <strong>aceleración tecnológica</strong> que no conocía. Había <strong>roles</strong> en tecnología que ni siquiera sabía que existían, y el único que conocía era el de <strong>desarrolladora</strong>... programar. Fue como si de repente, un <strong>iceberg de oportunidades</strong> se levantara ante mí, y decidí sumergirme de lleno en ese mar de nuevas posibilidades.</p>
<p>Mi primer trabajo en Argentina fue en una <strong>joyería</strong>, lo que me permitió ahorrar lo suficiente para comprar mi primera notebook. Recuerdo claramente <strong>la computadora usada que compré</strong>, y cómo, cada noche, surfeaba en aprender algo nuevo, <strong>sin roadmap</strong>, sin una guía clara. Solo me aferraba a la curiosidad y a la necesidad de <strong>darle una oportunidad a la tecnología</strong>.</p>
<p>Y, poco a poco, mi CV fue subiendo en los portales de empleo, hasta que <strong>me ofrecieron mi primera oportunidad como analista DevOps</strong>. ¡Ni siquiera sabía qué era exactamente ese rol! Pero dije que sí, me mudé a otra provincia a 1000 km, <mark>y aunque esa historia podría dar lugar a otro blog</mark>, lo más importante es que <strong>tomé la oportunidad</strong>. Fue un <strong>nuevo día cero</strong>, y a partir de allí mi vida en la tecnología <strong>despegó por completo</strong>.</p>
<hr />
<h3 id="heading-lecciones-aprendidas"><strong>Lecciones Aprendidas</strong></h3>
<p>Ahora, quiero compartirte las lecciones que me han permitido avanzar y que pueden ayudarte a recorrer un camino más sólido y efectivo en DevOps.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751560869883/8311e381-dfc4-45c8-9c00-ab8468db42c5.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-1-comienza-con-lo-basico-y-construye-una-base-solida">1. <strong>Comienza con lo Básico y Construye una Base Sólida</strong></h3>
<p>Uno de los mayores errores que cometí fue intentar abarcarlo todo desde el principio sin tener una base sólida. Aprender sobre herramientas como <strong>Docker</strong> o <strong>Kubernetes</strong> sin conocer los fundamentos de DevOps fue como intentar <strong>construir una casa sin cimientos</strong>. Durante mi pausa, me centré en los conceptos fundamentales de DevOps: <strong>control de versiones, integración continua, infraestructura como código</strong>. Comprender estos principios no solo me ayudó a entender las herramientas, sino que les dio un <strong>propósito real</strong> en mi camino.</p>
<p><strong>Lección aprendida:</strong> <strong>Domina lo básico</strong> antes de sumergirte en las herramientas. <strong>Entender el “por qué”</strong> detrás de cada herramienta te proporciona una base sólida y hace que todo lo demás sea mucho más claro.</p>
<hr />
<h3 id="heading-2-las-certificaciones-son-buenas-pero-solo-son-el-comienzo">2. <strong>Las Certificaciones Son Buenas, Pero Solo Son El Comienzo</strong></h3>
<p>Creí que las <strong>certificaciones</strong> serían la clave para dominar DevOps, pero pronto descubrí que son solo una <strong>introducción</strong>. Son útiles para construir la confianza, pero <strong>no te enseñan a resolver problemas reales</strong>. Después entendí que <strong>el aprendizaje real viene con la práctica</strong>, trabajando en proyectos que te desafíen a aplicar lo que has aprendido en entornos reales.</p>
<p><strong>Lección aprendida:</strong> Las certificaciones son valiosas, pero no te quedes ahí. <strong>El verdadero aprendizaje llega con la práctica</strong>. Los proyectos reales te enseñan a solucionar problemas y a mejorar tus habilidades.</p>
<hr />
<h3 id="heading-3-el-sindrome-del-impostor-es-normal-y-se-puede-gestionar">3. <strong>El Síndrome del Impostor Es Normal y Se Puede Gestionar</strong></h3>
<p>Uno de los mayores obstáculos que enfrenté fue <strong>el síndrome del impostor</strong>. Pensaba que no era lo suficientemente buena, y ver a otros avanzar más rápido solo me hacía sentir que no tenía lo que se necesitaba. Aprendí que este síndrome es <strong>común en casi todos los que empiezan en un campo nuevo</strong>. Me di cuenta de que debía <strong>celebrar cada pequeño logro</strong>, y establecí metas <strong>pequeñas y alcanzables</strong> para mantenerme enfocada en el progreso.</p>
<p><strong>Lección aprendida:</strong> <strong>El síndrome del impostor es normal</strong>, y todos lo enfrentamos en algún momento. <strong>Enfócate en pequeñas metas</strong>, celebra cada paso y sigue adelante. <strong>Cada paso cuenta</strong>.</p>
<hr />
<h3 id="heading-4-la-practica-real-es-clave-para-consolidar-tus-habilidades">4. <strong>La Práctica Real Es Clave para Consolidar Tus Habilidades</strong></h3>
<p>Una vez que entendí lo básico, me concentré en <strong>practicar</strong>. No solo quería saber cómo funcionaban las herramientas, sino verlas en acción. Trabajar en proyectos reales me dio la oportunidad de poner a prueba todo lo aprendido y, sobre todo, me permitió <strong>ganar confianza</strong>. Empecé con entornos de prueba y luego me lancé a proyectos más complejos. Ver los resultados tangibles de mis esfuerzos fue lo que realmente consolidó mis habilidades.</p>
<p><strong>Lección aprendida:</strong> <strong>Practica desde el primer momento.</strong> La experiencia real es la que te dará la <strong>confianza</strong> necesaria para enfrentar desafíos más grandes.</p>
<hr />
<h3 id="heading-5-esta-bien-pausar-reiniciar-y-priorizar">5. <strong>Está Bien Pausar, Reiniciar y Priorizar</strong></h3>
<p>Tomarme un descanso a veces es necesario. Me permitió <strong>revaluar mi enfoque</strong>, <strong>bajar el ritmo</strong> y establecer prioridades claras. Si te sientes abrumado, no temas hacer una pausa. Usa ese tiempo para <strong>reorientarte</strong>, reflexionar y crear un plan que sea manejable. <strong>DevOps es un viaje largo</strong>, y es mejor avanzar a un ritmo que te mantenga motivado y comprometido.</p>
<p><strong>Lección final:</strong> <strong>Pausar no significa rendirse</strong>. Es un paso para <strong>prepararte para el éxito</strong>. Aprovecha el tiempo para reflexionar, reorganizar y continuar con un enfoque renovado.</p>
<hr />
<p>Si estás empezando en DevOps, mi consejo es este: empieza poco a poco, domina lo básico y no te agobies por saberlo todo al principio. <strong>La práctica real y un ritmo más lento</strong> te permitirán <strong>asimilar más de lo que imaginas</strong>. Cuando te sientas abrumado, <strong>tómate un paso atrás</strong>. ¡Recuerda que <strong>cada paso cuenta</strong> en este camino hacia el éxito!</p>
<p><strong>Si pude hacerlo, ¡tú también puedes!</strong> Recuerda siempre que el <strong>día cero</strong> es solo el comienzo, pero si persistes, cada paso te llevará más cerca de tus metas. 💪🚀</p>
<hr />
<h3 id="heading-90-dias-de-devops-con-roxs-unete-al-desafio"><strong>90 Días de DevOps con Roxs: ¡Únete al Desafío!</strong></h3>
<p>Si te apasiona <strong>DevOps</strong> y quieres dar ese primer paso con una guía clara, te invito a unirte a mi programa <strong>90 Días de DevOps con Roxs</strong>. ¡Es completamente gratis! En este desafío, recorreremos <strong>juntos el camino de aprender, practicar y crecer en DevOps</strong>. Te acompañaré en cada etapa para que logres los conocimientos y habilidades necesarias para ser un profesional competente en el campo.</p>
<p><strong>Si quieres seguir aprendiendo y apoyarme en la creación de más contenido gratuito, puedes hacerlo en mi perfil de Ko-fi.</strong> Tu apoyo me permitirá seguir ofreciendo material valioso para la comunidad.</p>
<p>Visita <a target="_blank" href="https://roxs.295devops.com/"><strong>roxs.295devops.com</strong></a> para más información sobre el desafío y mis redes sociales.</p>
<p>¡Nos vemos en el desafío! 💥🔥</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751560565109/b4a2787b-9a49-44c9-acb5-549bbc9d634c.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[🔥 El Primer Paso en DevOps: Con Roxs, ¡Despierta Tu Fuego y Domina el Camino! 🔥]]></title><description><![CDATA[¡Hola, mis padawans onfire de la tecnología! 💥 Soy Roxs, Rossana Suarez, y hoy quiero hablarles de un tema que sé que muchos enfrentan al empezar en DevOps y Cloud: dar ese primer paso. Sé que no es fácil. El camino está lleno de dudas, inseguridade...]]></description><link>https://blog.295devops.com/el-primer-paso-en-devops-con-roxs-despierta-tu-fuego-y-domina-el-camino</link><guid isPermaLink="true">https://blog.295devops.com/el-primer-paso-en-devops-con-roxs-despierta-tu-fuego-y-domina-el-camino</guid><category><![CDATA[295devops]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Thu, 03 Jul 2025 02:53:40 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1751510225177/11c72905-6ce9-4f4a-bfff-85b2b3862d13.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>¡Hola, mis padawans onfire de la tecnología! 💥 Soy <strong>Roxs, Rossana Suarez</strong>, y hoy quiero hablarles de un tema que sé que muchos enfrentan al empezar en DevOps y Cloud: <strong>dar ese primer paso.</strong> Sé que no es fácil. El camino está lleno de dudas, inseguridades y, a veces, hasta parece que el fuego de la motivación se apaga. Pero, <strong>te aseguro que tú puedes con esto</strong>.</p>
<p>Desde el primer día que decidí sumergirme en el mundo de la tecnología, nunca imaginé lo que significaría para mí. <strong>Con cada desafío superado, descubrí que el fuego dentro de mí nunca se apagaba.</strong> Y ahora, quiero que ese mismo fuego arda en ti. <strong><mark>Porque si algo tengo claro, es que cuando decides dar el primer paso, el camino se abre ante ti</mark></strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751511101635/92d06480-d02e-4a28-b7ef-7295f09bb38f.jpeg" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-1-dar-el-primer-paso-no-es-facil-pero-ese-paso-te-define">1. <strong>Dar el Primer Paso No Es Fácil, Pero Ese Paso Te Define</strong></h3>
<p>El mundo de DevOps y Cloud puede parecer un gigante abrumador al principio. <strong>La sensación de no saber por dónde empezar es real.</strong> Pero quiero que sepas algo: <strong>el primer paso es lo más difícil, pero también es el que más te impulsa.</strong> Cuando lo des, cuando empieces a aprender, a probar herramientas, a experimentar con contenedores, <strong>ahí es cuando el fuego comienza a encenderse.</strong></p>
<p>Sé que no es fácil, pero <strong>el primer paso te cambia</strong>. A partir de ese momento, ya no hay vuelta atrás. Cada pequeña victoria, cada línea de código que aprendas, cada vez que consigas algo que no sabías que podías hacer, será un paso más en tu viaje.</p>
<hr />
<h3 id="heading-2-fracasos-una-trampa-o-una-oportunidad">2. <strong>Fracasos, ¿Una Trampa o Una Oportunidad?</strong></h3>
<p>¡Déjame decirte algo! <strong>Los fracasos no son el fin del mundo</strong>, son el combustible que enciende tu motor. Si caíste, si algo no funcionó, si el contenedor no se levantó como esperabas… ¡no te preocupes! Es solo una oportunidad de aprender, <strong>de mejorar</strong>.</p>
<p>En DevOps y Cloud, <strong>el error es una herramienta poderosa</strong>. Cada error significa que estás un paso más cerca de dominarlo. <strong>Fallar rápido, aprender rápido</strong>. Y lo más importante, <strong>no te rindas.</strong> Cada paso hacia adelante es un triunfo, y aunque no lo creas, <strong>cuando te levantes de nuevo, tu fuego será aún más fuerte.</strong></p>
<hr />
<h3 id="heading-3-sigue-aprendiendo-porque-el-fuego-nunca-se-apaga">3. <strong>Sigue Aprendiendo, Porque El Fuego Nunca Se Apaga</strong></h3>
<p>En DevOps, <strong>la curva de aprendizaje es infinita</strong>, pero eso es lo que la hace tan excitante. ¡Hay tanto por aprender! Desde Kubernetes, hasta Docker, AWS, y mucho más. <strong>La clave está en seguir avanzando</strong>. Si hoy no entiendes algo, ¡mañana lo harás! La tecnología avanza, y tú con ella.</p>
<p>No importa lo que te enfrentes, <strong>el fuego de aprender es lo que te hará imparable</strong>. Cada nuevo conocimiento es una chispa que avivará tu pasión, y esa pasión te llevará a hacer cosas increíbles. <strong>Nunca dejes de aprender, nunca dejes de arder.</strong></p>
<hr />
<h3 id="heading-4-nunca-estas-solo-la-comunidad-es-tu-mayor-fuerza">4. <strong>Nunca Estás Solo: La Comunidad es Tu Mayor Fuerza</strong></h3>
<p>Una de las cosas más increíbles de este mundo es <strong>la comunidad</strong>. Aquí, nadie se queda atrás. No tengas miedo de pedir ayuda, de conectarte con otros, de compartir tus dudas. <strong>La comunidad tecnológica está llena de personas dispuestas a levantarte cuando lo necesites.</strong></p>
<p>Cuando estés en esos momentos difíciles, donde parece que todo está en contra, <strong>recuerda que puedes contar con los demás</strong>. ¡Aquí estamos para apoyarnos y crecer juntos! Si algo he aprendido en mi camino es que las conexiones y los lazos que creas son lo que realmente marca la diferencia.</p>
<hr />
<h3 id="heading-5-construye-tu-red-porque-juntos-somos-mas-fuertes">5. <strong>Construye Tu Red, Porque Juntos Somos Más Fuertes</strong></h3>
<p>Tu red de contactos es oro puro. <strong>No se trata solo de LinkedIn, se trata de las conexiones reales</strong>, de esas personas que te inspiran, te motivan y te ayudan a ser mejor cada día. <strong>Asiste a eventos, participa en meetups, únete a grupos online</strong>. Cada persona que cruza tu camino puede ser un mentor, una fuente de motivación, o incluso un aliado para el futuro.</p>
<p><strong>El poder de tu red está en la colaboración.</strong> Así que, nunca subestimes el impacto de las personas que conoces en tu camino. Juntos, ¡podemos conquistar todo lo que se nos ponga enfrente!</p>
<hr />
<h3 id="heading-6-descanso-recarga-y-vuelve-con-mas-fuerza">6. <strong>Descanso, Recarga, ¡Y Vuelve Con Más Fuerza!</strong></h3>
<p>No olvides algo fundamental: <strong>también está bien descansar.</strong> A veces, lo mejor que puedes hacer por tu aprendizaje es <strong>alejarte un poco</strong>. Sal a caminar, haz ejercicio, desconéctate de la pantalla, ¡y cuando regreses, vuelve con el doble de energía! 🚀</p>
<p>Los descansos no son una debilidad, <strong>son una estrategia para regresar más fuerte y más enfocado.</strong> Así que, recarga tu fuego, y sigue con más ganas que nunca.</p>
<hr />
<h3 id="heading-7-celebra-cada-logro-porque-tienes-fuego">7. <strong>Celebra Cada Logro, ¡Porque Tienes Fuego! 🔥</strong></h3>
<p>Recuerda siempre celebrar tus logros, <strong>por pequeños que sean.</strong> Cada paso que des es una victoria. Hoy aprendiste a configurar un contenedor, mañana has desplegado tu primera aplicación en la nube, y pasado mañana automatizas tu primer pipeline CI/CD. <strong>Cada logro suma, y es parte de tu historia de fuego.</strong></p>
<p>Como dice Roxs, <strong>cada victoria te acerca más a ser imparable.</strong> ¡Celebra con fuerza, celebra con pasión, porque el fuego está en vos!</p>
<hr />
<h3 id="heading-y-por-eso-nacio-90-dias-de-devops-con-roxs"><strong>Y Por Eso Nació "90 Días de DevOps con Roxs" 🔥</strong></h3>
<p>Este camino puede ser solitario a veces, pero <strong>no tiene que serlo.</strong> <strong>Por eso nació "90 Días de DevOps con Roxs"</strong>, un desafío práctico en DevOps, donde todos vamos <strong>codo a codo, aprendiendo y creciendo juntos.</strong> Este reto es una oportunidad única para dar ese primer paso, enfrentar los desafíos y avanzar en la práctica. Aquí, <strong>te voy a acompañar en cada etapa</strong> para que ese fuego nunca se apague.</p>
<p>Si aún no te has unido, <strong>aún estás a tiempo</strong>, siempre que tengas la fuerza y la determinación. 💪 Juntos vamos a acelerar ese aprendizaje, a convertir cada dificultad en un impulso, y a asegurarnos de que, cuando llegues a la meta, no solo hayas aprendido, sino que hayas transformado todo tu ser en un <strong>devops on fire</strong>. 🔥🔥🔥</p>
<p><strong>Revisa mi página con todos los enlaces</strong> <a target="_blank" href="https://roxs.295devops.com/">https://roxs.295devops.com/</a> y no te pierdas ninguna de las oportunidades que tengo para ti. Además, te invito a que <strong>te suscribas a mi canal de YouTube</strong> aquí donde subo contenido exclusivo para que sigas aprendiendo con nosotros.</p>
<p><img src="https://sdmntprwestus2.oaiusercontent.com/files/00000000-52ec-61f8-9218-f8299038e986/raw?se=2025-07-03T03%3A52%3A25Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=604e20f8-c25d-55db-9d5b-f387f2f06c9f&amp;skoid=24a7dec3-38fc-4904-b888-8abe0855c442&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-07-02T16%3A10%3A34Z&amp;ske=2025-07-03T16%3A10%3A34Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=Le3N%2BEbIpMH59NfqP/XiOCgWfJ5sRkUyrruzgf6kihQ%3D" alt /></p>
<hr />
<h3 id="heading-antes-de-mis-reflexiones-finales-mi-historia"><strong>Antes de mis Reflexiones Finales: Mi Historia</strong></h3>
<p><img src="https://scontent.fres5-1.fna.fbcdn.net/v/t39.30808-6/467401072_10235118337919883_4134251905844010659_n.jpg?_nc_cat=103&amp;ccb=1-7&amp;_nc_sid=127cfc&amp;_nc_ohc=6ahMEKHO-N0Q7kNvwHu6g4R&amp;_nc_oc=AdnbE_GR7HVq6cUFDF1_EYjYgmVHh-CNpLZDeHU_kBhERshLRyCjruryLiWzda-w4YhPIyNDZ0C__ZHxHv7yQT7u&amp;_nc_zt=23&amp;_nc_ht=scontent.fres5-1.fna&amp;_nc_gid=rv6wSEidXNnbyG7uQ6m_Tw&amp;oh=00_AfMcYu-o7aihQK-BWgYNuw9giMIStwGcUq4QJZczhoTHdQ&amp;oe=686BDBE2" alt="No hay ninguna descripción de la foto disponible." /></p>
<p>Quiero compartir una imagen de <strong>quién era yo antes de entrar 100% en la tecnología</strong>. Esa era yo antes de tener rumbo, sin fuego ni objetivos claros, viviendo entre un sueldo y sin sueños, sin saber qué hacer con mi vida. <strong>No sabía qué era el fuego</strong>, pero con esfuerzo y determinación, me levanté.</p>
<p>Hoy, <strong>estoy aquí</strong> para demostrar que <strong>todos podemos empezar de cero.</strong> Mi historia la contaré en otro post, pero lo que quiero que te lleves hoy es que <strong>el fuego se enciende cuando decides dar ese primer paso.</strong> Si yo pude, ¡tú también puedes!</p>
<hr />
<h3 id="heading-reflexiones-finales">Reflexiones Finales</h3>
<p><strong>Roxs te dice: <mark>El primer paso es solo el principio.</mark></strong> <strong><mark>¡Este viaje va a ser increíble, y el fuego que llevas dentro es todo lo que necesitas!</mark></strong> Así que no te detengas, no te rindas, y sigue aprendiendo, creciendo, y sobre todo, <strong>mantén ese fuego ardiendo</strong>.</p>
<p>Hoy comenzaste este viaje, y <strong>mañana serás el que inspire a otros a dar su primer paso.</strong> Porque cuando tienes el fuego de Roxs en ti, no hay límites.</p>
<p>¡Vamos con todo! <strong>¡El futuro es tuyo, y el fuego nunca se apaga! 🔥🔥🔥</strong></p>
]]></content:encoded></item><item><title><![CDATA[🔥 El Éxito Es una Decisión: Elegí Desplegarte]]></title><description><![CDATA[Muchas veces escuchamos frases como “todos tenemos las mismas oportunidades” o “si querés, podés”. Y aunque suenan lindas, la realidad es más compleja. Las oportunidades no siempre son justas ni están repartidas de forma equitativa. Nacer en ciertos ...]]></description><link>https://blog.295devops.com/el-exito-es-una-decision-elegi-desplegarte</link><guid isPermaLink="true">https://blog.295devops.com/el-exito-es-una-decision-elegi-desplegarte</guid><category><![CDATA[motivation]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Wed, 11 Jun 2025 23:13:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1749683255224/1a0e9c45-f31f-41a8-953a-cf8a6ba1b475.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Muchas veces escuchamos frases como <strong><em>“todos tenemos las mismas oportunidades”</em> o <em>“si querés, podés”</em>.</strong> Y aunque suenan lindas, la realidad es más compleja. Las oportunidades no siempre son justas ni están repartidas de forma equitativa. Nacer en ciertos contextos, enfrentarse a barreras invisibles (y otras bien visibles), cargar con historias familiares, o simplemente tener que pelearla más que el resto... no es cuento: es vida.</p>
<p><mark>Pero, en medio de todo eso, hay algo que no puede quitártelo nadie: tu decisión.</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1749683562494/3197bae4-434a-4113-90b1-cb45253f9723.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-que-es-el-exito-y-quien-lo-define">✨ ¿Qué es el éxito? ¿Y quién lo define?</h2>
<p>La sociedad nos vende que ser exitoso es tener plata, fama o un puesto con título rimbombante. Pero vos y yo sabemos que eso no es todo. Para mí, y para muchas personas que conozco en comunidad, el éxito puede ser cosas como:</p>
<ul>
<li><p>Terminar el deploy que te venía fallando hace días.</p>
</li>
<li><p>Animarte a levantar la mano en una daily.</p>
</li>
<li><p>Compartir tu primer blog o crear tu primer repo público.</p>
</li>
<li><p>O simplemente seguir adelante, aún cuando sentís que el mundo se te viene encima.</p>
</li>
</ul>
<p>Cada quien tiene su propia definición de éxito, y está bien. Lo importante es que la definas <em>vos</em>.</p>
<hr />
<h2 id="heading-la-receta-secreta-no-es-tan-secreta-espiritu-indomable">💪 La receta secreta no es tan secreta: espíritu indomable</h2>
<p>Sí, hay factores que ayudan: tener tiempo, apoyo, acceso a tecnología, buenos mentores. Pero lo que realmente te hace seguir cuando todo tiembla es ese fuego interno, ese <em>“no me rindo”</em>, ese <em>mindset de superación constante</em> que decidís renovar todos los días.</p>
<p>Lo llamo <strong>espíritu indomable</strong>.</p>
<p>Ese fuego que te hace:</p>
<p>🔥 Volver a intentar después de un error.</p>
<p>🔥 Estudiar de madrugada aunque estés cansado.</p>
<p>🔥 Creer en vos cuando nadie más lo hace.</p>
<p>Y no es magia. Es una elección diaria. Elegís seguir. Elegís crecer. Elegís mejorar. <em>Elegís ser tu propia versión del éxito.</em></p>
<hr />
<h2 id="heading-grit-foco-y-vulnerabilidad">🧠 Grit, foco y vulnerabilidad</h2>
<p>El éxito real no es lineal ni glamoroso. Es ensayo y error. Es llorar frente a la compu y volver al rato con más fuerza. Es aprender a decir <em>“no sé”</em>, buscar ayuda, compartir lo que sabés y apoyar a otros en su camino.</p>
<p>No se trata solo de talento o inteligencia. Se trata de <strong>grit</strong>: esa mezcla de pasión + perseverancia + resistencia que te mantiene en el camino, incluso cuando se vuelve cuesta arriba.</p>
<hr />
<h2 id="heading-vos-podes-redefinir-el-sistema-aunque-el-sistema-no-sea-justo">🌎 Vos podés redefinir el sistema (aunque el sistema no sea justo)</h2>
<p>¿La igualdad de oportunidades es real? No del todo. Pero eso no significa que nos tengamos que resignar.</p>
<p>Desde nuestros espacios ya sea una comunidad tech, un bootcamp, una empresa o un canal de YouTube podemos construir un entorno más justo, más inclusivo y con menos barreras. Donde no importe de dónde venís, sino las ganas que tenés de llegar.</p>
<p>Yo lo vivo todos los días en la comunidad de <strong>90 Días de DevOps con Roxs</strong>: hay gente que viene de diseño, de marketing, de cocina, de mil lados. Y todos crecen. Porque el primer paso fue elegir intentar.</p>
<hr />
<h2 id="heading-conclusion-el-exito-no-es-destino-es-camino">💥 Conclusión: El éxito no es destino, es camino</h2>
<p>Elegí tu definición. Caminá tu trayecto. Rodeate de gente que encienda tu fuego.</p>
<p>Y nunca olvides esto:</p>
<blockquote>
<p><strong>“Éxito no es tener más que otros, es tener más de vos mismo que ayer.”</strong></p>
</blockquote>
<p>🌟 El éxito no te llega por suerte. El éxito se construye. El éxito, como el crecimiento, <strong>es una elección diaria</strong>.</p>
<p>¿Y vos? ¿Hoy qué elegís?</p>
<hr />
<h2 id="heading-seguime-y-sumate-al-fuego">🔗 Seguime y sumate al fuego</h2>
<p>📚 Todo mi contenido, comunidad y redes:<br />👉 <a target="_blank" href="https://roxs.295devops.com">https://roxs.295devops.com</a></p>
<p>🎥 Canal de YouTube con clases, desafíos y comunidad ON FIRE:<br />👉 <a target="_blank" href="https://www.youtube.com/@295devops">https://www.youtube.com/@295devops</a></p>
<p>👾 ¿Querés aprender DevOps desde cero? Unite al reto <a target="_blank" href="https://90daysdevops.295devops.com/">90 Días de DevOps con Roxs</a></p>
<p>🔥 ¡Te espero con fuego y superpower para que despleguemos juntxs!</p>
<hr />
]]></content:encoded></item><item><title><![CDATA[🚀 Cómo armé mi propio laboratorio DevOps: stack completo con monitoreo incluido]]></title><description><![CDATA[Hace tiempo vengo buscando una forma práctica y didáctica de enseñar DevOps sin depender de servicios pagos, con todo corriendo localmente, y que además sea realista. Así nació roxs-devops-stack, un laboratorio educativo con FastAPI, PostgreSQL, Ngin...]]></description><link>https://blog.295devops.com/como-arme-mi-propio-laboratorio-devops-stack-completo-con-monitoreo-incluido</link><guid isPermaLink="true">https://blog.295devops.com/como-arme-mi-propio-laboratorio-devops-stack-completo-con-monitoreo-incluido</guid><category><![CDATA[Devops]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sun, 25 May 2025 20:51:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748203082762/e9226847-33c2-4a20-a2f0-0c5c2c7bd133.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hace tiempo vengo buscando una forma práctica y didáctica de enseñar DevOps sin depender de servicios pagos, con todo corriendo localmente, y que además sea realista. Así nació <a target="_blank" href="https://github.com/roxsross/roxs-devops-stack"><strong>roxs-devops-stack</strong></a>, un laboratorio educativo con FastAPI, PostgreSQL, Nginx, Docker Compose y todo un stack de monitoreo con Prometheus y Grafana... ¡sí, todo en tu compu! 🧠💻</p>
<hr />
<h2 id="heading-pre-requisitos-tecnicos">📦 Pre-requisitos técnicos</h2>
<p>Para correr este laboratorio necesitás:</p>
<p>🔹 <strong>Docker Desktop</strong> instalado y corriendo<br />🔹 <strong>Docker Compose</strong> v2.34 o superior * ya viene incluido en el docker desktop<br />🔹 <strong>Make</strong> (opcional, pero súper útil)<br />🔹 Sistema operativo: Linux, macOS o Windows con WSL2<br />🔹 Al menos <strong>4 GB de RAM</strong> (recomendado 8 GB)<br />🔹 Mínimo <strong>5 GB libres</strong> en disco<br />🔹 Conexión a internet para descargar imágenes la primera vez</p>
<p>Verificá si ya tenés todo listo:</p>
<pre><code class="lang-bash">docker version
Client:
 Version:           28.0.4
 API version:       1.48
 Go version:        go1.23.7
 Git commit:        b8034c0
 Built:             Tue Mar 25 15:06:09 2025
 OS/Arch:           darwin/arm64
 Context:           desktop-linux

docker compose version

Docker Compose version v2.34.0-desktop.1

make --version <span class="hljs-comment"># (opcional)</span>
</code></pre>
<blockquote>
<p>💡 Si estás en Windows, asegurate de tener <strong>WSL2 activado</strong> y Docker corriendo correctamente.</p>
</blockquote>
<p>Podes completar el setup con mi blog anterior <a target="_blank" href="https://blog.295devops.com/crea-tu-laboratorio-devops-local-sin-gastar-un-peso">https://blog.295devops.com/crea-tu-laboratorio-devops-local-sin-gastar-un-peso</a></p>
<hr />
<h2 id="heading-que-vas-a-encontrar-en-este-proyecto">🎯 ¿Qué vas a encontrar en este proyecto?</h2>
<p>La idea es que puedas aprender y practicar DevOps sin vueltas. El stack incluye:</p>
<ul>
<li><p><strong>Frontend con Nginx</strong> y HTML/CSS/JS vanilla</p>
</li>
<li><p><strong>Backend con FastAPI</strong> y PostgreSQL</p>
</li>
<li><p><strong>Docker y Docker Compose</strong> para orquestar todo</p>
</li>
<li><p><strong>Prometheus + Grafana</strong> para monitoreo real</p>
</li>
<li><p><strong>Node Exporter</strong> para métricas de sistema</p>
</li>
<li><p>Un <strong>Makefile</strong> lleno de comandos útiles</p>
</li>
<li><p>Dashboards visuales listos para usar</p>
</li>
</ul>
<blockquote>
<p>💡 Ideal para quienes quieren aprender DevOps desde cero o armar su propio laboratorio para practicar CI/CD, monitoreo, troubleshooting y más.</p>
</blockquote>
<hr />
<h2 id="heading-arquitectura-simple-pero-poderosa">🧱 Arquitectura simple pero poderosa</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748203822050/628ab900-7b9e-4edc-bd50-c5e14afb0fa3.png" alt class="image--center mx-auto" /></p>
<p>Todo esto conectado por redes Docker personalizadas (<code>roxs-devops-network</code> y <code>roxs-monitoring-network</code>), con métricas expuestas en <code>/metrics</code> y monitoreo en tiempo real de toda la aplicación. <mark>¡Literalmente podés ver cuántas requests hacés y cómo responde tu app! 🔍📈</mark></p>
<hr />
<h2 id="heading-como-lo-usas">🧪 ¿Cómo lo usás?</h2>
<ol>
<li><strong>Clonás el repo</strong>:</li>
</ol>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/roxsross/roxs-devops-stack
<span class="hljs-built_in">cd</span> roxs-devops-stack
make install
make all
</code></pre>
<ol start="2">
<li>Accedé a los servicios:</li>
</ol>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Servicio</td><td>URL</td></tr>
</thead>
<tbody>
<tr>
<td>Frontend</td><td><a target="_blank" href="http://localhost">http://localhost</a></td></tr>
<tr>
<td>Backend API</td><td><a target="_blank" href="http://localhost:3000">http://localhost:3000</a></td></tr>
<tr>
<td>Docs API (Swagger)</td><td><a target="_blank" href="http://localhost:3000/docs">http://localhost:3000/docs</a></td></tr>
<tr>
<td>Prometheus</td><td><a target="_blank" href="http://localhost:9090">http://localhost:9090</a></td></tr>
<tr>
<td>Grafana</td><td><a target="_blank" href="http://localhost:3001">http://localhost:3001</a> <a target="_blank" href="http://localhost">(admin/admin)</a></td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-que-podes-hacer">🎮 ¿Qué podés hacer?</h2>
<ul>
<li><p>Crear, listar, editar y borrar ítems desde el frontend</p>
</li>
<li><p>Ver métricas como requests, latencia, uptime</p>
</li>
<li><p>Ver dashboards en Grafana con performance y estado de todos los servicios</p>
</li>
<li><p>Inspeccionar logs del backend</p>
</li>
<li><p>Ver el estado de salud de cada contenedor</p>
</li>
<li><p>Probar los endpoints con <code>curl</code> o Swagger UI</p>
</li>
</ul>
<hr />
<h2 id="heading-el-toque-devops-metrica-logging-y-dashboards">📊 El toque DevOps: métrica, logging y dashboards</h2>
<p>Este no es solo un “todo corre en Docker”, sino que <strong>incluye un sistema de monitoreo funcional</strong>, con:</p>
<ul>
<li><p>Dashboards listos en Grafana</p>
</li>
<li><p>Métricas de performance de la API</p>
</li>
<li><p>Estado de la base de datos</p>
</li>
<li><p>Logs estructurados del backend</p>
</li>
<li><p>Health checks, latencia y uptimes</p>
</li>
</ul>
<blockquote>
<p>🎯 ¡Ideal para aprender Prometheus y Grafana sin pelearte con configuraciones!</p>
</blockquote>
<hr />
<h2 id="heading-que-aprendes-armandolo">🛠️ ¿Qué aprendés armándolo?</h2>
<ul>
<li><p>Cómo dockerizar backend y frontend</p>
</li>
<li><p>Cómo conectar servicios con redes personalizadas</p>
</li>
<li><p>Cómo exponer y recolectar métricas con Prometheus</p>
</li>
<li><p>Cómo visualizar todo con Grafana</p>
</li>
<li><p>Cómo automatizar con Makefile</p>
</li>
<li><p>Troubleshooting real con logs y health checks</p>
</li>
</ul>
<hr />
<h2 id="heading-screenshots-by-roxs"><strong>📸 Screenshots by ROXS</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748203589880/cc8543b6-d55c-4cce-ad56-53a30b38fbb1.png" alt class="image--center mx-auto" /></p>
<p>Revisa en: <a target="_blank" href="https://github.com/roxsross/roxs-devops-stack">https://github.com/roxsross/roxs-devops-stack</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748203620044/1b2f30e2-c444-4a0b-a3b1-3f0a22e2f7ee.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748203607787/c8fa9992-d26f-4845-a2c8-9703f1f40bf6.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-casos-de-uso-recomendados">🧪 Casos de uso recomendados</h2>
<ul>
<li><p>🔍 Simular caídas y ver alertas en Prometheus/Grafana</p>
</li>
<li><p>🧩 Practicar debugging usando métricas y logs</p>
</li>
<li><p>📈 Agregar nuevas métricas personalizadas a FastAPI</p>
</li>
<li><p>🔐 Experimentar con escaneos de seguridad (Próximo paso del roadmap)</p>
</li>
<li><p>📦 Crear tu pipeline CI/CD con GitHub Actions usando este stack como base</p>
</li>
</ul>
<hr />
<h2 id="heading-detras-del-monitoreo">📊 Detrás del monitoreo</h2>
<p>La app expone métricas en <code>/metrics</code> usando Prometheus client for Python. Entre las métricas disponibles:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><a target="_blank" href="https://github.com/prometheus/client_python">Métrica</a></td><td><a target="_blank" href="https://github.com/prometheus/client_python">Sig</a>nificado</td></tr>
</thead>
<tbody>
<tr>
<td><code>http_requests_total</code></td><td>Requests HTTP totales</td></tr>
<tr>
<td><code>http_request_duration_seconds</code></td><td>Latencia promedio</td></tr>
<tr>
<td><code>database_items_total</code></td><td>Cantidad de ítems en la DB</td></tr>
<tr>
<td><code>app_uptime_seconds</code></td><td>Tiempo que lleva activa la app</td></tr>
<tr>
<td><code>database_status</code></td><td>Estado de conexión a PostgreSQL</td></tr>
</tbody>
</table>
</div><p>Todo esto es recolectado por <strong>Prometheus</strong>, y luego <strong>Grafana</strong> lo grafica automáticamente. Ya incluye dashboards preconfigurados.</p>
<hr />
<h2 id="heading-makefile-tu-asistente-devops">🧰 Makefile: tu asistente DevOps</h2>
<p>El <code>Makefile</code> te ahorra escribir comandos largos. Algunos highlights:</p>
<pre><code class="lang-bash">make up                <span class="hljs-comment"># Levanta la app</span>
make down              <span class="hljs-comment"># La detiene</span>
make monitoring        <span class="hljs-comment"># Solo Prometheus + Grafana</span>
make logs              <span class="hljs-comment"># Ver logs en tiempo real</span>
make health            <span class="hljs-comment"># Chequeo de salud de servicios</span>
make urls              <span class="hljs-comment"># Muestra todas las URLs</span>
</code></pre>
<hr />
<h3 id="heading-y-si-no-quiero-usar-make">⚙️ ¿Y si no quiero usar <code>make</code>?</h3>
<p>Sin drama. Todos los comandos del Makefile también se pueden ejecutar manualmente con Docker Compose. Acá te dejo los pasos:</p>
<h4 id="heading-levantar-la-aplicacion-sin-make">🔧 Levantar la aplicación sin <code>make</code></h4>
<pre><code class="lang-bash"><span class="hljs-comment"># 1. Cloná el repo</span>
git <span class="hljs-built_in">clone</span> https://github.com/roxsross/roxs-devops-stack
<span class="hljs-built_in">cd</span> roxs-devops-stack

<span class="hljs-comment"># 2. Levantar la aplicación principal</span>
docker compose -f docker-compose.yml up -d

<span class="hljs-comment"># 3. Levantar el stack de monitoreo</span>
docker compose -f docker-compose.monitoring.yml up -d
</code></pre>
<h4 id="heading-acceder-a-los-servicios">📊 Acceder a los servicios</h4>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Servicio</td><td>URL</td></tr>
</thead>
<tbody>
<tr>
<td>Frontend</td><td><a target="_blank" href="http://localhost">http://localhost</a></td></tr>
<tr>
<td>Backend API</td><td><a target="_blank" href="http://localhost:3000">http://localhost:3000</a></td></tr>
<tr>
<td>Swagger Docs</td><td><a target="_blank" href="http://localhost:3000/docs">http://localhost:3000/docs</a></td></tr>
<tr>
<td>Prometheus</td><td><a target="_blank" href="http://localhost:9090">http://localhost:9090</a></td></tr>
<tr>
<td>Grafana</td><td><a target="_blank" href="http://localhost:3001">http://localhost:3001</a> (admin/admin)</td></tr>
</tbody>
</table>
</div><h4 id="heading-ver-logs">🔍 Ver logs</h4>
<pre><code class="lang-bash">docker compose logs -f
docker compose -f docker-compose.monitoring.yml logs -f
</code></pre>
<blockquote>
<p>💡 Consejo: si no usás <code>make</code>, podés revisar el archivo <code>Makefile</code> para ver todos los comandos disponibles y adaptarlos a tu estilo.</p>
</blockquote>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Si utilizas una versión de Docker Compose anterior a la v2.34.0 (incluida en Docker Desktop), debes usar el comando <code>docker-compose</code> con guión en lugar de <code>docker compose</code> separado.</div>
</div>

<hr />
<h2 id="heading-como-personalizar-este-stack">💡 ¿Cómo personalizar este stack?</h2>
<p>Algunas ideas para que lo hagas tuyo:</p>
<ul>
<li><p>Cambiá la base de datos a MySQL o MongoDB</p>
</li>
<li><p>Usá React o Vue como frontend (sirve igual con Nginx)</p>
</li>
<li><p>Agregá tu propio microservicio</p>
</li>
<li><p>Sumá alertas reales con <code>Alertmanager</code></p>
</li>
<li><p>Añadí un <code>Dockerfile</code> para testing o CI</p>
</li>
</ul>
<hr />
<h2 id="heading-queres-probarlo">🧠 ¿Querés probarlo?</h2>
<p>👉 <a target="_blank" href="https://github.com/roxsross/roxs-devops-stack">https://gith</a><a target="_blank" href="http://localhost/">ub.com/roxsross/</a><a target="_blank" href="https://github.com/roxsross/roxs-devops-stack">roxs-devops-sta</a><a target="_blank" href="http://localhost/">ck</a></p>
<p>Dale una estrella ⭐ si te gusta, y escribime si querés sumarte a contribuir o tenés ideas.</p>
<hr />
<h2 id="heading-que-sigue">🔮 ¿Qué sigue?</h2>
<p>Este es solo el comienzo. En el roadmap tengo pensado:</p>
<ul>
<li><p>CI/CD completo con GitHub Actions</p>
</li>
<li><p>Deploy en Kubernetes con Helm y ArgoCD</p>
</li>
<li><p>Configuración de Terraform para IaC</p>
</li>
<li><p>Integración con herramientas de seguridad</p>
</li>
<li><p>Test de performance y Chaos Engineering</p>
</li>
</ul>
<p>¡Y todo lo vas a poder practicar con este stack base! 💥</p>
<hr />
<h2 id="heading-bonus-se-viene-90-dias-de-devops-by-roxs">🎓 Bonus: se viene <strong>"90 Días</strong> <strong>de DevOps by Roxs"</strong> 🚀</h2>
<p>¿Querés aprender DevOps en serio, acompañado/a, y con práctica real?</p>
<p>🧑‍💻 Estoy lanzando una experiencia gratuita llamada <strong>90 Días de DevOps by Roxs</strong>, con:</p>
<ul>
<li><p>🔁 Encuentros <strong>semanales ó quincenales</strong> (según cómo avancemos)</p>
</li>
<li><p>📦 Proyectos reales como el <code>roxs-devops-stack</code></p>
</li>
<li><p>💬 Comunidad privada para dudas, feedback y networking</p>
</li>
<li><p>📈 Desafíos técnicos, guías y tips de carrera</p>
</li>
<li><p>🤝 Totalmente <strong>GRATIS</strong> (solo cupo limitado)</p>
</li>
</ul>
<p>🎯 <strong>Solo para las primeras 200 personas</strong></p>
<p><img src="https://sdmntprwestus3.oaiusercontent.com/files/00000000-c51c-61fd-86ef-5007f762bd57/raw?se=2025-05-25T20%3A57%3A17Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=3fc8dd31-3c37-52f9-9852-abc6155f7694&amp;skoid=864daabb-d06a-46b3-a747-d35075313a83&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-05-25T00%3A21%3A36Z&amp;ske=2025-05-26T00%3A21%3A36Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=yff0OFuIIdft8KYJayRmBGsmOnBdcXx0HvidLjFsM18%3D" alt="Imagen generada" /></p>
<hr />
<h3 id="heading-queres-participar">👉 ¿Querés participar?</h3>
<p>📩 Completá este <a target="_blank" href="https://forms.gle/iRTeHW8wrxcihbfm9">formulario de interés</a> o escribime por redes y te mando el acceso cuando abramos inscripciones.</p>
<blockquote>
<p>¡Va a ser una aventura intensa, práctica y transformadora!</p>
</blockquote>
<hr />
<h2 id="heading-contacto">✉️ Contacto</h2>
<ul>
<li><p>🐦 Twitter: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p>🔗 LinkedIn: <a target="_blank" href="https://linkedin.com/in/roxsross">roxsross</a></p>
</li>
<li><p>▶️ Youtube: <a target="_blank" href="https://www.youtube.com/@295devops">295devops</a></p>
</li>
<li><p>💌 Email: roxs@295devops.com</p>
</li>
</ul>
<hr />
<h3 id="heading-nos-vemos-en-el-proximo-experimento-devops">🤘 ¡Nos vemos en el próximo experimento DevOps!</h3>
]]></content:encoded></item><item><title><![CDATA[🎮 Crea tu Laboratorio DevOps Local (¡Sin Gastar un Peso!)]]></title><description><![CDATA[🚨 El Problema: Practicar DevOps sin miedo a la factura
A Sofía, como a muchos que están aprendiendo DevOps, le pasaba lo siguiente: leía sobre CI/CD, containers, automatización… pero al momento de practicar, todo requería usar AWS, Azure o GCP.
“Reg...]]></description><link>https://blog.295devops.com/crea-tu-laboratorio-devops-local-sin-gastar-un-peso</link><guid isPermaLink="true">https://blog.295devops.com/crea-tu-laboratorio-devops-local-sin-gastar-un-peso</guid><category><![CDATA[Docker]]></category><category><![CDATA[ansible]]></category><category><![CDATA[tools]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Fri, 23 May 2025 18:17:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1748007621530/ca2362ed-db7b-4a21-a237-a1c0e9859f7b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-el-problema-practicar-devops-sin-miedo-a-la-factura">🚨 El Problema: Practicar DevOps sin miedo a la factura</h2>
<p><strong><mark>A Sofía</mark></strong><mark>, como a muchos que están aprendiendo DevOps, le pasaba lo siguiente: leía sobre CI/CD, containers, automatización… pero al momento de practicar, todo requería usar AWS, Azure o GCP.</mark></p>
<p>“Registrate en el nivel gratuito,” decían todos los tutoriales. Pero ella sabía que esos "free tiers" tienen límites, y había leído historias de terror donde el descuido de dejar un recurso encendido se traducía en una factura de cientos de dólares.</p>
<p><img src="https://i.redd.it/lmyrdzu7twc91.jpg" alt="Using AWS : r/ProgrammerHumor" class="image--center mx-auto" /></p>
<p><strong>Sofía pensó: <em>“¿Y si armo todo local, sin depender del cloud?”</em> Y así fue como descubrió el poder de un laboratorio DevOps en su laptop/notebook/pc.</strong></p>
<hr />
<h2 id="heading-devops-explicado-sencillo">🛠️ DevOps explicado sencillo</h2>
<p>DevOps es colaboración. Imaginá que estás construyendo una casa: los desarrolladores serían los arquitectos, y el equipo de operaciones, los albañiles. En modelos tradicionales, estos equipos apenas se hablan. DevOps propone que trabajen codo a codo desde el día uno. Así se entregan soluciones más rápidas, estables y de mejor calidad.</p>
<h3 id="heading-herramientas-claves-que-vas-a-usar">Herramientas claves que vas a usar:</h3>
<ul>
<li><p><strong>Docker</strong>: Contenedores que empacan tu app con todo lo necesario para correr.</p>
</li>
<li><p><strong>Kubernetes</strong>: Orquestador que gestiona múltiples contenedores.</p>
</li>
<li><p><strong>Vagrant</strong>: Te permite levantar máquinas virtuales de forma fácil.</p>
</li>
<li><p><strong>Ansible</strong>: Automatiza tareas repetitivas como configurar servidores.</p>
</li>
<li><p><strong>Terraform</strong>: Infraestructura como código: define entornos con archivos <code>.tf</code>.</p>
</li>
</ul>
<hr />
<h2 id="heading-ventajas-de-montar-tu-laboratorio-local">🚀 Ventajas de montar tu laboratorio local</h2>
<ul>
<li><p>💸 <strong>Costo cero</strong>: sin facturas sorpresa.</p>
</li>
<li><p>✈️ <strong>Offline-friendly</strong>: perfecto para aprender incluso sin conexión.</p>
</li>
<li><p>🔒 <strong>Seguro</strong>: todo queda en tu máquina.</p>
</li>
<li><p>🧠 <strong>Aprendizaje profundo</strong>: rompes, arreglas, entendés.</p>
</li>
<li><p>⚡ <strong>Velocidad</strong>: sin esperar a que cargue nada en la nube.</p>
</li>
<li><p>🧪 <strong>Control total</strong>: podés experimentar sin miedo.</p>
</li>
</ul>
<hr />
<h2 id="heading-requisitos-para-armar-tu-laboratorio">🧰 Requisitos para armar tu laboratorio</h2>
<ul>
<li><p>💻 Laptop con mínimo 8 GB de RAM (16 GB recomendado).</p>
</li>
<li><p>📂 Al menos 20 GB de espacio libre.</p>
</li>
<li><p>🖥️ Windows, macOS o Linux.</p>
</li>
<li><p>👑 Acceso administrador.</p>
</li>
<li><p>🧬 Virtualización activada en BIOS.</p>
</li>
<li><p>🕒 Unas horas de tu tiempo.</p>
</li>
</ul>
<hr />
<h2 id="heading-paso-1-instalar-docker-tu-parque-de-contenedores">🧱 Paso 1: Instalar Docker, tu parque de contenedores</h2>
<h3 id="heading-para-windows">Para Windows</h3>
<ol>
<li><p>Activá la virtualización en la BIOS.</p>
</li>
<li><p>Descargá <a target="_blank" href="https://www.docker.com/products/docker-desktop">Docker Desktop</a>.</p>
</li>
<li><p>Durante la instalación, habilitá WSL2.</p>
</li>
<li><p>Reiniciá y abrí Docker Desktop. Esperá que la ballenita deje de moverse.</p>
</li>
</ol>
<h3 id="heading-para-mac">Para Mac</h3>
<ol>
<li><p>Descargá el <code>.dmg</code> desde el sitio de Docker.</p>
</li>
<li><p>Instalalo en “Aplicaciones”.</p>
</li>
<li><p>Abrilo y esperá que el ícono de la barra esté listo.</p>
</li>
</ol>
<h3 id="heading-para-linux-ubuntu">Para Linux (Ubuntu):</h3>
<p><a target="_blank" href="https://docs.docker.com/engine/install/">Como podemos instalarlo en Linux</a></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748016916055/06bf0a87-ab92-4ad5-b4be-f14dc5fa1c86.png" alt class="image--center mx-auto" /></p>
<pre><code class="lang-bash">sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository <span class="hljs-string">"deb [arch=amd64] https://download.docker.com/linux/ubuntu <span class="hljs-subst">$(lsb_release -cs)</span> stable"</span>
sudo apt update
sudo apt install docker-ce
sudo usermod -aG docker <span class="hljs-variable">$USER</span>
</code></pre>
<p>Salí y volvé a iniciar sesión para que los permisos se apliquen.</p>
<h3 id="heading-verifica-que-docker-funciona">Verificá que Docker funciona:</h3>
<pre><code class="lang-bash">docker run hello-world
</code></pre>
<p>Deberías ver un mensaje de “Hello from Docker!”</p>
<hr />
<h2 id="heading-paso-2-kubernetes-tu-orquesta-de-contenedores">🎻 Paso 2: Kubernetes – Tu orquesta de contenedores</h2>
<h3 id="heading-opcion-a-minikube-ideal-para-principiantes">Opción A: Minikube – Ideal para principiantes</h3>
<p>Minikube levanta un cluster Kubernetes de un solo nodo en tu compu.</p>
<h4 id="heading-instalacion-en-windows">Instalación en Windows</h4>
<ol>
<li><p>Descargá el instalador desde <a target="_blank" href="https://github.com/kubernetes/minikube/releases">Minikube Releases</a>.</p>
</li>
<li><p>Ejecutalo.</p>
</li>
<li><p>Abrí CMD como administrador y corré:</p>
</li>
</ol>
<pre><code class="lang-bash">minikube start --driver=docker
</code></pre>
<h4 id="heading-en-macos-con-homebrew">En macOS (con Homebrew)</h4>
<pre><code class="lang-bash">brew install minikube
minikube start --driver=docker
</code></pre>
<h4 id="heading-en-linux">En Linux:</h4>
<pre><code class="lang-bash">curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube-linux-amd64
sudo mv minikube-linux-amd64 /usr/<span class="hljs-built_in">local</span>/bin/minikube
minikube start --driver=docker
</code></pre>
<h4 id="heading-probalo">Probalo:</h4>
<pre><code class="lang-bash">minikube status
minikube dashboard
</code></pre>
<h3 id="heading-opcion-b-kind-kubernetes-mas-liviano-corre-dentro-de-docker">Opción B: Kind – Kubernetes más liviano, corre dentro de Docker</h3>
<p><a target="_blank" href="https://kind.sigs.k8s.io/docs/user/quick-start/#installing-with-a-package-manager">Sobre Kind</a></p>
<h4 id="heading-instalacion-universal">Instalación universal:</h4>
<pre><code class="lang-bash">curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.20.0/kind-$(uname)-amd64
chmod +x ./kind
sudo mv ./kind /usr/<span class="hljs-built_in">local</span>/bin/kind
</code></pre>
<h4 id="heading-crear-un-cluster">Crear un cluster:</h4>
<pre><code class="lang-bash">kind create cluster --name devops-lab
</code></pre>
<hr />
<h2 id="heading-paso-3-kubectl-tu-control-remoto-de-kubernetes">🕹️ Paso 3: kubectl – Tu control remoto de Kubernetes</h2>
<h3 id="heading-instalacionhttpskubernetesiodocstaskstools"><a target="_blank" href="https://kubernetes.io/docs/tasks/tools/">Instalación</a>:</h3>
<ul>
<li><p><strong>Windows</strong>: <code>choco install kubernetes-cli</code></p>
</li>
<li><p><strong>macOS</strong>: <code>brew install kubectl</code></p>
</li>
<li><p><strong>Linux</strong>:</p>
</li>
</ul>
<pre><code class="lang-bash">curl -LO <span class="hljs-string">"https://dl.k8s.io/release/<span class="hljs-subst">$(curl -L -s https://dl.k8s.io/release/stable.txt)</span>/bin/linux/amd64/kubectl"</span>
chmod +x kubectl
sudo mv kubectl /usr/<span class="hljs-built_in">local</span>/bin/kubectl
</code></pre>
<h4 id="heading-verifica-que-funcione">Verificá que funcione:</h4>
<pre><code class="lang-bash">kubectl get pods --all-namespaces
</code></pre>
<hr />
<h2 id="heading-paso-4-vagrant-gestiona-tus-maquinas-virtuales">🧳 Paso 4: Vagrant – Gestioná tus máquinas virtuales</h2>
<h3 id="heading-requisitos">Requisitos:</h3>
<ul>
<li><p><strong>VirtualBox</strong></p>
</li>
<li><p><strong>Vagrant</strong></p>
</li>
</ul>
<h4 id="heading-instalacion-en-cualquier-sistema">Instalación en cualquier sistema:</h4>
<ol>
<li><p><a target="_blank" href="https://www.virtualbox.org/wiki/Downloads">Descargá VirtualBox</a></p>
</li>
<li><p><a target="_blank" href="https://developer.hashicorp.com/vagrant/downloads">Descargá Vagrant</a></p>
</li>
<li><p>Verificá:</p>
</li>
</ol>
<pre><code class="lang-bash">vboxmanage --version
vagrant --version
</code></pre>
<hr />
<h3 id="heading-crear-tu-primera-vm">Crear tu primera VM:</h3>
<pre><code class="lang-bash">mkdir mi_lab &amp;&amp; <span class="hljs-built_in">cd</span> mi_lab
vagrant init ubuntu/focal64
vagrant up
vagrant ssh
</code></pre>
<p>Listo, ¡tenés Ubuntu corriendo!</p>
<p><a target="_blank" href="https://portal.cloud.hashicorp.com/vagrant/discover">Listado de Boxes</a></p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Si usas arquitectura MAC m1,m2,etc que trabaja con arm64, ya virtualbox lo soporta y además en los boxes revisa que tenga este soporte sino te dará error.</div>
</div>

<h3 id="heading-opcional-crear-un-vagrant-boxes-personalizada-a-partir-de-iso"><strong>(Opcional) Crear un Vagrant Boxes personalizada a partir de ISO</strong></h3>
<ol>
<li><strong>Descargar ISO de Ubuntu</strong> :</li>
</ol>
<ul>
<li><p>Vaya a <a target="_blank" href="https://ubuntu.com/download/desktop">https://ubuntu.com/download/desktop (o servidor)</a></p>
</li>
<li><p>Elija Ubuntu 24.04.2 LTS y guarde el archivo .iso localmente</p>
</li>
</ul>
<p><strong>2. Instalar Ubuntu en VirtualBox</strong> :</p>
<ul>
<li><p>Abrir VirtualBox → Nuevo → Nombre: ubuntu-devops → Tipo: Linux → Versión: Ubuntu (64 bits)</p>
</li>
<li><p>Asignar 2048 MB de RAM, 20 GB de disco duro (VDI)</p>
</li>
<li><p>En Almacenamiento, adjunte el .iso descargado en Unidad óptica</p>
</li>
<li><p>Inicie la máquina virtual y complete la instalación de Ubuntu (cree usuario, establezca contraseña)</p>
</li>
</ul>
<p><strong>3. Empaquetar la máquina virtual como Vagrant Boxes</strong> :</p>
<pre><code class="lang-bash">
 VBoxManage list vms   
<span class="hljs-comment"># Paquete</span>
 vagrant package -- base  <span class="hljs-string">"ubuntu-devops"</span> --output ubuntu2404.box   
<span class="hljs-comment"># Agregar a Vagrant  </span>
 vagrant box add ubuntu2404 ubuntu2404.box
</code></pre>
<p>Ahora tienes Ubuntu 2404 como equipo local, sin necesidad de Internet</p>
<hr />
<h2 id="heading-paso-5-ansible-automatizacion-sin-drama">🤖 Paso 5: Ansible – Automatización sin drama</h2>
<h3 id="heading-macos">macOS:</h3>
<pre><code class="lang-bash">brew install ansible
</code></pre>
<h3 id="heading-linux-ubuntu">Linux (Ubuntu):</h3>
<pre><code class="lang-bash">sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible
</code></pre>
<h3 id="heading-windows">Windows:</h3>
<p>Usá Ubuntu vía WSL. Luego instalás Ansible como en Linux.</p>
<h4 id="heading-probar-ansible">Probar Ansible:</h4>
<ol>
<li>Archivo <code>hosts</code>:</li>
</ol>
<pre><code class="lang-ini"><span class="hljs-section">[local]</span>
localhost <span class="hljs-attr">ansible_connection</span>=local
</code></pre>
<ol start="2">
<li><code>playbook.yml</code>:</li>
</ol>
<pre><code class="lang-yaml"><span class="hljs-meta">---</span>
<span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Prueba</span> <span class="hljs-string">de</span> <span class="hljs-string">Ansible</span>
  <span class="hljs-attr">hosts:</span> <span class="hljs-string">local</span>
  <span class="hljs-attr">tasks:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Mostrar</span> <span class="hljs-string">mensaje</span>
      <span class="hljs-attr">debug:</span>
        <span class="hljs-attr">msg:</span> <span class="hljs-string">"¡Ansible funciona!"</span>
</code></pre>
<ol start="3">
<li>Ejecutá:</li>
</ol>
<pre><code class="lang-bash">ansible-playbook -i hosts playbook.yml
</code></pre>
<hr />
<h2 id="heading-paso-6-terraform-tu-varita-magica-de-infraestructura">✨ Paso 6: Terraform – Tu varita mágica de Infraestructura</h2>
<h3 id="heading-instalacion">Instalación:</h3>
<ul>
<li><p><strong>Windows</strong>: <code>choco install terraform</code></p>
</li>
<li><p><strong>macOS</strong>: <code>brew install terraform</code></p>
</li>
<li><p><strong>Linux</strong>:</p>
</li>
</ul>
<pre><code class="lang-bash">wget https://releases.hashicorp.com/terraform/1.6.0/terraform_1.6.0_linux_amd64.zip
unzip terraform_1.6.0_linux_amd64.zip
sudo mv terraform /usr/<span class="hljs-built_in">local</span>/bin/
</code></pre>
<h3 id="heading-probar-terraform">Probar Terraform:</h3>
<p>Archivo <code>main.tf</code>:</p>
<pre><code class="lang-bash">resource <span class="hljs-string">"local_file"</span> <span class="hljs-string">"demo"</span> {
  content  = <span class="hljs-string">"¡Hola desde Terraform!"</span>
  filename = <span class="hljs-string">"<span class="hljs-variable">${path.module}</span>/saludo.txt"</span>
}
</code></pre>
<pre><code class="lang-bash">terraform init
terraform apply
</code></pre>
<p>Chequeá que exista el archivo <code>saludo.txt</code>.</p>
<hr />
<h1 id="heading-tu-primer-proyecto-devops-local-integrado">🧩 Tu Primer Proyecto DevOps Local Integrado</h1>
<p>Ya tenés Docker, Kubernetes, Vagrant, Ansible y Terraform instalados. Ahora, vamos a combinar todo en un proyecto real que simula una infraestructura DevOps básica. Esto te va a servir para aprender CI/CD, gestión de infraestructura y automatización de una manera <strong>100% práctica</strong>.</p>
<hr />
<h2 id="heading-objetivo-del-proyecto">🎯 Objetivo del Proyecto</h2>
<p>Crear una arquitectura de dos niveles (web + base de datos), usando:</p>
<ul>
<li><p><strong>Terraform</strong> para generar archivos de configuración.</p>
</li>
<li><p><strong>Vagrant</strong> para levantar las máquinas virtuales.</p>
</li>
<li><p><strong>Ansible</strong> para configurar los servidores.</p>
</li>
<li><p><strong>Docker</strong> para desplegar la app.</p>
</li>
<li><p><strong>Kubernetes</strong> (opcional para más adelante).</p>
</li>
</ul>
<hr />
<h2 id="heading-estructura-de-archivos">🗂️ Estructura de Archivos</h2>
<p>Crea una carpeta llamada <code>devops-lab-proyecto</code> con estos archivos:</p>
<pre><code class="lang-bash">devops-lab-proyecto/
├── Vagrantfile (generado por Terraform)
├── inventory (Ansible hosts)
├── playbook.yml (Ansible playbook)
└── main.tf (Terraform config)
</code></pre>
<hr />
<h2 id="heading-terraform-generacion-de-configuracion">🧙‍♂️ Terraform – Generación de configuración</h2>
<p>Archivo <a target="_blank" href="http://main.tf"><code>main.tf</code></a>:</p>
<pre><code class="lang-bash">resource <span class="hljs-string">"local_file"</span> <span class="hljs-string">"vagrant_file"</span> {
  content = &lt;&lt;-EOT
    Vagrant.configure(<span class="hljs-string">"2"</span>) <span class="hljs-keyword">do</span> |config|
      config.vm.box = <span class="hljs-string">"bento/ubuntu-22.04"</span>

      config.vm.define <span class="hljs-string">"web"</span> <span class="hljs-keyword">do</span> |web|
        web.vm.network <span class="hljs-string">"private_network"</span>, ip: <span class="hljs-string">"192.168.33.10"</span>
        web.vm.network <span class="hljs-string">"forwarded_port"</span>, guest: 80, host: 8080
      end

      config.vm.define <span class="hljs-string">"db"</span> <span class="hljs-keyword">do</span> |db|
        db.vm.network <span class="hljs-string">"private_network"</span>, ip: <span class="hljs-string">"192.168.33.11"</span>
      end
    end
  EOT
  filename = <span class="hljs-string">"<span class="hljs-variable">${path.module}</span>/Vagrantfile"</span>
}

resource <span class="hljs-string">"local_file"</span> <span class="hljs-string">"inventory_file"</span> {
  content = &lt;&lt;-EOT
    [webservers]
    192.168.33.10 ansible_user=vagrant ansible_ssh_private_key_file=.vagrant/machines/web/virtualbox/private_key

    [dbservers]
    192.168.33.11 ansible_user=vagrant ansible_ssh_private_key_file=.vagrant/machines/db/virtualbox/private_key
  EOT
  filename = <span class="hljs-string">"<span class="hljs-variable">${path.module}</span>/inventory"</span>
}

resource <span class="hljs-string">"local_file"</span> <span class="hljs-string">"playbook_file"</span> {
  content = &lt;&lt;-EOT
    ---
    - name: Configurar servidor web
      hosts: webservers
      become: yes
      tasks:
        - name: Instalar Docker
          apt:
            name: docker.io
            state: present
            update_cache: yes

        - name: Agregar usuario al grupo docker
          user:
            name: <span class="hljs-string">"{{ ansible_user }}"</span>
            groups: docker
            append: yes

        - name: Iniciar y habilitar servicio Docker
          systemd:
            name: docker
            state: started
            enabled: yes
            daemon_reload: yes

        - name: Desplegar contenedor Nginx
          docker_container:
            name: webapp
            image: nginx
            ports:
              - <span class="hljs-string">"80:80"</span>
            restart_policy: always

    - name: Configurar base de datos
      hosts: dbservers
      become: yes
      tasks:
        - name: Instalar MariaDB
          apt:
            name: mariadb-server
            state: present
            update_cache: yes

        - name: Iniciar servicio MariaDB
          service:
            name: mariadb
            state: started
            enabled: yes
  EOT
  filename = <span class="hljs-string">"<span class="hljs-variable">${path.module}</span>/playbook.yml"</span>
}
</code></pre>
<hr />
<h2 id="heading-ejecuta-los-pasos">⚙️ Ejecutá los pasos</h2>
<ol>
<li><strong>Inicializar Terraform y generar los archivos</strong></li>
</ol>
<pre><code class="lang-bash">terraform init
terraform apply
</code></pre>
<ol start="2">
<li><strong>Levantar las VMs con Vagrant</strong></li>
</ol>
<pre><code class="lang-bash">vagrant up
</code></pre>
<ol start="3">
<li><strong>Aplicar la configuración con Ansible</strong></li>
</ol>
<pre><code class="lang-bash">ansible-playbook -i inventory playbook.yml
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748022420890/555e5946-d394-4f48-bc40-b3506ccefdd2.png" alt class="image--center mx-auto" /></p>
<ol start="4">
<li><strong>Abrir la app web</strong></li>
</ol>
<p>Navegá a <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a> y deberías ver la página por defecto de Nginx.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748022178198/020b910e-6c4f-4a26-aade-8e2dff868822.png" alt class="image--center mx-auto" /></p>
<ol start="5">
<li>Tambien podes probar las maquinas virtuales con vagrant</li>
</ol>
<pre><code class="lang-bash">vagrant ssh web
vagrant ssh db
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748022843730/34cf70e5-2553-4a7b-be8f-b9e9f667ba15.png" alt class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1748022873833/22c8db87-0034-411d-b0c1-bef559668f60.png" alt class="image--center mx-auto" /></p>
<ol start="5">
<li><strong>Destruir cuando termines</strong></li>
</ol>
<pre><code class="lang-bash">vagrant destroy -f
terraform destroy
</code></pre>
<hr />
<h2 id="heading-bonus-no-quiero-usar-vagrant-alguna-opcion-pues-si">🧪 Bonus: No quiero usar Vagrant, alguna opción? pues si.</h2>
<p>El crack de <strong>James Spurin tiene un repo re-copado</strong> <a target="_blank" href="https://github.com/spurin/diveintoansible-lab">https://github.com/spurin/diveintoansible-lab</a></p>
<p>con <strong>docker-compose</strong> podes levantar algunas maquinas</p>
<p>Si te gusta lo que viste de Ansible te recomiendo este repo <a target="_blank" href="https://github.com/spurin/diveintoansible-lab">https://github.com/spurin/diveintoansible-lab</a></p>
<pre><code class="lang-bash">services:
  ubuntu-c:
    hostname: ubuntu-c
    container_name: ubuntu-c
    image: spurin/diveintoansible:ansible
    ports: 
     - <span class="hljs-variable">${UBUNTUC_PORT_SSHD}</span>:22
     - <span class="hljs-variable">${UBUNTUC_PORT_TTYD}</span>:7681
    privileged: <span class="hljs-literal">true</span>
    volumes:
     - <span class="hljs-variable">${CONFIG}</span>:/config
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/shared:/shared
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/ubuntu-c/ansible:/home/ansible
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/ubuntu-c/root:/root
    networks:
     - diveinto.io

  ubuntu1:
    hostname: ubuntu1
    container_name: ubuntu1
    image: spurin/diveintoansible:ubuntu
    ports: 
     - <span class="hljs-variable">${UBUNTU1_PORT_SSHD}</span>:22
     - <span class="hljs-variable">${UBUNTU1_PORT_TTYD}</span>:7681
    privileged: <span class="hljs-literal">true</span>
    volumes:
     - <span class="hljs-variable">${CONFIG}</span>:/config
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/shared:/shared
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/ubuntu1/ansible:/home/ansible
     - <span class="hljs-variable">${ANSIBLE_HOME}</span>/ubuntu1/root:/root
    networks:
     - diveinto.io

  ....
</code></pre>
<hr />
<h2 id="heading-bonus-y-si-lo-paso-a-kubernetes">🧪 Bonus: ¿Y si lo paso a Kubernetes?</h2>
<p>En una siguiente etapa podés:</p>
<ul>
<li><p>Empaquetar tu app como una imagen personalizada de Docker.</p>
</li>
<li><p>Crear archivos <code>deployment.yaml</code> y <code>service.yaml</code>.</p>
</li>
<li><p>Usar <code>kubectl apply -f</code> para desplegar en Minikube o Kind.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">…. se viene un post extra sobre esto.</div>
</div>

<hr />
<h2 id="heading-conclusion-tu-laboratorio-devops-esta-on-fire">🧭 Conclusión: ¡Tu laboratorio DevOps está ON FIRE!</h2>
<p>Lograste lo que muchos solo sueñan: un entorno completo para aprender DevOps desde tu compu, sin gastar ni un peso y entendiendo cada capa del proceso.</p>
<p>🌟 Ya tenés:</p>
<ul>
<li><p>Infraestructura local</p>
</li>
<li><p>Automatización</p>
</li>
<li><p>Contenedores</p>
</li>
<li><p>Entendimiento real del stack</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Ahora te toca a vos: <strong>rompé cosas, arreglalas, y volvé a intentar.</strong> Esa es la magia del aprendizaje DevOps.</div>
</div>]]></content:encoded></item><item><title><![CDATA[La etiqueta :latest en Docker: El amigo que te traiciona cuando menos lo esperas]]></title><description><![CDATA[En el mundo de Docker, la etiqueta :latest parece ser el héroe de la película. La forma más rápida y conveniente de obtener la última versión de una imagen, ¿cierto? Es fácil de usar, tentadora e intuitiva.
¿Quién no ha caído en la trampa? Es tan sed...]]></description><link>https://blog.295devops.com/la-etiqueta-latest-en-docker-el-amigo-que-te-traiciona-cuando-menos-lo-esperas</link><guid isPermaLink="true">https://blog.295devops.com/la-etiqueta-latest-en-docker-el-amigo-que-te-traiciona-cuando-menos-lo-esperas</guid><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Docker]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 17 May 2025 01:11:21 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747442716350/9cc051dd-77c7-448b-9441-469dd6414ddd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>En el mundo de Docker, la etiqueta <code>:latest</code> parece ser el héroe de la película. La forma más rápida y conveniente de obtener la última versión de una imagen, ¿cierto? Es fácil de usar, tentadora e intuitiva.</p>
<p><strong>¿Quién no ha caído en la trampa?</strong> Es tan seductora como un amigo que te dice: "¡No te preocupes! Yo te apoyo en todo", solo para luego dejarte en la estacada cuando más lo necesitas.</p>
<p>Aunque la etiqueta <code>:latest</code> puede parecer inofensiva y útil, en realidad <strong>es un desastre esperando a suceder</strong>. En este artículo, te contaré por qué deberías dejar de usarla y cómo evitar que se convierta en tu peor pesadilla.</p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747444020558/43fde15c-b241-490a-972a-fcd1bc69a252.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-que-es-la-etiqueta-latest-y-por-que-es-peligrosa"><strong>¿Qué es la etiqueta</strong> <code>:latest</code> y por qué es peligrosa?</h2>
<p>Primero, aclaramos el concepto. La etiqueta <code>:latest</code> <strong>no significa "última versión"</strong>. <strong>¡Sorpresa!</strong> En realidad, significa <strong>"la imagen que se etiquetó como</strong> <code>latest</code> más recientemente". Esto no es lo mismo que tener siempre el código más actualizado, y es aquí donde comienza el lío.</p>
<p>La etiqueta <code>:latest</code> puede ser etiquetada sobre una imagen con código de hace seis meses, o incluso un código con errores. <strong>¿La peor parte?</strong> Docker no tiene forma de saber si realmente es la versión más reciente de tu código. Solo se basa en la última imagen que recibió la etiqueta. Así que, si alguien se equivocó y subió una versión errónea, <strong>esa será la que se ejecute en producción</strong>.</p>
<hr />
<h2 id="heading-historias-de-no-son-on-fire-pero-con-mucho-thriller-a-lo-michael-jackson-con-la-etiqueta-latest">Historias de no son on-fire, pero con mucho thriller a lo Michael Jackson con la etiqueta :latest</h2>
<p>Para que entiendas mejor el peligro de usar <code>:latest</code>, déjame contarte unas historias de terror sobre cómo esta etiqueta ha arruinado despliegues, ha hecho desaparecer aplicaciones y ha dejado a equipos de desarrollo luchando por encontrar el problema.</p>
<h3 id="heading-1-kubernetes-se-vuelve-loco"><strong>1. Kubernetes se vuelve loco</strong></h3>
<p>Tu equipo de desarrollo despliega un <code>Helm chart</code> con la imagen <code>roxsross:latest</code>. Todo va bien en <strong>staging</strong>, pero cuando se lleva a <strong>producción</strong>, todo explota. Los pods se caen, y tu aplicación no funciona. ¿Por qué?</p>
<p>Porque alguien más subió una versión diferente de <code>roxsross:latest</code> desde su notebook/laptop. Aunque la etiqueta es la misma, el código es diferente. Kubernetes descarga la imagen incorrecta, y el despliegue se arruina. El resultado: <strong>la versión que funcionaba en staging ahora no sirve en producción.</strong></p>
<h3 id="heading-2-cicd-se-convierte-en-un-juego-de-azar"><strong>2. CI/CD se convierte en un juego de azar</strong></h3>
<p>Imagina que tienes una pipeline de <strong>GitHub Actions</strong> que construye <code>app-roxsops:latest</code>. Las pruebas pasan, todo parece perfecto. Pero horas después, otro pipeline se ejecuta, esperando que <code>:latest</code> sea lo mismo, pero un nuevo commit ha sobrescrito la imagen. Las pruebas fallan y el equipo comienza a buscar errores en el código, pero el problema es mucho más simple: <strong>la imagen</strong> <code>:latest</code> estaba equivocada.</p>
<h3 id="heading-3-terraform-te-apunala-por-la-espalda"><strong>3. Terraform te apuñala por la espalda</strong></h3>
<p>Tienes un entorno de producción en <strong>AWS ECS</strong> que utiliza la imagen <code>webroxsapp:latest</code>. Todo parece funcionar bien, hasta que un redeploy se ejecuta y ECS toma una nueva versión de <code>:latest</code>. Pero no hay cambios en el código ni en la infraestructura; simplemente es una versión equivocada de la imagen.</p>
<p>Terraform dice que todo está bien, pero la aplicación responde con un error 404. Nadie sabe por qué. <strong>La etiqueta</strong> <code>:latest</code> ha causado el caos.</p>
<h3 id="heading-4-rollbacks-imposibles"><strong>4. Rollbacks imposibles</strong></h3>
<p>El despliegue con <code>:latest</code> falla. Intentas hacer rollback, pero ahora <code>:latest</code> está apuntando a la versión rota. La versión anterior ya no está disponible. El proceso de rollback se convierte en un juego de adivinanza, buscando imágenes antiguas en los registros. El tiempo de inactividad se extiende y <strong>nadie sabe qué hacer</strong>.</p>
<hr />
<h2 id="heading-como-funciona-realmente-la-etiqueta-latest-en-docker"><strong>¿Cómo funciona realmente la etiqueta :latest en Docker?</strong></h2>
<p>Es crucial entender cómo funciona Docker para ver por qué <code>:latest</code> es tan peligrosa. Aquí te muestro cómo <strong>Docker maneja las etiquetas</strong>:</p>
<h4 id="heading-construccion-y-etiquetado"><strong>Construcción y Etiquetado</strong></h4>
<p>Cuando ejecutas un <code>docker build</code>, si no especificas una etiqueta, Docker por defecto le asignará la etiqueta <code>:latest</code> a la imagen.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Construcción con versión explícita</span>
docker build -t devopsconrox:0.1 .

<span class="hljs-comment"># Construcción sin etiqueta</span>
docker build -t devopsconrox .
</code></pre>
<p>¿Qué sucede? La segunda construcción recibe la etiqueta <code>devopsconrox:latest</code>. Si luego construyes una nueva versión:</p>
<pre><code class="lang-bash">docker build -t devopsconrox:0.2 .
</code></pre>
<p><mark>¿Crees que :latest se actualizó? </mark> <strong><mark>¡No!</mark></strong> <mark> Sigue apuntando a la construcción anterior. Docker no sabe cuál es la imagen más reciente si no le especificas una etiqueta clara. </mark> <strong><mark>Es un caos total.</mark></strong></p>
<hr />
<h2 id="heading-como-evitar-los-problemas-con-latest"><strong>¿Cómo evitar los problemas con</strong> <code>:latest</code>?</h2>
<p>Ahora que sabes lo peligrosa que puede ser la etiqueta <code>:latest</code>, te voy a contar cómo puedes evitar que esta trampa te cause problemas en tu equipo.</p>
<h3 id="heading-1-usa-versiones-semanticas-o-shas-de-commits"><strong>1. Usa versiones semánticas o SHAs de commits</strong></h3>
<p>La clave es etiquetar las imágenes de manera precisa. Usa <strong>versiones semánticas</strong> o el <strong>SHA de los commits</strong>. De esta manera, siempre sabrás qué versión estás utilizando, y no tendrás que depender de la ambigua etiqueta <code>:latest</code>.</p>
<pre><code class="lang-bash">docker build -t devopsconrox:1.3.7 -t devopsconrox:commit-b6fa2e1 .
docker push devopsconrox:1.3.7
docker push devopsconrox:commit-b6fa2e1
</code></pre>
<h3 id="heading-2-usa-digests-para-un-control-aun-mas-preciso"><strong>2. Usa Digests para un control aún más preciso</strong></h3>
<p>Los <strong>digests</strong> son inmutables, lo que significa que la imagen no podrá ser sobrescrita accidentalmente. Usar digests es una forma de asegurarte de que el despliegue sea siempre el correcto.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Despliegue en Kubernetes con Digest</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">containers:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">devopsconroxapp</span>
      <span class="hljs-attr">image:</span> <span class="hljs-string">devopsconroxapp@sha256:abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890</span>
</code></pre>
<h3 id="heading-3-automatiza-el-etiquetado-con-tu-pipeline-cicd"><strong>3. Automatiza el etiquetado con tu pipeline CI/CD</strong></h3>
<p>Para evitar errores manuales, automatiza el etiquetado dentro de tu pipeline de CI/CD. De esta forma, nunca tendrás que preocuparte de que alguien etiquete mal la imagen.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">and</span> <span class="hljs-string">Deploy</span>
<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [ <span class="hljs-string">main</span> ]
<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>
    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Build</span> <span class="hljs-string">and</span> <span class="hljs-string">tag</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">|
          docker build -t devopsconrox:${{ github.sha }} -t devopsconrox:prod .
          docker push devopsconrox:${{ github.sha }}
          docker push devopsconrox:prod</span>
</code></pre>
<h3 id="heading-4-prohibe-latest-en-tu-pipeline-y-en-tus-registros"><strong>4. Prohíbe :latest en tu pipeline y en tus registros</strong></h3>
<p>Usa herramientas como <a target="_blank" href="https://github.com/open-policy-agent/conftest"><strong>conftest</strong></a> o <a target="_blank" href="https://github.com/stackrox/kube-linter"><strong>kube-linter</strong></a> para detectar el uso de <code>:latest</code>. Además, puedes configurar reglas en tu registro (por ejemplo, AWS ECR) para evitar que se suban imágenes con esta etiqueta.</p>
<h4 id="heading-1-escanea-tu-codigo-con-conftest-o-kube-linter"><strong>1. Escanea tu código con conftest o kube-linter</strong></h4>
<p>Puedes usar herramientas como <a target="_blank" href="https://github.com/open-policy-agent/conftest"><strong>conftest</strong></a> o <a target="_blank" href="https://github.com/stackrox/kube-linter"><strong>kube-linter</strong></a> para escanear tu código y detectar el uso de <code>:latest</code>. Estas herramientas te permiten asegurarte de que los manifiestos y las configuraciones de Kubernetes no incluyan esta etiqueta problemática.</p>
<p>Aquí tienes un ejemplo de cómo configurar una <strong>regla de Open Policy Agent (OPA)</strong> para bloquear <code>:latest</code> en los despliegues de Kubernetes:</p>
<pre><code>package kubernetes
deny[msg] {
  input.kind == <span class="hljs-string">"Deployment"</span>
  <span class="hljs-attr">container</span> := input.spec.template.spec.containers[_]
  contains(container.image, <span class="hljs-string">":latest"</span>)
  <span class="hljs-attr">msg</span> := <span class="hljs-string">"No :latest allowed!"</span>
}
</code></pre><p><mark>Con esta regla, cualquier intento de despliegue con una imagen que contenga </mark> <code>:latest</code> <mark> será rechazado, garantizando que tus aplicaciones solo se desplieguen con versiones explícitas y controladas.</mark></p>
<h4 id="heading-2-agrega-un-paso-en-tu-pipeline-para-rechazar-latest"><strong>2. Agrega un paso en tu pipeline para rechazar</strong> <code>:latest</code></h4>
<p>Una de las formas más efectivas de evitar que <code>:latest</code> se cuele es agregar una <strong>verificación en tu pipeline de CI/CD</strong>. Con un simple script, puedes detectar la presencia de la etiqueta y fallar el pipeline si aparece.</p>
<p>Este es un ejemplo de un paso en tu pipeline que detecta y rechaza <code>:latest</code> en tus manifiestos y Dockerfiles:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">if</span> grep -r <span class="hljs-string">":latest"</span> manifests/ Dockerfile; <span class="hljs-keyword">then</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"Error: :latest detected!"</span>
  <span class="hljs-built_in">exit</span> 1
<span class="hljs-keyword">fi</span>
</code></pre>
<p>Este comando busca la etiqueta <code>:latest</code> en todos los archivos relevantes de tu proyecto. Si la encuentra, el pipeline se detendrá inmediatamente, evitando que un despliegue potencialmente problemático llegue a producción.</p>
<p>Aquí tienes un ejemplo de cómo configurar una regla en ECR para rechazar la etiqueta <code>:latest</code>:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"rules"</span>: [
    {
      <span class="hljs-attr">"rulePriority"</span>: <span class="hljs-number">1</span>,
      <span class="hljs-attr">"description"</span>: <span class="hljs-string">"No :latest allowed"</span>,
      <span class="hljs-attr">"selection"</span>: {
        <span class="hljs-attr">"tagStatus"</span>: <span class="hljs-string">"tagged"</span>,
        <span class="hljs-attr">"tagPrefixList"</span>: [<span class="hljs-string">"latest"</span>],
        <span class="hljs-attr">"countType"</span>: <span class="hljs-string">"imageCountMoreThan"</span>,
        <span class="hljs-attr">"countNumber"</span>: <span class="hljs-number">0</span>
      },
      <span class="hljs-attr">"action"</span>: {
        <span class="hljs-attr">"type"</span>: <span class="hljs-string">"expire"</span>
      }
    }
  ]
}
</code></pre>
<hr />
<h2 id="heading-buenas-practicas-en-docker-despliegues-eficientes-y-sin-sorpresas"><strong>Buenas prácticas en Docker: Despliegues eficientes y sin sorpresas</strong></h2>
<p>Además de evitar el uso de la peligrosa etiqueta <code>:latest</code>, es esencial seguir <strong>buenas prácticas en Docker</strong> para asegurarte de que tus contenedores sean eficientes, seguros y fáciles de mantener. Docker es una herramienta poderosa, pero su verdadero potencial se alcanza cuando aplicas las mejores prácticas. Aquí te comparto algunas de las <strong>principales recomendaciones</strong> para construir y gestionar tus imágenes de manera efectiva:</p>
<ul>
<li><p><strong>Usa imágenes base pequeñas y optimizadas:</strong> Como las imágenes <code>alpine</code> para reducir el tamaño de las imágenes.</p>
</li>
<li><p><strong>Minimiza el número de capas en tu Dockerfile</strong> combinando las instrucciones en bloques.</p>
</li>
<li><p><strong>Ordena bien las instrucciones</strong> para aprovechar el cache de Docker.</p>
</li>
<li><p><strong>Usa multi-stage builds</strong> para optimizar el tamaño de la imagen.</p>
</li>
<li><p><strong>Elimina archivos innecesarios</strong> en cada etapa de construcción.</p>
</li>
<li><p><strong>Usa</strong> <code>.dockerignore</code> para excluir archivos que no necesitas en el contenedor final.</p>
</li>
</ul>
<p>Para más detalles, puedes revisar la <a target="_blank" href="https://docs.docker.com/build/building/best-practices/">documentación oficial de buenas prácticas d</a><a target="_blank" href="https://docs.docker.com/build/building/best-practices/">e Docker.</a></p>
<hr />
<h2 id="heading-conclusion-evita-el-thriller-de-latest-y-asegura-tus-despliegues"><strong>Conclusión: ¡Evita el thriller de</strong> <code>:latest</code> y asegura tus despliegues!</h2>
<p>La etiqueta <code>:latest</code> en Docker es como un thriller lleno de suspenso, pero sin la emoción que deseas. Puede parecer una solución rápida y fácil, pero lo único que trae son problemas inesperados, caos en producción y confusión en tu pipeline. Como en cualquier buen thriller, todo parece ir bien hasta que, de repente, <strong>todo se viene abajo</strong>.</p>
<p>Para evitar que tu historia de despliegue se convierta en una pesadilla, es hora de decirle adiós a <code>:latest</code>. <strong>Usa versiones semánticas</strong>, <strong>digests</strong> y <strong>automatiza el etiquetado</strong> para tener un control total sobre lo que está ocurriendo en tus entornos de desarrollo y producción. Así, en lugar de enfrentarte a un thriller lleno de sorpresas, podrás disfrutar de un despliegue confiable y predecible, donde todo sigue el guion.</p>
<p>Recuerda, no pongas en riesgo tus despliegues por una etiqueta que suena fácil, pero esconde un montón de problemas. <strong>La etiqueta</strong> <code>:latest</code> es la verdadera estrella del drama, ¡y es hora de que dejes que el thriller termine y comiences una nueva era de despliegues seguros y controlados!</p>
<hr />
<h2 id="heading-bonus-y-esto-no-es-todo"><strong>Bonus: ¡Y esto no es todo!</strong></h2>
<p>Si pensabas que ya habíamos cubierto todo lo importante, te tengo una <strong>sorpresa</strong>. Este artículo solo ha sido el principio de una serie de posts sobre Docker, DevOps y buenas prácticas que te ayudarán a <strong>sobrevivir al fuego.</strong></p>
<p>En la próxima entrada, nos vamos a <strong>sumergir en un tema aún más ON FIRE</strong>: <strong>las historias de terror en contenedores multiarquitectura</strong>. ¡Prepárate! Este tema es más intenso que un buen thriller de suspenso. Si pensabas que el uso de <code>:latest</code> era un riesgo, espera a ver lo que puede pasar cuando ejecutas contenedores en diferentes arquitecturas. Vamos a hablar de las sorpresas, los problemas y las soluciones que te ayudarán a <strong>navegar sin miedo</strong> por el mundo de las <strong>multiarquitecturas</strong>.</p>
<p>Así que quédate atento, porque <strong>¡esto se pone aún más emocionante!</strong> 🔥🔥</p>
<hr />
<h2 id="heading-no-dejes-que-el-miedo-a-lo-desconocido-te-detenga"><strong>¡No dejes que el miedo a lo desconocido te detenga!</strong></h2>
<p>En DevOps y el desarrollo, <strong>la innovación y la mejora continua</strong> son el camino hacia el éxito. No temas dar el siguiente paso hacia un futuro más seguro y confiable en tus despliegues. ¡Lo único constante es el cambio y las mejoras, y con el conocimiento adecuado, puedes transformar cualquier desafío en una oportunidad!</p>
<p><strong>¡Vamos por más!</strong> 💪 <strong>Nunca dejes de aprender y compartir, porque en la comunidad, todos crecemos juntos.</strong> 🚀</p>
<p>Sígueme en mis redes para más consejos, trucos y contenido exclusivo sobre DevOps, Docker y mucho más:</p>
<ul>
<li><p><strong>Twitter:</strong> <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>LinkedIn:</strong> <a target="_blank" href="https://www.linkedin.com/in/roxsross">Rossana Suarez</a></p>
</li>
<li><p><strong>Instagram:</strong> <a target="_blank" href="https://www.instagram.com/roxsross">@roxsdevops</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[20 Ideas DevOps para Principiantes: Construye tus fundamentos]]></title><description><![CDATA[Si estás comenzando en DevOps, la mejor manera de adquirir habilidades es mediante proyectos prácticos. Los proyectos no solo te permiten aprender, sino también experimentar con herramientas y conceptos clave que se utilizan en la vida real. ¡Y lo me...]]></description><link>https://blog.295devops.com/20-ideas-devops-para-principiantes-construye-tus-fundamentos</link><guid isPermaLink="true">https://blog.295devops.com/20-ideas-devops-para-principiantes-construye-tus-fundamentos</guid><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 17 May 2025 00:22:28 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1747439831449/62e7f55a-306b-4a5b-92f0-a237b2c70a92.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Si estás comenzando en DevOps, la mejor manera de adquirir habilidades es mediante proyectos prácticos. Los proyectos no solo te permiten aprender, sino también experimentar con herramientas y conceptos clave que se utilizan en la vida real. ¡Y lo mejor es que puedes ejecutar estos proyectos localmente, en plataformas como <a target="_blank" href="https://killercoda.com/">Killercoda</a> o <a target="_blank" href="http://labs.iximiuz.com">labs.iximiuz.com</a>! Estas plataformas te brindan entornos ideales para practicar sin necesidad de configurar todo desde cero en tu máquina local.</p>
<p><mark>A continuación, te traigo </mark> <strong><mark>20 ideas DevOps para principiantes</mark></strong> <mark> que te ayudarán a construir una base sólida y a familiarizarte con las herramientas y conceptos fundamentales. ¡Vamos al challenge!</mark></p>
<p><img src="https://sdmntpreastus.oaiusercontent.com/files/00000000-85b0-61f9-8e12-5a20e3736687/raw?se=2025-05-17T00%3A05%3A00Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=00000000-0000-0000-0000-000000000000&amp;skoid=02b7f7b5-29f8-416a-aeb6-99464748559d&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-05-16T20%3A56%3A27Z&amp;ske=2025-05-17T20%3A56%3A27Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=wItLRqOB5phb6mD8O/f0xk%2BIOTAQB9kJ74mPlaIXIrM%3D" alt /></p>
<h3 id="heading-1-automatizacion-de-tareas-basicas-con-scripts-bash">1. <strong>Automatización de Tareas Básicas con Scripts Bash</strong></h3>
<p>Aprende a usar Bash para automatizar tareas repetitivas de administración del sistema, como eliminar ar<a target="_blank" href="https://labs.iximiuz.com">chivos antiguos</a> o crear copias de seguridad. Este es un primer paso para familiarizarte con la automatización de procesos que se repiten en el entorno de desarrollo y administración de sistemas.</p>
<h3 id="heading-enfoque">Enfoque:</h3>
<ul>
<li><p>Crea un script <code>.sh</code> que elimine logs antiguos de una carpeta específica.</p>
</li>
<li><p>Usa comandos como <code>ls</code>, <code>rm</code>, <code>cp</code> y <code>tar</code> para manejar archivos y directorios.</p>
</li>
<li><p>Añade condicionales (<code>if/else</code>) y bucles (<code>for</code>) para darle flexibilidad al script, de manera que puedas personalizar el comportamiento según las necesidades.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a>: En Killercoda puedes realizar una gran variedad de prácticas que te permitirán afianzar lo aprendido con Bash, como la creación de scripts más complejos y la ejecución en entornos controlados.</p>
</li>
</ul>
<h3 id="heading-objetivo">Objetivo:</h3>
<p>Familiarizarte con Bash, aprender a automatizar tareas comunes y comprender la lógica básica de programación en un entorno Unix/Linux.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747440458876/901cd949-e91a-4fc3-bf2b-9fbf331a0a56.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-2-pipeline-de-cicd-basico-con-github-actions">2. <strong>Pipeline de CI/CD Básico con GitHub Actions</strong></h3>
<p>Configura un pipeline sencillo que ejecute pruebas automáticas cada vez que empujas código al repositorio. Ideal para entender cómo funciona la integración continua y cómo automatizar los procesos de construcción y prueba en tus proyectos.</p>
<h3 id="heading-enfoque-1">Enfoque:</h3>
<ul>
<li><p>Crea un repositorio en GitHub y sube un pequeño proyecto (por ejemplo, una app en Node.js o Python).</p>
</li>
<li><p>Configura un archivo de flujo de trabajo en <code>.github/workflows/main.yml</code> para que se ejecute cada vez que se haga un <code>push</code> al branch principal.</p>
</li>
<li><p>Agrega pasos para hacer el checkout del código, instalar dependencias y correr pruebas automáticas.</p>
</li>
<li><p><a target="_blank" href="https://docs.github.com/es/actions"><strong>Entrenamiento en CI/CD en GitHub</strong></a>: Si quieres comenzar a entrenarte con CI/CD en GitHub, cuentas con los pasos disponibles directamente en la documentación oficial de GitHub Actions. Aquí podrás entender cómo configurar y personalizar tus pipelines, lo que te permitirá automatizar tareas de forma eficiente y segura.</p>
</li>
</ul>
<h3 id="heading-objetivo-1">Objetivo:</h3>
<p>Familiarizarte con GitHub Actions y aprender los fundamentos de la integración continua mediante la automatización de pruebas en un flujo de trabajo de CI/CD.s automáticas.</p>
<p><img src="https://miro.medium.com/v2/resize:fit:575/1*7Eegp545ceif0cAsWmAk7w.png" alt="Deploying to a Server with GitHub Actions using ssh | by Balazs Kocsis |  Medium" /></p>
<h3 id="heading-3-despliegue-de-un-sitio-estatico-con-docker">3. <strong>Despliegue de un Sitio Estático con Docker</strong></h3>
<p>Aprende los principios de contenerización utilizando Docker para ejecutar un sitio web estático dentro de un contenedor. Este proyecto te permitirá familiarizarte con la creación de contenedores Docker para aplicaciones web simples.</p>
<h3 id="heading-enfoque-2">Enfoque:</h3>
<ul>
<li><p>Crea una página web básica con <a target="_blank" href="https://startbootstrap.com/themes">HTML y CSS.</a></p>
</li>
<li><p>Escribe un <code>Dockerfile</code> usando una imagen base como <code>nginx:alpine</code> para servir tu sitio web.</p>
</li>
<li><p>Construye la imagen con <code>docker build</code> y corre el contenedor con <code>docker run</code> para poner en marcha tu sitio estático.</p>
</li>
<li><p><a target="_blank" href="https://docs.docker.com/get-started/workshop/"><strong>Refuerza tus conocimientos de Docker</strong></a>: Puedes usar esta web, que ofrece varios temas sobre sitios estáticos, y si deseas profundizar más en Docker, este tutorial sobre Docker es increíble para aprender más sobre la contenerización y cómo utilizar Docker en diferentes escenarios.</p>
</li>
</ul>
<h3 id="heading-objetivo-2">Objetivo:</h3>
<p>Familiarizarte con la creación y ejecución de contenedores Docker para sitios estáticos, lo que te permitirá aplicar principios de contenerización en proyectos reales.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Podrías usar esta web donde hay varios <a target="_self" href="https://startbootstrap.com/themes">temas</a> de sitios estáticos y a los contenedores.</div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747440445129/73bc0216-0f13-46a0-b9c1-6184f874ceea.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-4-monitoreo-basico-del-sistema-en-linux">4. <strong>Monitoreo Básico del Sistema en Linux</strong></h3>
<p>Familiarízate con los comandos básicos de Linux para monitorear el rendimiento de tu sistema, como CPU, memoria y espacio en disco.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Utiliza comandos como <code>top</code>, <code>htop</code>, <code>df -h</code> y <code>free -h</code> para monitorear los recursos del sistema.</p>
</li>
<li><p>Puedes escribir un script que verifique la carga del sistema y avise si hay problemas de rendimiento.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a></p>
</li>
</ul>
<h3 id="heading-5-automatizacion-de-instalacion-de-paquetes-en-linux">5. <strong>Automatización de Instalación de Paquetes en Linux</strong></h3>
<p>Crea un script para automatizar la instalación de software en un servidor Linux. Esto te ayudará a entender cómo mantener tus servidores consistentes.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Escribe un script en Bash que instale herramientas esenciales como <code>git</code>, <code>docker</code>, <code>nodejs</code>.</p>
</li>
<li><p>Usa <code>apt</code> o <code>yum</code> según el sistema operativo que estés utilizando.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a></p>
</li>
</ul>
<h3 id="heading-6-control-de-versiones-con-git">6. <strong>Control de Versiones con Git</strong></h3>
<p>Aprende los conceptos básicos de Git, la herramienta más usada para el control de versiones en proyectos de software.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Inicializa un repositorio con <code>git init</code>.</p>
</li>
<li><p>Realiza un commit, crea ramas y haz merges de manera sencilla.</p>
</li>
<li><p>Aprende a resolver conflictos de fusión.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a></p>
</li>
</ul>
<h3 id="heading-7-provisionamiento-de-servidores-con-ansible">7. <strong>Provisionamiento de Servidores con Ansible</strong></h3>
<p>Ansible es una herramienta de automatización que te permite configurar servidores y aplicaciones de manera eficiente. Ideal para principiantes en IaC (Infraestructura como Código).</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Instala Ansible en tu máquina y escribe un playbook básico para instalar un servidor web (como <code>nginx</code>).</p>
</li>
<li><p>Ejecuta el playbook con <code>ansible-playbook</code> y configura tu servidor automáticamente.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a></p>
</li>
</ul>
<h3 id="heading-8-rotacion-automatica-de-logs">8. <strong>Rotación Automática de Logs</strong></h3>
<p>Aprende a gestionar archivos de logs para evitar que llenen el disco con información innecesaria.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Usa <code>logrotate</code> para gestionar logs y asegurarte de que los archivos no crezcan demasiado.</p>
</li>
<li><p>Configura el archivo de configuración de <code>logrotate</code> para realizar la rotación y compresión de logs automáticamente.</p>
</li>
<li><p><strong>Practica con</strong> <a target="_blank" href="https://killercoda.com/"><strong>Killercoda</strong></a></p>
</li>
</ul>
<h3 id="heading-9-introduccion-a-terraform-para-iac">9. <strong>Introducción a Terraform para IaC</strong></h3>
<p>Terraform es una herramienta de IaC que te permite gestionar infraestructuras en la nube. Comienza con algo simple como crear una máquina virtual en AWS.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Instala Terraform y configura tu proveedor (por ejemplo, AWS).</p>
</li>
<li><p>Crea un archivo <a target="_blank" href="http://main.tf"><code>main.tf</code></a> que defina una instancia de EC2 en AWS.</p>
</li>
<li><p>Usa <code>terraform init</code>, <code>terraform plan</code>, y <code>terraform apply</code> para provisionar la infraestructura.</p>
</li>
</ul>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Puedes usar <a target="_self" href="https://docs.localstack.cloud/overview/">Localstack</a> para practicas =)</div>
</div>

<h3 id="heading-10-monitoreo-de-uptime-de-un-sitio-web-con-cron-jobs">10. <strong>Monitoreo de Uptime de un Sitio Web con Cron Jobs</strong></h3>
<p>Configura un cron job para verificar la disponibilidad de un sitio web y enviarte un aviso si está caído.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Escribe un script que use <code>curl</code> para verificar el código de estado HTTP de un sitio.</p>
</li>
<li><p>Si el sitio está caído, el script enviará un correo electrónico o una alerta por Slack.</p>
</li>
<li><p>Programa el script para que se ejecute cada 5 minutos usando <code>cron</code>.</p>
</li>
</ul>
<h3 id="heading-11-pipeline-de-cicd-con-jenkins-y-docker">11. <strong>Pipeline de CI/CD con Jenkins y Docker</strong></h3>
<p>Configura un pipeline básico de CI/CD en Jenkins y usa Docker para crear un entorno de construcción consistente.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Instala Jenkins y configúralo para usar Docker.</p>
</li>
<li><p>Crea un <code>Jenkinsfile</code> para definir las etapas del pipeline: checkout del código, construcción de la imagen Docker, pruebas y despliegue.</p>
</li>
</ul>
<h3 id="heading-12-despliegue-de-una-aplicacion-web-en-aws-usando-terraform">12. <strong>Despliegue de una Aplicación Web en AWS usando Terraform</strong></h3>
<p>Lleva el concepto de IaC un paso más allá creando una infraestructura en AWS para alojar una aplicación web.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Usa Terraform para crear recursos en AWS, como una instancia EC2 y un grupo de seguridad.</p>
</li>
<li><p>Implementa una aplicación simple en la instancia y hazla accesible a través de un balanceador de carga.</p>
</li>
</ul>
<h3 id="heading-13-respaldo-automatico-de-bases-de-datos-con-shell-scripts">13. <strong>Respaldo Automático de Bases de Datos con Shell Scripts</strong></h3>
<p>Aprende a crear copias de seguridad automatizadas de una base de datos y a almacenarlas en la nube.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Escribe un script que use <code>mysqldump</code> o <code>pg_dump</code> para crear una copia de seguridad de la base de datos.</p>
</li>
<li><p>Comprime la copia de seguridad y súbela a un servicio de almacenamiento en la nube como AWS S3.</p>
</li>
</ul>
<h3 id="heading-14-configuracion-basica-de-kubernetes-con-minikube">14. <strong>Configuración Básica de Kubernetes con Minikube</strong></h3>
<p>Configura un clúster Kubernetes localmente con Minikube y aprende los conceptos básicos como Pods y Servicios.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Instala Minikube y <code>kubectl</code> en tu máquina.</p>
</li>
<li><p>Inicia un clúster local con <code>minikube start</code> y despliega una aplicación simple en Kubernetes.</p>
</li>
</ul>
<h3 id="heading-15-gestion-centralizada-de-logs-con-elk-stack">15. <strong>Gestión Centralizada de Logs con ELK Stack</strong></h3>
<p>Aprende a recolectar y visualizar logs usando Elasticsearch, Logstash y Kibana (ELK).</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Despliega Elasticsearch y Kibana utilizando Docker.</p>
</li>
<li><p>Usa Logstash para procesar logs de un servidor o aplicación y visualízalos en Kibana.</p>
</li>
</ul>
<h3 id="heading-16-cicd-para-microservicios-con-docker-y-kubernetes">16. <strong>CI/CD para Microservicios con Docker y Kubernetes</strong></h3>
<p>Aprende cómo gestionar una arquitectura de microservicios usando Docker y Kubernetes.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Configura un repositorio para múltiples microservicios.</p>
</li>
<li><p>Crea un pipeline de CI/CD que construya imágenes Docker, ejecute pruebas y las despliegue en Kubernetes.</p>
</li>
</ul>
<h3 id="heading-17-gestion-de-configuracion-de-servidores-con-puppet">17. <strong>Gestión de Configuración de Servidores con Puppet</strong></h3>
<p>Puppet es una herramienta poderosa para gestionar la configuración de servidores. Ideal para principiantes que quieren aprender IaC.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li>Instala Puppet y configura un servidor web con <code>nginx</code> usando un manifiesto de Puppet.</li>
</ul>
<h3 id="heading-18-revisiones-automaticas-de-calidad-de-codigo-con-sonarqube">18. <strong>Revisiones Automáticas de Calidad de Código con SonarQube</strong></h3>
<p>Integra SonarQube en tu pipeline para realizar análisis estáticos de código y asegurar que se cumplan los estándares de calidad.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Configura un servidor de SonarQube y conéctalo a tu pipeline de CI/CD.</p>
</li>
<li><p>Ejecuta análisis de calidad de código cada vez que se haga un commit en el repositorio.</p>
</li>
</ul>
<h3 id="heading-19-implementacion-de-un-servidor-de-nginx-con-docker-y-ansible">19. <strong>Implementación de un Servidor de Nginx con Docker y Ansible</strong></h3>
<p>Aprende a automatizar la implementación de un servidor Nginx usando Docker y Ansible para la configuración de servidores de forma eficiente.</p>
<h3 id="heading-enfoque-3">Enfoque:</h3>
<ul>
<li><p>Crea un archivo <code>Dockerfile</code> para desplegar Nginx en un contenedor Docker.</p>
</li>
<li><p>Utiliza Ansible para automatizar la instalación de Docker y la configuración del contenedor Nginx en un servidor remoto.</p>
</li>
<li><p>Configura un playbook de Ansible para asegurarte de que el servidor tenga el contenedor Docker con Nginx funcionando automáticamente.</p>
</li>
</ul>
<h3 id="heading-objetivo-3">Objetivo:</h3>
<p>Familiarizarte con la integración de Docker y Ansible para la gestión y configuración de servidores.</p>
<h3 id="heading-20-automatizacion-del-proceso-de-certificados-con-lets-encrypt">20. <strong>Automatización del Proceso de Certificados con Let's Encrypt</strong></h3>
<p>Automatiza la obtención y renovación de certificados SSL/TLS usando Let's Encrypt.</p>
<p><strong>Enfoque:</strong></p>
<ul>
<li><p>Usa <code>certbot</code> para obtener y renovar certificados SSL de manera automática.</p>
</li>
<li><p>Configura un cron job para renovar los certificados periódicamente.</p>
</li>
</ul>
<hr />
<p>Estos <strong>fundamentos de DevOps</strong> son esenciales para cualquiera que quiera adentrarse en el mundo de la automatización, integración continua y gestión de infraestructuras. A medida que avanzas en estos proyectos, estarás construyendo no solo una base técnica sólida, sino también una mentalidad ágil y eficiente que te permitirá enfrentar desafíos reales en el desarrollo y despliegue de aplicaciones. Además, aprender y practicar con herramientas como <strong>Docker</strong>, <strong>GitHub Actions</strong>, <strong>Ansible</strong> y <strong>Terraform</strong> te abrirá puertas a muchas oportunidades en el mundo de la tecnología.</p>
<p><mark>Recuerda que el camino en DevOps es un proceso continuo de aprendizaje y mejora. No tengas miedo de experimentar, probar nuevas herramientas y enfrentarte a desafíos. Cada pequeño paso te acerca más a ser un profesional completo en este campo.</mark></p>
<p>¡Estamos todos juntos en esta ola!</p>
<hr />
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747003017741/2aab81cb-60b3-489c-9c0f-546c75003455.png?auto=compress,format&amp;format=webp" alt class="image--center mx-auto" /></p>
<p>Si tienes alguna duda o quieres seguir aprendiendo más sobre DevOps, puedes encontrarme en mis redes sociales. ¡Conéctate conmigo y sigamos compartiendo conocimiento y creciendo juntos!</p>
<ul>
<li><p><strong>Twitter</strong>: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>LinkedIn</strong>: <a target="_blank" href="https://www.linkedin.com/in/roxsross/">Rossana Suarez</a></p>
</li>
<li><p><strong>GitHub</strong>: <a target="_blank" href="https://github.com/roxsross">roxsross</a></p>
</li>
<li><p><strong>YouTube</strong>: <a target="_blank" href="https://www.youtube.com/@295devops">295devops</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Los retos ocultos de las entrevistas en DevOps (y cómo destacarte en ellas)]]></title><description><![CDATA[Las entrevistas en DevOps son conocidas por ser un verdadero desafío, y la razón de ello puede ser más compleja de lo que parece. Con una demanda creciente, es fácil sentirse atrapado en un mar de evaluaciones técnicas interminables y criterios confu...]]></description><link>https://blog.295devops.com/los-retos-ocultos-de-las-entrevistas-en-devops-y-como-destacarte-en-ellas</link><guid isPermaLink="true">https://blog.295devops.com/los-retos-ocultos-de-las-entrevistas-en-devops-y-como-destacarte-en-ellas</guid><category><![CDATA[entrevistas]]></category><category><![CDATA[Devops]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sun, 11 May 2025 22:38:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746995724114/e7e3bbcf-fcee-4222-a0f0-6f88646fac2b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Las entrevistas en DevOps son conocidas por ser un <strong>verdadero desafío</strong>, y la razón de ello puede ser más compleja de lo que parece. Con una demanda creciente, es fácil sentirse atrapado en un <strong>mar de evaluaciones técnicas interminables y criterios confusos</strong>. Sin embargo, existen factores clave que pueden marcar la diferencia entre obtener el trabajo que deseas y ser descartado por las empresas.</p>
<p>A continuación, exploramos algunos de los mayores desafíos que enfrentan los DevOps durante las entrevistas y cómo puedes prepararte para superarlos de manera efectiva.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747001508484/2ffcdac1-9126-4126-bb30-56db511f072b.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-la-brecha-entre-teoria-y-practica-el-mayor-desafio">La brecha entre teoría y práctica: el mayor desafío</h2>
<p>Es común que las entrevistas se centren en <strong>conocimientos teóricos y certificaciones</strong>, pero esto no siempre refleja las habilidades prácticas necesarias para el trabajo. A menudo, los candidatos que se presentan <strong>con un currículum cargado de certificaciones como AWS o Kubernetes</strong> se ven sorprendidos al enfrentarse a preguntas básicas sobre conceptos fundamentales, como balanceo de carga o la terminación de SSL.</p>
<p><strong>La lección aquí es clara</strong>: tener certificaciones no garantiza que poseas las habilidades necesarias para resolver problemas reales. Es fácil memorizar respuestas para aprobar un examen, pero la experiencia práctica es lo que realmente cuenta cuando se trata de DevOps. <strong>Las empresas buscan a alguien que sepa cómo aplicar sus conocimientos en entornos de producción, no solo que pueda repetir teoría.</strong></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747002537549/65952961-2b3d-4bcd-b73c-ce3044b29779.png" alt class="image--center mx-auto" /></p>
<blockquote>
<p>¿Memorizar o resolver?</p>
<ul>
<li><p>La tecnología cambia todos los días.</p>
</li>
<li><p>Los comandos de hoy, mañana quedan obsoletos.</p>
</li>
<li><p>La verdadera habilidad no está en recordar cada línea.</p>
</li>
<li><p><mark>Está en pensar, adaptarse y encontrar soluciones cuando el desafío aparece.</mark></p>
</li>
</ul>
</blockquote>
<hr />
<h2 id="heading-que-buscan-realmente-las-empresas">¿Qué buscan realmente las empresas?</h2>
<p><strong>Las certificaciones pueden abrirte puertas</strong>, <strong>pero no son suficientes para asegurar el puesto</strong>. Los gerentes de contratación buscan habilidades concretas y experiencia práctica. Algunos aspectos esenciales que destacan en las entrevistas incluyen:</p>
<ul>
<li><strong>Conocimiento sólido de los principios fundamentales:</strong> Las empresas valoran una comprensión robusta de conceptos clave como por ejemplo: administración de sistemas Linux, automatización, contenedores, redes, proveedores de nube, seguridad y cicd, antes de abordar herramientas avanzadas como Kubernetes o Terraform.</li>
</ul>
<blockquote>
<p><strong>Ejemplo:</strong><br />Una empresa puede valorar más a un candidato que entiende a fondo cómo funciona un sistema operativo (como Linux) y cómo interactúa con redes, en lugar de uno que solo sabe cómo usar herramientas como Kubernetes sin saber cómo optimizar las configuraciones a nivel de sistema.</p>
</blockquote>
<ul>
<li><strong>Capacidad para resolver problemas reales:</strong> Ser capaz de identificar y resolver problemas de forma rápida es crucial. Las empresas valoran enormemente la habilidad de gestionar errores y fallos sin entrar en pánico.</li>
</ul>
<blockquote>
<p><strong>Ejemplo:</strong><br />En un escenario real, si un equipo de DevOps enfrenta un <strong>fallo en una pipeline CI/CD</strong> debido a un cambio de configuración en un repositorio, el candidato ideal no solo debe identificar el problema rápidamente sino también proponer y aplicar una solución eficiente sin causar interrupciones significativas en la entrega continua. Este tipo de resolución de problemas en tiempo real es lo que más valoran las empresas.</p>
</blockquote>
<ul>
<li><strong>Capacidad para trabajar bajo presión:</strong> En DevOps, la gestión de incidentes y la resolución de crisis son habilidades fundamentales. Un buen ingeniero de DevOps debe poder mantener la calma bajo presión y aplicar soluciones rápidas y eficaces.</li>
</ul>
<blockquote>
<p><strong>Ejemplo:</strong><br />Imagina que una empresa está experimentando una <strong>interrupción crítica en su base de datos</strong> debido a un aumento inesperado de tráfico. Un buen DevOps no solo identificaría el problema rápidamente, sino que también implementaría una <strong>estrategia de escalado automático en el clúster de bases de datos</strong>, lo que permite manejar el tráfico sin afectar la experiencia del usuario, todo mientras mantiene la comunicación clara y efectiva con los equipos involucrados.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747001009502/1f8bf27a-e1ea-4594-8d94-1583f86e595f.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-ejemplo-practico"><strong>Ejemplo práctico:</strong></h3>
<p>Imagina que una empresa está buscando un DevOps para integrar su nueva aplicación en la nube. El candidato ideal no solo tendría que tener conocimientos sobre la infraestructura en la nube y cómo configurar Kubernetes, sino también ser capaz de identificar rápidamente un problema en el flujo de trabajo de despliegue. Supongamos que al realizar el despliegue se presenta un <strong>error de acceso a la base de datos debido a una mala configuración de los secretos de la nube</strong>.</p>
<p>El DevOps debería ser capaz de:</p>
<ol>
<li><p><strong>Diagnosticar el problema rápidamente</strong> al revisar los registros y los secretos de la nube.</p>
</li>
<li><p><strong>Aplicar una solución rápida</strong> configurando correctamente los permisos y accesos.</p>
</li>
<li><p><strong>Optimizar el proceso de despliegue para evitar que el problema ocurra en el futuro.</strong></p>
</li>
<li><p><strong>Mantener la comunicación constante</strong> con los equipos de desarrollo y seguridad para asegurar que no se repita el incidente.</p>
</li>
</ol>
<p><mark>Este tipo de experiencia práctica y habilidad para manejar situaciones en tiempo real es exactamente lo que buscan las empresas en un profesional DevOps.</mark></p>
<hr />
<h2 id="heading-preparacion-practica-lo-que-realmente-importa">Preparación práctica: lo que realmente importa</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747001884596/d9f814ff-9db0-4e0b-a1f2-298382f78ba2.png" alt class="image--center mx-auto" /></p>
<p>Para prepararte adecuadamente para una entrevista en DevOps, es importante enfocarte en las siguientes áreas:</p>
<ul>
<li><strong>Domina lo básico antes de las herramientas complejas.</strong><br />  Antes de lanzarte a aprender herramientas como Terraform o Kubernetes, asegúrate de tener una comprensión sólida <strong>[Fundamentos]</strong> de sistemas operativos, scripting, redes, seguridad … [<a target="_blank" href="https://roadmap.sh/devops">Roadmap</a>]. Estas áreas constituyen la base de la mayoría de las tareas en DevOps.</li>
</ul>
<blockquote>
<p><strong>Consejo práctico:</strong><br /><strong>Haz un "sandbox" en tu propio entorno</strong> (puedes usar VMs o contenedores locales). Este será tu <strong>laboratorio personal</strong> donde podrás experimentar con configuraciones de red, sistemas de monitoreo y pequeños scripts de automatización antes de meterte en tecnologías más complejas.</p>
</blockquote>
<ul>
<li><strong>Desarrolla experiencia resolviendo problemas reales.</strong><br />  La teoría está bien, pero la práctica es lo que realmente cuenta. Si puedes, crea un entorno de laboratorio en tu casa, contribuye a proyectos de código abierto o trabaja en proyectos prácticos para aprender a resolver problemas reales. <a target="_blank" href="https://blog.295devops.com/te-sentis-estancado-aprendiendo-devops-aqui-te-dejo-una-solucion-practica-para-avanzar-en-60-dias">Aquí te dejo una solución práctica para avanzar en 60 días</a></li>
</ul>
<blockquote>
<p><strong>Ejemplo práctico:</strong><br />Simula un <strong>fallo en el balanceo de carga</strong> en un entorno de producción. Intenta identificar la raíz del problema usando <strong>logs</strong>, <strong>trazabilidad</strong> y <strong>monitoreo de métricas</strong>. La habilidad para <strong>reconstruir el incidente</strong> y tomar acciones correctivas rápidamente te prepara para los verdaderos desafíos de producción.</p>
</blockquote>
<ul>
<li><strong>Aprende a leer logs y mensajes de error.</strong><br />  La lectura de registros es crucial en DevOps. Muchas veces, la solución a un problema está en los logs, y saber interpretarlos es esencial para diagnosticar y solucionar problemas rápidamente.</li>
</ul>
<blockquote>
<p><strong>Consejo práctico:</strong><br />Haz ejercicios regulares de <strong>debugging</strong>. Revisa los logs de un contenedor o una aplicación en ejecución y busca errores comunes. <strong>Desafíate a encontrar la causa raíz de un problema</strong> solo mirando los logs. Cuanto más lo practiques, mejor serás en resolver problemas rápidamente.</p>
</blockquote>
<ul>
<li><strong>Sé honesto sobre lo que no sabes.</strong><br />  En lugar de intentar impresionar a los entrevistadores con conocimientos falsos, admite lo que no sabes y muestra tu disposición a aprender. La actitud proactiva hacia el aprendizaje es altamente valorada en DevOps.</li>
</ul>
<blockquote>
<p><strong>Ejemplo práctico:</strong><br />Si en una entrevista no sabes cómo manejar un escenario específico, en lugar de intentar adivinar la respuesta, puedes responder algo como:<br /><em>"No tengo experiencia directa con esa herramienta, pero me siento cómodo aprendiendo nuevas tecnologías rápidamente. Te puedo dar ejemplos de cómo he aprendido otras herramientas, como [menciona alguna]. Estoy seguro de que podré adaptarme a este desafío también."</em><br />Esto demuestra <strong>confianza y disposición</strong> para aprender.</p>
</blockquote>
<ul>
<li><strong>Construye un portafolio de soluciones reales.</strong><br />  Presentar ejemplos tangibles de tu trabajo y las soluciones que has implementado en proyectos anteriores demuestra tu experiencia y capacidad real.</li>
</ul>
<blockquote>
<p><strong>Consejo práctico:</strong><br />Documenta tu experiencia utilizando <strong>markdown</strong> o en una plataforma como <strong>GitHub</strong> o <strong>GitLab</strong>. Comparte las soluciones que implementaste y describe las <strong>lecciones aprendidas</strong>. Incluye enlaces a repositorios de código, configuraciones de infraestructura o diagramas que muestren tu proceso.</p>
</blockquote>
<hr />
<h2 id="heading-la-realidad-de-los-roles-en-devops-un-equilibrio-complicado">La realidad de los roles en DevOps: un equilibrio complicado</h2>
<p>Uno de los mayores desafíos en los roles de DevOps es la necesidad de tener un conocimiento equilibrado tanto de desarrollo como de operaciones. A diferencia de otros campos, DevOps requiere que seas capaz de navegar entre estas dos áreas, algo que tradicionalmente ha sido manejado por diferentes especialidades. Esta dualidad hace que el rol sea complicado, ya que no solo debes ser un experto en herramientas y procesos, sino también en la colaboración entre equipos de desarrollo y operaciones.</p>
<p>Este equilibrio también implica que, como ingeniero DevOps, es probable que tengas que cambiar de contexto constantemente, lo que significa que es más importante ser adaptable y tener una base sólida en lugar de memorizar detalles específicos de cada herramienta o servicio.</p>
<hr />
<h2 id="heading-shades-of-devops-roles-un-concepto-para-entender-las-multiples-facetas-de-devops"><strong>Shades of DevOps Roles</strong>: Un concepto para entender las múltiples facetas de DevOps</h2>
<p>El gráfico de <strong>Patrick Debois</strong>, que muestra los <strong>"Shades of DevOps Roles"</strong>, ilustra cómo <strong>DevOps significa cosas diferentes para diferentes personas</strong>. En el diagrama, se puede ver cómo diferentes roles se encuentran en el espectro entre <strong>desarrollo</strong> y <strong>operaciones</strong>, cada uno con su propio conjunto de habilidades y responsabilidades.</p>
<p>Este gráfico revela cómo <strong>el rol de DevOps es dinámico y diverso</strong>, y cómo ha evolucionado más allá de su origen como un conjunto de prácticas relacionadas con la automatización y la entrega continua. Ahora incluye roles emergentes como <strong>DataOps</strong>, <strong>AIOps</strong>, <strong>MLops</strong>, hasta llegar a aquellos que están más centrados en la producción, como <strong>Cloud Ops</strong> y <strong>SysAdmin</strong>. La <strong>"Buzzword Hipness"</strong> muestra cómo algunas tendencias son más populares que otras en el momento, pero todas las prácticas son igualmente importantes en su contexto.</p>
<p><img src="https://media.licdn.com/dms/image/sync/v2/D5627AQEhsOFB39lz8Q/articleshare-shrink_800/articleshare-shrink_800/0/1711818176793?e=2147483647&amp;v=beta&amp;t=tX5iOh99mIYu566YkS6i7izklecpXeHMmDzz_Fdjmt8" alt="Shades of DevOps | Patrick Debois " /></p>
<h4 id="heading-hoy-hay-mas">Hoy, hay más…</h4>
<p>Y como muestra el gráfico de Patrick Debois, <strong>hoy hay más roles en DevOps que nunca</strong>, cada uno con un enfoque especializado para necesidades específicas dentro del ciclo de vida del software. Pero, claro, no olvidemos que <strong>RoxsOps</strong> (¡sí, lo dije!, soy yo 🔥) , <strong>con toda la fuerza de la IA</strong> y el poder de la automatización, llevando a <strong>DevOps</strong> a un <strong>nivel superpower</strong>. 😎</p>
<p>¡Así que, si tienes dudas, no te preocupes! Solo recuerda <strong>"surfea el fuego"</strong> y <strong>mantén el ritmo con RoxsOps</strong>. <strong>¡La IA está aquí, y RoxsOps no te dejará atrás!</strong> 💪🔥</p>
<hr />
<h2 id="heading-enfoque-para-avanzar-en-devops">Enfoque para avanzar en DevOps</h2>
<p>Si estás buscando ingresar a DevOps o mejorar tu rendimiento en las entrevistas, lo más importante es construir <strong>una base sólida de habilidades prácticas en lugar de enfocarte solo en obtener certificaciones</strong>. Recuerda que DevOps no se trata solo de conocer herramientas o plataformas específicas, sino de conectar diferentes áreas y resolver problemas de manera eficiente.</p>
<p>Si eres parte del proceso de contratación, considera que podrías estar filtrando a candidatos valiosos con habilidades reales. <strong>Revisa tus procesos de entrevistas y asegúrate de que estés buscando las habilidades que realmente importan</strong>.</p>
<p>Al final, DevOps <mark>no es solo sobre tener un conjunto de habilidades técnicas</mark>; <strong><mark>se trata de tener la capacidad de adaptarse, aprender y colaborar de manera efectiva</mark></strong>. Enfócate en la práctica, mantén una mentalidad de aprendizaje constante, y te convertirás en un candidato invaluable para cualquier equipo de DevOps.</p>
<hr />
<h2 id="heading-bonus-track-la-ia-en-devops-una-tendencia-clave-en-la-aceleracion"><strong>Bonus Track: La IA en DevOps: Una tendencia clave en la aceleración</strong></h2>
<p>La inteligencia artificial (IA) está jugando un papel crucial en DevOps, acelerando procesos y transformando la forma en que gestionamos el ciclo de vida del software. La <strong>automatización impulsada por IA</strong> permite que los equipos de DevOps realicen tareas con mayor rapidez y precisión, desde la optimización de pipelines hasta la predicción de fallos en los sistemas.</p>
<p><strong>Aceleración y optimización con IA:</strong></p>
<ul>
<li><p><strong>Monitoreo inteligente:</strong> Las herramientas de IA pueden analizar grandes cantidades de datos y detectar patrones que podrían pasarse por alto en un entorno tradicional. Esto acelera la identificación de problemas y permite una respuesta proactiva antes de que el impacto sea significativo.</p>
</li>
<li><p><strong>Automatización predictiva:</strong> Con el uso de IA, es posible predecir fallos en la infraestructura antes de que ocurran, lo que permite a los equipos DevOps tomar medidas preventivas y mejorar la fiabilidad del sistema.</p>
</li>
<li><p><strong>Optimización de pipelines:</strong> Herramientas como Jenkins y GitLab están incorporando IA para mejorar la ejecución de pipelines, ayudando a identificar y solucionar cuellos de botella de manera automática.</p>
</li>
</ul>
<h2 id="heading-como-prepararte-para-aprovechar-la-ia-en-devops"><strong>¿Cómo prepararte para aprovechar la IA en DevOps?</strong></h2>
<p>Familiarízate con herramientas basadas en IA que se integran en el flujo de trabajo DevOps, como <strong>GitLab CI/CD, Github Actions</strong> con capacidades de aprendizaje automático y <strong>Terraform</strong> para automatización predictiva. <strong>Entender cómo aplicar IA para mejorar la eficiencia de tu pipeline y la estabilidad de tus sistemas</strong> será un diferenciador clave en las entrevistas.</p>
<p><a target="_blank" href="https://blog.295devops.com/20-trucos-de-ia-para-dominar-tu-flujo-de-trabajo-devops-y-acelerar-resultados">20 Trucos de IA para Dominar tu Flujo de Trabajo DevOps y Acelerar Resultados</a></p>
<hr />
<p>En este mundo en constante cambio, DevOps es un campo donde <strong>el aprendizaje continuo</strong> es la clave. No te limites a memorizar teorías: <strong>practica, resuelve problemas reales y mantén una mentalidad de crecimiento</strong>. <strong>DevOps es para quienes buscan adaptarse, aprender y colaborar, no solo para quienes conocen herramientas.</strong> Con estas estrategias, estarás en el camino correcto para destacarte y tener éxito en tus entrevistas.</p>
<p><strong><em>¡Sigue surfeando el fuego del cambio, cada desafío es una oportunidad para crecer!</em></strong></p>
<hr />
<h2 id="heading-conectate-conmigo-y-vamos-a-surfear-juntos"><strong>Conéctate conmigo y vamos a surfear juntos:</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747003017741/2aab81cb-60b3-489c-9c0f-546c75003455.png" alt class="image--center mx-auto" /></p>
<p>Si quieres seguir aprendiendo, compartir ideas, o simplemente unirte a la comunidad, <strong>conéctate conmigo en mis redes sociales</strong>.</p>
<ul>
<li><p><strong>Twitter</strong>: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>LinkedIn</strong>: <a target="_blank" href="https://www.linkedin.com/in/roxsross">Rossana Suarez</a></p>
</li>
<li><p><strong>YouTube (295devops)</strong>: <a target="_blank" href="https://www.youtube.com/@295devops">295DevOps en YouTube</a></p>
</li>
<li><p><strong>Instagram</strong>: <a target="_blank" href="https://www.instagram.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>GitHub</strong>: <a target="_blank" href="https://github.com/roxsross">Roxs GitHub</a></p>
</li>
</ul>
<p><strong><em>¡Juntos seguimos creciendo!</em></strong></p>
]]></content:encoded></item><item><title><![CDATA[¿Qué Hago Yo en DevOps? Spoiler: No Arreglo Impresoras 😂]]></title><description><![CDATA[Si eres parte del mundo tech, probablemente alguna vez te hayan hecho esa temida pregunta: “**¿Y vos qué hacés?” …y de repente, el espacio se vuelve más incómodo que cuando tu abuela intenta usar WhatsApp.
Ser DevOps es, por lo general, sinónimo de l...]]></description><link>https://blog.295devops.com/que-hago-yo-en-devops-spoiler-no-arreglo-impresoras</link><guid isPermaLink="true">https://blog.295devops.com/que-hago-yo-en-devops-spoiler-no-arreglo-impresoras</guid><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 03 May 2025 18:53:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746296785269/8912ca2e-f306-4871-9808-402296214bcb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Si eres parte del mundo tech, probablemente alguna vez te hayan hecho esa temida pregunta: <em>“<strong>**¿Y vos qué hacés?”</strong></em> …y de repente, el espacio se vuelve más incómodo que cuando tu abuela intenta usar WhatsApp.</p>
<p>Ser DevOps es, por lo general, sinónimo de lidiar con conceptos tan técnicos que, cuando intentas explicarlos a alguien que no tiene idea, la conversación termina en *“*<strong><em>Ah, entonces trabajas con computadoras, ¿no?”</em></strong></p>
<p><mark>Pero no te preocupes, aquí te traemos algunas formas divertidas, y a veces absurdas, de explicar tu trabajo sin perder la paciencia. 😎</mark></p>
<h3 id="heading-1-la-fabrica-de-tacos-la-explicacion-que-todos-entienden">1. <strong>La Fábrica de Tacos: La Explicación que Todos Entienden 🌮</strong></h3>
<p>"Los desarrolladores hacen tacos. Yo construyo la taquería donde se preparan esos tacos". 🏭</p>
<p>¿Quién no entiende esa metáfora? Un ingeniero me dijo: <em>“Usé esta explicación en la fiesta de mi prima y todos lo entendieron al instante”</em>. Y claro, hay más versiones, porque en el mundo DevOps todo se puede comparar con comida:</p>
<ul>
<li><p>"Yo hago las tortillas y las salsas que hacen que los tacos salgan perfectos".</p>
</li>
<li><p>"Me aseguro de que podamos hacer tacos en masa sin que exploten las parrillas".</p>
</li>
<li><p>"¡Yo soy el que prueba los tacos y a veces los tiro al suelo solo para ver si hay salsa derramada!"</p>
</li>
</ul>
<p>Así que ya sabes, tu trabajo en DevOps también es como construir una taquería de tacos... ¡todo el mundo lo entiende!</p>
<h3 id="heading-2-trabajo-con-computadoras-ya-esta">2. <strong>¿Trabajo con Computadoras? ¡Ya está! 🙄</strong></h3>
<p>La respuesta más rápida de muchos es simplemente <em>"Trabajo con computadoras"</em> y hacen un movimiento como si estuvieran escribiendo un código secreto. Y luego… ¡plop! La gente ya no pregunta más.</p>
<p><strong>Ingeniero 1:</strong> "Digo 'Trabajo con computadoras' y automáticamente la gente se va."<br /><strong>Ingeniero 2:</strong> "Lo mejor es decir 'Trabajo con computadoras', luego decir que si te hace falta la impresora, no es mi problema" 😆</p>
<h3 id="heading-3-respuestas-absurdas-para-crear-confusion-total">3. <strong>Respuestas Absurdas para Crear Confusión Total 🤯</strong></h3>
<p>¿Alguna vez has querido salirte por la tangente completamente? Aquí tienes un par de respuestas para dejar a todos boquiabiertos:</p>
<ul>
<li><p>"Digo que soy influencer en OnlyFotos. Nadie hace más preguntas."</p>
</li>
<li><p>“Soy un RoxsStar de Eurovision”</p>
</li>
<li><p>“Chef de una cadena de comida coreana”</p>
</li>
</ul>
<p><mark>A veces, cuanto más extraño suene, más divertido es el desconcierto de la gente.</mark></p>
<h3 id="heading-4-la-caja-de-pandora-digital-nunca-sabes-lo-que-va-a-salir">4. La Caja de Pandora Digital: ¡Nunca Sabes lo que Va a Salir! 🎁</h3>
<p>¿Dices "trabajo con la nube"? Y ahí empieza la confusión…</p>
<p><strong>Yo:</strong> "Trabajo con la nube."<br /><strong>Ellos:</strong> "Ah, ¿como el Wi-Fi?"<br /><strong>Yo:</strong> "Sí, pero imagina que el Wi-Fi está tomando café y no lo puedes ver." ☕</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746298062943/d380798f-90f0-4d5f-bd6b-4f96b31b2995.png" alt class="image--center mx-auto" /></p>
<p>Es como tener una <em>caja de Pandora digital</em>: nadie sabe qué hay adentro, pero cuando la abres, todo está funcionando… ¡hasta que de repente no lo está! 😜</p>
<h3 id="heading-5-la-clasica-pregunta-arreglas-mi-computadora">5. <strong>La Clásica Pregunta: "¿Arreglas mi computadora?"</strong> 💻</h3>
<p>No importa cuán técnico sea tu trabajo, siempre habrá alguien que pregunte:<br /><em>“Entonces, ¿eres un experto en computadoras? ¿Puedes arreglar mi computadora?”</em></p>
<p><img src="https://sdmntprsouthcentralus.oaiusercontent.com/files/00000000-544c-61f7-98ba-448c36ba6ae0/raw?se=2025-05-03T18%3A54%3A51Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=10cba972-a499-5bea-a5f2-5b82e2354a9c&amp;skoid=7c382de0-129f-486b-9922-6e4a89c6eb7d&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-05-02T20%3A36%3A40Z&amp;ske=2025-05-03T20%3A36%3A40Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=0E%2BIpkqx8VZm0NFRdBRe1tr3G4fbXmQmuAcx0MAnYTU%3D" alt /></p>
<p>La respuesta clásica: "Solo porque trabajo con computadoras no significa que pueda arreglar tu impresora, pero sí, la puedo arreglar... aunque no sea mi trabajo". 🙃</p>
<h3 id="heading-6-el-superheroe-digital">6. <strong>El Superhéroe Digital 🦸‍♂️</strong></h3>
<p>"Soy como un superhéroe digital. ¡Pero sin capa! Mi trabajo es asegurarme de que el código fluya sin problemas, que los sistemas estén listos para escalar y que todo el equipo de desarrollo y operaciones pueda colaborar eficientemente. Mientras todos están distraídos con memes, yo me aseguro de que la magia ocurra sin que se note." 😎💻</p>
<p>En DevOps, nadie ve todo el trabajo detrás del telón. Pero sin ese esfuerzo continuo de automatización, integración continua y entrega continua, ¡la web sería un caos! 🚀</p>
<h3 id="heading-7-la-comparacion-con-la-cocina">7. <strong>La Comparación con la Cocina 🍳</strong></h3>
<p>"Soy como un chef de software. Los desarrolladores son los que preparan los ingredientes, pero yo soy el que se encarga de la receta para que todo salga a tiempo, bien cocido y sin que se queme". 🍴</p>
<p>Si no fuera por ti, el “plato” (es decir, el sistema) podría no salir como se espera. ¡Alguien tiene que estar al mando de la cocina para que todo quede delicioso y funcione perfectamente!</p>
<hr />
<h2 id="heading-reflexion-final-lo-importante-no-es-lo-que-haces-sino-como-lo-explicas"><strong>Reflexión Final: Lo Importante No Es lo que Haces, Sino Cómo Lo Explicas.</strong></h2>
<p>Al final del día, lo que más importa es tu capacidad de comunicar lo que haces y ayudar a otros a entender la importancia de tu trabajo, incluso si tu explicación es algo tan simple como <em>“Soy el arquitecto de la nube”</em> o <em>“Arreglo la autopista digital por donde corren los datos”</em>. Lo que haces puede ser complejo, pero si lo explicas con humor y claridad, ¡todo se hace más fácil de entender!</p>
<p>Recuerda, como en DevOps, la clave es la <strong>colaboración</strong>. La comunidad tech está aquí para apoyarnos y aprender juntos, así que no te frustres si no te entienden. Al final, todos estamos en el mismo equipo. 🔥</p>
<hr />
<p><strong>Sígueme en mis redes sociales para más contenido onfire:</strong></p>
<ul>
<li><p><strong>LinkedIn</strong>: <a target="_blank" href="https://www.linkedin.com/in/roxsross">@roxsross</a></p>
</li>
<li><p><strong>Twitter</strong>: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>Instagram</strong>: <a target="_blank" href="https://www.instagram.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>YouTube</strong>: <a target="_blank" href="https://www.youtube.com/c/295devops">295devops</a></p>
</li>
</ul>
<p><strong>¡Y no olvides que lo importante no es la respuesta, sino surfear las olas!</strong> 💪</p>
]]></content:encoded></item><item><title><![CDATA[CI/CD The Series: Aprende a Crear tu Primer Pipeline de Jenkins con Roxs]]></title><description><![CDATA[Es muy común encontrar procesos de despliegue basados en scripts manuales con documentación obsoleta o, en el peor de los casos, ¡sin ninguna! 🤔. ¿Cuánto tiempo tarda tu nuevo código en desplegarse en producción? ¿Un viernes por la tarde? ¿Cuántos d...]]></description><link>https://blog.295devops.com/cicd-the-series-aprende-a-crear-tu-primer-pipeline-de-jenkins-con-roxs</link><guid isPermaLink="true">https://blog.295devops.com/cicd-the-series-aprende-a-crear-tu-primer-pipeline-de-jenkins-con-roxs</guid><category><![CDATA[roxsross]]></category><category><![CDATA[Devops]]></category><category><![CDATA[cicd]]></category><category><![CDATA[Jenkins]]></category><category><![CDATA[ Jenkins, DevOps]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 03 May 2025 16:55:25 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746285223154/e1ef0d10-faff-491b-913a-4fee84fb742a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Es muy común encontrar procesos de despliegue basados en scripts manuales con documentación obsoleta o, en el peor de los casos, ¡sin ninguna! 🤔. ¿Cuánto tiempo tarda tu nuevo código en desplegarse en producción? ¿Un viernes por la tarde? ¿Cuántos despliegues puedes realizar a la semana? ¿Y al día? 🔥</p>
<p>Si alguna vez has tenido que lidiar con estos problemas, no te preocupes, no estás solo. La buena noticia es que ¡puedes resolverlo de manera rápida y eficiente! Hoy comenzamos con "CI/CD The Series", y en esta primera entrega vamos a hablar de <strong>Jenkins</strong>, la herramienta de automatización de tareas en procesos de integración continua (CI) más extendida. Vamos a entender qué es Jenkins, cómo funciona, para qué sirve y, por qué es una de las mejores opciones si queremos aplicar CI en nuestros proyectos de software. Además, explicaremos de forma sencilla en qué consiste la práctica de la integración continua y por qué es tan crucial en el mundo del desarrollo ágil y la entrega de software.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746287352084/6e7f9c8d-4b05-4a2a-9207-b3984d3ce4ee.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-que-es-ci-integracion-continua"><strong>¿Qué es CI (Integración Continua)?</strong></h2>
<p>La <strong>integración continua (CI)</strong> es una práctica fundamental en el desarrollo de software moderno. En términos simples, se refiere a la acción de integrar cambios de código frecuentemente en un repositorio compartido. Los desarrolladores no esperan semanas para realizar cambios masivos, sino que lo hacen de manera continua, integrando los cambios a medida que avanzan. Esto permite a los equipos detectar errores rápidamente y mantener la calidad del código constantemente.</p>
<h4 id="heading-beneficios-de-la-ci"><strong>Beneficios de la CI:</strong></h4>
<ol>
<li><p><strong>Desarrollo más rápido:</strong> Al integrar cambios pequeños y frecuentes, los desarrolladores pueden detectar errores más rápidamente.</p>
</li>
<li><p><strong>Menos conflictos de código:</strong> La integración continua ayuda a reducir los conflictos de código que suelen ocurrir cuando varias personas trabajan en una misma base de código durante largo tiempo sin integración.</p>
</li>
<li><p><strong>Mejora de la calidad:</strong> Las pruebas automáticas frecuentes permiten encontrar errores más pronto, lo que significa que los desarrolladores pueden corregir los fallos antes de que se conviertan en problemas críticos.</p>
</li>
<li><p><strong>Entrega continua:</strong> Al facilitar la integración de todos los cambios, se hace más fácil implementar la práctica de <strong>entrega continua (CD)</strong>, donde cada cambio pasa por un proceso automático de pruebas y despliegue.</p>
</li>
</ol>
<p><a target="_blank" href="https://aws.amazon.com/es/devops/continuous-integration/"><strong>Integración continua by AWS</strong></a></p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jltprqyy4jai60l5jgbm.png" alt="CICD" /></p>
<p><mark>Con la </mark> <em><mark>entrega continua</mark></em><mark>, se crean, prueban y preparan automáticamente los cambios en el código y se entregan para la fase de producción. La entrega continua amplía la integración continua al implementar todos los cambios en el código en un entorno de pruebas y/o de producción después de la fase de creación.</mark></p>
<blockquote>
<p><strong><em>Siempre fue un gran desafío para las empresas establecer, configurar y administrar un flujo de trabajo constante. Debido a los rápidos cambios de los últimos años, el desarrollo de software ha dado un gran paso adelante desde la introducción de la integración continua y la entrega continua (CI/CD). Ahora que comprende el papel que desempeña la CI en el desarrollo de software, podemos pasar al objetivo central de este tutorial de pipeline de Jenkins. by Roxs</em></strong></p>
</blockquote>
<h2 id="heading-por-que-jenkins-es-una-de-las-mejores-opciones-para-cicd"><strong>¿Por qué Jenkins es una de las mejores opciones para CI/CD?</strong></h2>
<p><strong>Jenkins</strong> es el servidor de CI más popular y utilizado, diseñado para facilitar la integración continua y la entrega continua. Con <a target="_blank" href="https://github.com/jenkinsci/jenkins"><strong>más de 23.9k estrellas en GitHub</strong> y <strong>9.1k forks</strong></a>, Jenkins es conocido por su flexibilidad y la capacidad de automatizar casi todos los aspectos del ciclo de vida del software.</p>
<h4 id="heading-ventajas-de-jenkins"><strong>Ventajas de Jenkins:</strong></h4>
<ul>
<li><p><strong>Automatización total:</strong> Jenkins permite automatizar completamente los procesos de construcción, pruebas y despliegue, eliminando tareas manuales tediosas y propensas a errores.</p>
</li>
<li><p><strong>Extensibilidad mediante plugins:</strong> Jenkins cuenta con una enorme cantidad de plugins que lo hacen muy versátil. Puedes integrar Jenkins con herramientas de testing, bases de datos, servicios en la nube como AWS, y mucho más.</p>
</li>
<li><p><strong>Escalabilidad:</strong> Desde proyectos pequeños hasta sistemas a gran escala, Jenkins se adapta fácilmente a proyectos de cualquier tamaño y complejidad.</p>
</li>
<li><p><strong>Código abierto:</strong> Al ser open-source, Jenkins permite modificaciones y personalización para adaptarse a las necesidades específicas de tu equipo y flujo de trabajo.</p>
</li>
<li><p><strong>Interfaz web intuitiva:</strong> Jenkins es fácil de manejar gracias a su interfaz web que te permite configurar tus pipelines de manera visual, aunque también puedes hacerlo directamente con código.</p>
</li>
</ul>
<h3 id="heading-como-funciona-jenkins-en-un-flujo-de-trabajo-cicd"><strong>¿Cómo funciona Jenkins en un flujo de trabajo CI/CD?</strong></h3>
<p>Jenkins actúa como el corazón del flujo de trabajo CI/CD. Usando <strong>Jenkinsfiles</strong> (archivos de configuración en Groovy), puedes definir qué pasos se deben ejecutar automáticamente cuando se realiza un commit o pull request en tu repositorio de código.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1gn9dlpe34ppds9xy9hj.png" alt="Jenkins" /></p>
<p>Un flujo de trabajo típico de Jenkins implica varios pasos automatizados:</p>
<ol>
<li><p><strong>Checkout del código:</strong> Jenkins descarga el código desde un repositorio de control de versiones como Git.</p>
</li>
<li><p><strong>Compilación:</strong> Se compila el código (si aplica), asegurando que no haya errores de sintaxis.</p>
</li>
<li><p><strong>Pruebas:</strong> Ejecuta pruebas automatizadas para validar la integridad del código.</p>
</li>
<li><p><strong>Despliegue:</strong> Si las pruebas pasan con éxito, el código se despliega en un entorno de staging o producción.</p>
</li>
</ol>
<p>Con Jenkins, este proceso se convierte en algo automático, eliminando los errores humanos y acelerando el tiempo de entrega.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Documentación Oficial de <a target="_blank" href="https://www.jenkins.io/doc"><strong>Jenkins</strong></a></div>
</div>

<h2 id="heading-tipos-de-pipelines-en-jenkins"><strong>Tipos de Pipelines en Jenkins</strong></h2>
<p>Jenkins ofrece dos tipos de pipelines:</p>
<h4 id="heading-1-scripted-pipeline"><strong>1. Scripted Pipeline:</strong></h4>
<p>Este es el modelo tradicional y más flexible, pero también es más complejo. Se utiliza Groovy para escribir un pipeline que te permite un control total sobre el proceso.</p>
<h4 id="heading-2-declarative-pipeline"><strong>2. Declarative Pipeline:</strong></h4>
<p>Este tipo de pipeline es más simple y accesible, especialmente para quienes se inician en Jenkins. Usando una sintaxis más amigable y estructurada, los pipelines declarativos permiten escribir las etapas de CI/CD de forma más clara y fácil de entender.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>SCRIPTED PIPELINE</strong></td><td><strong>DESCRIPTED PIPELINE</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Modelo de programación imperativo</td><td>Modelo de programación declarativo</td></tr>
<tr>
<td>Entorno de programación con todas las funciones</td><td>Sintaxis más simple y pragmática para la creación de Jenkins pipeline</td></tr>
<tr>
<td>Gran flexibilidad y extensibilidad</td><td>Limitado a lo que puede hacer un usuario</td></tr>
<tr>
<td>Se declara y ejecuta mediante nodos</td><td>Se declara y ejecuta mediante el comando pipeline y los diferentes stages, stage, steps y step</td></tr>
<tr>
<td>No hay muchas limitaciones para usuarios expertos y requerimientos complejos</td><td>La mejor opción para el desarrollo de estrategias de CI y CD con Pipelines</td></tr>
</tbody>
</table>
</div><h2 id="heading-sintaxis-de-un-pipeline-declarativo"><strong>Sintaxis de un Pipeline Declarativo:</strong></h2>
<p>Un ejemplo simple de un pipeline declarativo en Jenkins:</p>
<pre><code class="lang-yaml"><span class="hljs-string">pipeline</span> {
    <span class="hljs-string">agent</span> <span class="hljs-string">any</span>
    <span class="hljs-string">stages</span> {
        <span class="hljs-string">stage('Stage:</span> <span class="hljs-string">Hola</span> <span class="hljs-string">Mundo')</span> {
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">echo</span> <span class="hljs-string">'Paso 1: Hola Mundo'</span>
            }
        }
        <span class="hljs-string">stage('Stage:</span> <span class="hljs-string">Segundo</span> <span class="hljs-string">Stage')</span> {
            <span class="hljs-string">steps</span> {
                <span class="hljs-string">echo</span> <span class="hljs-string">'Paso 2: Hola Dos Veces'</span>
                <span class="hljs-string">echo</span> <span class="hljs-string">'Paso 3: Hola Tres Veces'</span>
            }
        }
    }
}
</code></pre>
<p><mark>Este código define un pipeline con dos etapas (stages): una que imprime "Hola Mundo" y otra que imprime "Hola Dos Veces" y "Hola Tres Veces". ¡Imagina lo que podrías hacer con un pipeline real de construcción y despliegue!</mark></p>
<h2 id="heading-como-instalar-jenkins"><strong>¿Cómo instalar Jenkins?</strong></h2>
<p>Jenkins se puede instalar de varias maneras, pero la forma más rápida y sencilla es usando <strong>Docker</strong>. Esto te permite tener Jenkins corriendo en minutos sin preocuparte por la configuración del sistema.</p>
<h3 id="heading-instalacion-con-docker"><strong>Instalación con Docker:</strong></h3>
<pre><code class="lang-bash">docker run -p 8080:8080 -p 50000:50000 -d --name jenkins --restart=always jenkins/jenkins:alpine
</code></pre>
<p>Una vez que Jenkins esté en funcionamiento, puedes acceder a él a través de tu navegador en <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a>. ¡Y listo! Ahora puedes comenzar a configurar tu primer pipeline.</p>
<p>Desbloquear Jenkins: Abre tu navegador en <a target="_blank" href="http://localhost:8080">http://localhost:8080</a> y usa la contraseña que se encuentra en:</p>
<pre><code class="lang-bash">docker <span class="hljs-built_in">exec</span> jenkins cat /var/jenkins_home/secrets/initialAdminPassword
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Documentación sobre instalación de Jenkins usando <a target="_self" href="https://www.jenkins.io/doc/book/installing/docker/">Docker</a></div>
</div>

<h3 id="heading-instalacion-en-ubuntu"><strong>Instalación en Ubuntu:</strong></h3>
<p>Si prefieres instalar Jenkins directamente en un sistema Ubuntu, sigue estos pasos:</p>
<ol>
<li><p><strong>Instalar Java:</strong> Jenkins requiere Java, así que asegúrate de tenerlo instalado. Puedes instalar OpenJDK con el siguiente comando:</p>
<pre><code class="lang-bash"> sudo apt install -y openjdk-21-jre
</code></pre>
</li>
<li><p><strong>Agregar el repositorio de Jenkins:</strong></p>
<pre><code class="lang-bash"> sudo wget -O /etc/apt/keyrings/jenkins-keyring.asc https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key
 <span class="hljs-built_in">echo</span> <span class="hljs-string">"deb [signed-by=/etc/apt/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/"</span> | sudo tee /etc/apt/sources.list.d/jenkins.list &gt; /dev/null
 sudo apt-get update
 sudo apt install -y jenkins
</code></pre>
</li>
<li><p><strong>Iniciar Jenkins:</strong></p>
<pre><code class="lang-bash"> sudo systemctl start jenkins
 sudo systemctl status jenkins
</code></pre>
</li>
<li><p><strong>Desbloquear Jenkins:</strong> Abre tu navegador en <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a> y usa la contraseña que se encuentra en:</p>
<pre><code class="lang-yaml"> <span class="hljs-string">sudo</span> <span class="hljs-string">cat</span> <span class="hljs-string">/var/lib/jenkins/secrets/initialAdminPassword</span>
</code></pre>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Ahora, pega la Contraseña de administrador. Luego, haga clic en el Continúar</div>
</div>

<p>Espera hasta que se instalen todos los complementos. Cuando finalice la instalación, haga clic en continúar.</p>
<h3 id="heading-iniciando-jenkins">Iniciando Jenkins</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746286156542/f7f65304-b4bf-40ee-9102-5607fcefe749.png" alt class="image--center mx-auto" /></p>
<p><strong>Cree un perfil de administrador para Jenkins. Ingrese los detalles requeridos y haga clic en Guardar y continuar.</strong></p>
<blockquote>
<p><strong><em>Sabemos que siempre cuando es la primera vez, usamos user y pass admin:admin xD bueno tratemos que si es un ambiente productivo colocar pass con mas seguridad</em></strong></p>
</blockquote>
<h4 id="heading-finalmente-el-proceso-de-configuracion-esta-hecho-y-el-anterior-es-el-predeterminado"><mark>Finalmente, el proceso de configuración está hecho, y el anterior es el predeterminado,</mark></h4>
<h4 id="heading-bienvenido-a-jenkins"><mark>¡Bienvenido a Jenkins! .</mark></h4>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pfh7zi4nfh45cwowbzxo.png" alt="install" /></p>
<hr />
<h3 id="heading-10-plugins-esenciales-para-jenkins"><strong>10 Plugins Esenciales para Jenkins</strong></h3>
<p>Jenkins es increíblemente flexible y potente, y gran parte de esa flexibilidad se debe a su sistema de plugins. Con los siguientes 10 plugins podrás integrar Jenkins con diversas herramientas y servicios, facilitando aún más tu flujo de trabajo CI/CD.</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Revisa los plugins disponibles siempre asegura que sea oficiales <a target="_blank" href="https://plugins.jenkins.io/"><strong>Jenkins Plugins</strong></a></div>
</div>

<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1dd1x3kkcqy82txnj09g.png" alt="Image" /></p>
<h4 id="heading-1-aws-credentials-plugin"><strong>1. AWS Credentials Plugin</strong></h4>
<p>Este plugin permite que Jenkins gestione y utilice las credenciales de AWS para integrarse con servicios de Amazon Web Services, como S3, EC2, Lambda, etc. Es fundamental para la integración de Jenkins con la nube.</p>
<h4 id="heading-2-docker-pipeline-plugin"><strong>2. Docker Pipeline Plugin</strong></h4>
<p>Este plugin permite que Jenkins interactúe con Docker para crear contenedores, ejecutar pruebas dentro de contenedores y más. Es esencial si usas Docker en tu flujo de trabajo.</p>
<h4 id="heading-3-blue-ocean-plugin"><strong>3. Blue Ocean Plugin</strong></h4>
<p>Blue Ocean redefine la experiencia de usuario en Jenkins. Este plugin te proporciona una interfaz más moderna y visual para configurar, ejecutar y monitorear tus pipelines.</p>
<h4 id="heading-4-github-plugin"><strong>4. GitHub Plugin</strong></h4>
<p>Este plugin conecta Jenkins con GitHub, permitiendo disparar pipelines automáticamente cuando se realizan cambios en repositorios de GitHub.</p>
<h4 id="heading-5-sonarqube-scanner-plugin"><strong>5. SonarQube Scanner Plugin</strong></h4>
<p>El plugin SonarQube Scanner para Jenkins facilita la integración de Jenkins con SonarQube, permitiendo realizar análisis de calidad de código automáticamente.</p>
<h4 id="heading-6-slack-notification-plugin"><strong>6. Slack Notification Plugin</strong></h4>
<p>Este plugin envía notificaciones a canales de Slack cada vez que un job o un pipeline cambia de estado. Ideal para mantener al equipo informado sobre el estado de las tareas.</p>
<h4 id="heading-7-gitlab-plugin"><strong>7. GitLab Plugin</strong></h4>
<p>El plugin de GitLab integra Jenkins con los repositorios GitLab, permitiendo que las tareas de Jenkins se ejecuten cada vez que se haga un commit o un pull request en un repositorio GitLab.</p>
<h4 id="heading-8-pipeline-utility-steps-plugin"><strong>8. Pipeline Utility Steps Plugin</strong></h4>
<p>Este plugin proporciona pasos adicionales para manipular archivos y ejecutar comandos útiles dentro de los pipelines, como la creación de archivos, lectura y escritura de variables, etc.</p>
<h4 id="heading-9-email-extension-plugin"><strong>9. Email Extension Plugin</strong></h4>
<p>El plugin de Email Extension permite enviar correos electrónicos en función de los resultados de las compilaciones. Es útil para alertar a los miembros del equipo si algo sale mal durante el proceso de integración.</p>
<h4 id="heading-10-jira-plugin"><strong>10. Jira Plugin</strong></h4>
<p>Si utilizas Jira para gestionar los tickets de tu proyecto, este plugin te permite conectar Jenkins con Jira y asociar automáticamente los builds con tickets específicos.</p>
<hr />
<h2 id="heading-vamos-a-crear-nuestro-primer-pipeline"><strong>¡Vamos a Crear Nuestro Primer Pipeline!</strong></h2>
<h3 id="heading-ejemplo-simple-de-pipeline-en-jenkins"><strong>Ejemplo Simple de Pipeline en Jenkins:</strong></h3>
<p>A continuación, te mostramos un <strong>Jenkinsfile</strong> básico que realiza las siguientes acciones:</p>
<ol>
<li><p><strong>Compila el código.</strong></p>
</li>
<li><p><strong>Ejecuta pruebas.</strong></p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Este ejemplo es perfecto si estás comenzando y quieres ver cómo funciona un pipeline sin complicaciones.</div>
</div>

<h4 id="heading-1-crea-un-nuevo-proyecto-en-jenkins"><strong>1. Crea un Nuevo Proyecto en Jenkins</strong></h4>
<ul>
<li><p>Inicia sesión en Jenkins y haz clic en <strong>Nuevo Elemento</strong>.</p>
</li>
<li><p>Selecciona la opción <strong>Pipeline</strong> como tipo de proyecto. Este tipo de proyecto te permitirá definir tu pipeline mediante un <strong>Jenkinsfile</strong>.</p>
</li>
<li><p>Dale un nombre descriptivo a tu proyecto, como "MiPrimerPipeline" o algo relacionado con tu aplicación.</p>
</li>
</ul>
<h4 id="heading-2-define-tu-jenkinsfile"><strong>2. Define tu Jenkinsfile</strong></h4>
<ul>
<li><p>En la configuración de tu nuevo proyecto, busca la sección <strong>Pipeline</strong>.</p>
</li>
<li><p>En el campo <strong>Pipeline Script</strong>, define tu Jenkinsfile, que es el archivo donde escribirás las etapas (stages) de tu pipeline.</p>
</li>
</ul>
<pre><code class="lang-bash">pipeline {
    agent any

    stages {
        // Etapa de compilación
        stage(<span class="hljs-string">'Build'</span>) {
            steps {
                <span class="hljs-built_in">echo</span> <span class="hljs-string">'Compilando el código...'</span>
                // Aquí puedes agregar tu comando de compilación, por ejemplo:
                sh <span class="hljs-string">'echo "Compilación exitosa!"'</span>
            }
        }

        // Etapa de pruebas
        stage(<span class="hljs-string">'Test'</span>) {
            steps {
                <span class="hljs-built_in">echo</span> <span class="hljs-string">'Ejecutando las pruebas...'</span>
                // Aquí puedes agregar el comando para ejecutar pruebas, por ejemplo:
                sh <span class="hljs-string">'echo "Pruebas exitosas!"'</span>
            }
        }
    }
}
</code></pre>
<h4 id="heading-3-guarda-y-ejecuta-tu-pipeline"><strong>3. Guarda y Ejecuta tu Pipeline</strong></h4>
<ul>
<li><p>Una vez que hayas definido tu Jenkinsfile, haz clic en <strong>Guardar</strong> para guardar la configuración del proyecto.</p>
</li>
<li><p>Para ejecutar el pipeline, haz clic en <strong>Construir ahora</strong>. Jenkins comenzará a ejecutar cada etapa que hayas definido en el Jenkinsfile.</p>
</li>
<li><p>Puedes ver el progreso en la consola de Jenkins mientras se ejecutan las etapas, y si alguna falla, podrás revisar los logs para identificar el problema.</p>
</li>
</ul>
<h4 id="heading-4-observa-el-progreso-y-resultados"><strong>4. Observa el Progreso y Resultados</strong></h4>
<ul>
<li><p>Una vez que el pipeline se haya ejecutado, podrás ver el estado de cada etapa (Build, Test). Si todo sale bien, tu pipeline se completará exitosamente.</p>
</li>
<li><p>Si alguna de las etapas falla (por ejemplo, en las pruebas), Jenkins te mostrará los logs detallados para que puedas identificar y corregir el error.</p>
</li>
</ul>
<blockquote>
<h4 id="heading-que-hace-este-pipeline"><strong>¿Qué hace este pipeline?</strong></h4>
<ul>
<li>Este pipeline no está haciendo realmente una compilación o ejecutando pruebas reales, pero es un buen punto de partida. Lo importante aquí es que ya estás viendo cómo se estructura un pipeline en Jenkins.</li>
</ul>
</blockquote>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">También puedes seguir este tutorial de <a target="_self" href="https://www.jenkins.io/doc/pipeline/tour/hello-world/">Hola Mundo Jenkins</a></div>
</div>

<hr />
<h2 id="heading-tip-importante-para-docker"><strong>Tip Importante para Docker:</strong></h2>
<p>Recuerden usar el parámetro <code>restart: always</code> cuando configuren Jenkins en Docker. Esto es crucial, ya que si instalas plugins o realizas cambios en la configuración, Jenkins necesitará reiniciarse. Si no tienes este parámetro configurado, tu contenedor no se reiniciará automáticamente y tendrás que hacerlo manualmente cada vez que actualices Jenkins o añadas nuevos plugins.</p>
<p>Por ejemplo, al ejecutar Jenkins en Docker, usa el siguiente comando para asegurarte de que el contenedor se reinicie automáticamente:</p>
<pre><code class="lang-bash">docker run -p 8080:8080 -p 50000:50000 -d --name jenkins --restart=always jenkins/jenkins:alpine
</code></pre>
<p>Este pequeño ajuste te ahorrará mucho tiempo y asegurará que Jenkins se reinicie correctamente tras cualquier cambio importante, como la instalación de plugins o actualizaciones.</p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9cuzi36hq6ewdi16pv51.png" alt="Itfine" class="image--center mx-auto" /></p>
<p><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4t34j9sf4nx9orqlcdol.png" alt="jen" /></p>
<hr />
<h2 id="heading-resumen-de-la-instalacion-con-ubuntu">Resumen de la instalación con Ubuntu</h2>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Siempre atento a la documentación oficial <a target="_self" href="https://www.jenkins.io/doc/book/installing/linux/">Jenkins</a></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746291456467/ff7359bd-3821-45c9-98d9-870a8f2c59e0.gif" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-bonus-track-curso-gratuito-de-jenkins-aprende-desde-cero"><strong>Bonus Track: Curso Gratuito de Jenkins - ¡Aprende desde Cero! 🚀</strong></h2>
<p>Si estás listo para dar el siguiente paso y profundizar aún más en Jenkins, te recomiendo este <strong>curso gratuito</strong> ofrecido por la <strong>Linux Foundation</strong>. Se llama <em>Introduction to Jenkins (LFS167)</em> y está diseñado para enseñarte todo lo que necesitas saber para implementar flujos de trabajo de <strong>Integración Continua (CI)</strong> y <strong>Entrega Continua (CD)</strong> utilizando Jenkins. 💻🔧</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746291112812/e8120fd3-f5ba-4919-8047-f786dcd189dc.png" alt class="image--center mx-auto" /></p>
<p><strong>¿Quién debería tomar este curso?</strong><br />Este curso es ideal para equipos que estén considerando usar Jenkins como herramienta CI/CD y busquen automatizar su proceso de entrega de software. También es perfecto para quienes necesiten pautas sobre cómo configurar un flujo de trabajo de CI/CD usando el servidor de automatización Jenkins.</p>
<p><strong>Lo que aprenderás:</strong></p>
<ul>
<li><p><strong>El rol de Jenkins en el ciclo de vida del desarrollo de software.</strong></p>
</li>
<li><p>Cómo configurar y acceder al servidor de automatización Jenkins.</p>
</li>
<li><p>Cómo construir tu software configurando y ejecutando varios tipos de proyectos Jenkins.</p>
</li>
<li><p>Instalación y gestión de plugins.</p>
</li>
<li><p>Cómo escalar y asegurar Jenkins.</p>
</li>
</ul>
<p><strong>¿Qué te preparará para hacer?</strong><br />Al completar este curso, tendrás una comprensión sólida de:</p>
<ul>
<li><p>El papel de Jenkins en CI/CD.</p>
</li>
<li><p>Cómo instalar Jenkins y gestionar proyectos.</p>
</li>
<li><p>Integración con terceros mediante plugins.</p>
</li>
<li><p>Cómo asegurar y escalar Jenkins para grandes proyectos.</p>
</li>
</ul>
<p>Este curso te proporcionará todas las herramientas necesarias para convertirte en un experto en Jenkins y llevar tus pipelines al siguiente nivel. Además, es completamente gratuito. 🎓</p>
<p>Puedes <strong>comenzar el curso aquí</strong>:<br /><a target="_blank" href="https://training.linuxfoundation.org/training/introduction-to-jenkins-lfs167/"><strong>Introducción a Jenkins (LFS167)</strong></a></p>
<p>¡No pierdas la oportunidad de mejorar tus habilidades en CI/CD con Jenkins! 🌟</p>
<hr />
<h2 id="heading-conclusion"><strong>Conclusión:</strong></h2>
<p>Aunque todo esto pueda parecer complejo al principio, la magia de Jenkins está en la automatización. ¡No más scripts manuales, no más errores humanos! Jenkins facilita todo el proceso de desarrollo y despliegue, y lo mejor es que puedes empezar a trabajar con él en minutos.</p>
<p>La CI/CD no es solo para grandes empresas, es para cualquier desarrollador que quiera llevar su proceso de entrega de software al siguiente nivel. ¡Anímate a probar Jenkins y a ver cómo mejora tu flujo de trabajo!</p>
<hr />
<h2 id="heading-mantente-onfire"><strong>¡Mantente Onfire! 🔥</strong></h2>
<p>Si te ha gustado este tutorial, ¡espera la parte II de "CI/CD The Series" sobre Jenkins! Mientras tanto, puedes seguirme en mis redes sociales para mantenerte al día con todo lo relacionado a DevOps, RoxsOps y CI/CD.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746287442138/2f105e84-d0e6-4feb-8422-1d24e5923eb5.png" alt class="image--center mx-auto" /></p>
<p><strong>Sígueme en:</strong></p>
<ul>
<li><p><strong>GitHub:</strong> <a target="_blank" href="https://github.com/roxsross">https://github.com/roxsross</a></p>
</li>
<li><p><strong>LinkedIn:</strong> <a target="_blank" href="https://www.linkedin.com/in/roxsross/">https://www.linkedin.com/in/roxsross/</a></p>
</li>
<li><p><strong>Linktree:</strong> <a target="_blank" href="https://roxs.295devops.com">https://roxs.295devops.com</a></p>
</li>
</ul>
<p>¡Hasta la próxima! 💪🚀</p>
]]></content:encoded></item><item><title><![CDATA[Despliega tu Primer Contenedor Docker con Terraform]]></title><description><![CDATA[En este blog, te guiaré paso a paso para desplegar un contenedor Docker utilizando Terraform con la imagen base nginx:alpine. Además, aprenderás a gestionar un archivo index.html que se mostrará en el contenedor Nginx con un mensaje personalizado: "B...]]></description><link>https://blog.295devops.com/despliega-tu-primer-contenedor-docker-con-terraform</link><guid isPermaLink="true">https://blog.295devops.com/despliega-tu-primer-contenedor-docker-con-terraform</guid><category><![CDATA[Devops]]></category><category><![CDATA[Terraform]]></category><category><![CDATA[#IaC]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 03 May 2025 01:48:04 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746233279802/5a701ba0-d042-4851-808f-bb19f5a08d0e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>En este blog, te guiaré paso a paso para desplegar un contenedor Docker utilizando <strong>Terraform</strong> con la imagen base <code>nginx:alpine</code>. Además, aprenderás a gestionar un archivo <code>index.html</code> que se mostrará en el contenedor Nginx con un mensaje personalizado: <em>"Bienvenido al workshop de Terraform by Roxs"</em>. Este es un excelente punto de partida para quienes quieren comenzar a automatizar la gestión de contenedores y aprender a usar Terraform en sus proyectos de DevOps.</p>
<h2 id="heading-requisitos-previos"><strong>Requisitos previos</strong></h2>
<p>Para seguir este tutorial, asegúrate de tener lo siguiente instalado:</p>
<ol>
<li><p><strong>Terraform</strong>: Si aún no lo tienes instalado, puedes seguir las instrucciones de instalación <a target="_blank" href="https://learn.hashicorp.com/tutorials/terraform/install-cli">aquí</a>.</p>
</li>
<li><p><strong>Docker</strong>: Para crear y gestionar contenedores, instala Docker desde <a target="_blank" href="https://docs.docker.com/get-docker/">aquí</a>.</p>
</li>
<li><p><strong>Conexión a Docker</strong>: Asegúrate de tener Docker en funcionamiento en tu máquina local para poder usarlo con Terraform.</p>
</li>
<li><p><strong>Provider Docker</strong>: El proveedor Docker se utiliza para interactuar con contenedores e imágenes Docker. <a target="_blank" href="https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs">Aquí</a></p>
</li>
</ol>
<p>Si ya tienes estos programas instalados, <strong>¡estás listo para comenzar!</strong></p>
<h2 id="heading-paso-1-preparacion-del-entorno-de-terraform"><strong>Paso 1: Preparación del entorno de Terraform</strong></h2>
<p>Lo primero es crear un archivo de configuración en <strong>Terraform</strong>. En este archivo, definiremos dos recursos principales:</p>
<ul>
<li><p>El <strong>provider Docker</strong> para conectarnos a tu instalación local de Docker.</p>
</li>
<li><p>El <strong>provider local</strong> para gestionar archivos locales, como el archivo <code>index.html</code> que se usará en el contenedor.</p>
</li>
<li><p><strong>El recurso</strong> <code>data "local_file"</code> para referirnos al archivo <code>index.html</code> ya existente en el directorio.</p>
</li>
</ul>
<h3 id="heading-archivo-indexhtml"><strong>Archivo</strong> <code>index.html</code></h3>
<div class="gist-block embed-wrapper" data-gist-show-loading="false" data-id="6b95cfaf4828952a8cc7c34da5deb7c3"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a href="https://gist.github.com/roxsross/6b95cfaf4828952a8cc7c34da5deb7c3" class="embed-card">https://gist.github.com/roxsross/6b95cfaf4828952a8cc7c34da5deb7c3</a></div><p> </p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>Index.html</strong> generado con la IA claude3</div>
</div>

<h3 id="heading-archivo-maintf"><strong>Archivo</strong> <code>main.tf</code></h3>
<pre><code class="lang-yaml"><span class="hljs-string">terraform</span> {
  <span class="hljs-string">required_providers</span> {
    <span class="hljs-string">docker</span> <span class="hljs-string">=</span> {
      <span class="hljs-string">source</span> <span class="hljs-string">=</span> <span class="hljs-string">"kreuzwerker/docker"</span>
      <span class="hljs-string">version</span> <span class="hljs-string">=</span> <span class="hljs-string">"3.4.0"</span>
    }
  }
}

<span class="hljs-string">provider</span> <span class="hljs-string">"docker"</span> {
}

<span class="hljs-string">provider</span> <span class="hljs-string">"local"</span> {}

<span class="hljs-string">data</span> <span class="hljs-string">"local_file"</span> <span class="hljs-string">"index_html"</span> {
  <span class="hljs-string">filename</span> <span class="hljs-string">=</span> <span class="hljs-string">"${path.module}/index.html"</span>
}

<span class="hljs-string">resource</span> <span class="hljs-string">"docker_container"</span> <span class="hljs-string">"web"</span> {
  <span class="hljs-string">name</span>  <span class="hljs-string">=</span> <span class="hljs-string">"nginx-terraform"</span>
  <span class="hljs-string">image</span> <span class="hljs-string">=</span> <span class="hljs-string">"nginx:latest"</span>

  <span class="hljs-string">ports</span> {
    <span class="hljs-string">internal</span> <span class="hljs-string">=</span> <span class="hljs-number">80</span>
    <span class="hljs-string">external</span> <span class="hljs-string">=</span> <span class="hljs-number">8080</span>
  }

  <span class="hljs-string">upload</span> {
    <span class="hljs-string">file</span>    <span class="hljs-string">=</span> <span class="hljs-string">"/usr/share/nginx/html/index.html"</span>
    <span class="hljs-string">content</span> <span class="hljs-string">=</span> <span class="hljs-string">data.local_file.index_html.content</span>
  }
}

<span class="hljs-string">output</span> <span class="hljs-string">"container_name"</span> {
  <span class="hljs-string">value</span> <span class="hljs-string">=</span> <span class="hljs-string">docker_container.web.name</span>
}
<span class="hljs-string">output</span> <span class="hljs-string">"container_id"</span> {
  <span class="hljs-string">value</span> <span class="hljs-string">=</span> <span class="hljs-string">docker_container.web.id</span>
  <span class="hljs-string">description</span> <span class="hljs-string">=</span> <span class="hljs-string">"ID del contenedor Nginx"</span>
}
<span class="hljs-string">output</span> <span class="hljs-string">"container_image"</span> {
  <span class="hljs-string">value</span> <span class="hljs-string">=</span> <span class="hljs-string">docker_container.web.image</span>
  <span class="hljs-string">description</span> <span class="hljs-string">=</span> <span class="hljs-string">"Imagen del contenedor Nginx"</span>
}


<span class="hljs-string">output</span> <span class="hljs-string">"nginx_access_url"</span> {
  <span class="hljs-string">value</span> <span class="hljs-string">=</span> <span class="hljs-string">"http://localhost:8080"</span>
  <span class="hljs-string">description</span> <span class="hljs-string">=</span> <span class="hljs-string">"URL para acceder al servidor Nginx"</span>
}
</code></pre>
<h3 id="heading-explicacion-del-codigo"><strong>Explicación del código</strong>:</h3>
<ol>
<li><p><code>provider "docker"</code>: Configura la conexión con tu máquina local de Docker.</p>
</li>
<li><p><code>provider "local"</code>: Configura el uso de archivos locales. Aquí, lo utilizamos para referirnos al archivo <code>index.html</code> que ya existe en tu sistema.</p>
</li>
<li><p><code>data "local_file" "index_html"</code>: Este recurso se utiliza para referirse a un archivo local existente. El archivo <code>index.html</code> contendrá el mensaje que se mostrará cuando accedas a tu contenedor.</p>
</li>
<li><p><code>docker_container "web"</code>: Crea el contenedor usando la imagen <code>nginx:alpine</code> y sube el archivo <code>index.html</code> al contenedor en la ruta <code>/usr/share/nginx/html/</code>.</p>
</li>
</ol>
<h2 id="heading-paso-2-inicializacion-y-validacion-de-terraform"><strong>Paso 2: Inicialización y Validación de Terraform</strong></h2>
<p>Una vez que tengas el archivo <a target="_blank" href="http://main.tf"><code>main.tf</code></a> listo, puedes proceder con los siguientes pasos:</p>
<ol>
<li><p><strong>Inicializar el entorno de Terraform</strong>: Este comando descarga los proveedores necesarios y prepara el entorno de trabajo.</p>
<pre><code class="lang-yaml"> <span class="hljs-string">terraform</span> <span class="hljs-string">init</span>
</code></pre>
</li>
<li><p><strong>Validar la configuración de Terraform</strong>: Este paso verifica que la configuración de Terraform sea correcta y no haya errores en el archivo de configuración.</p>
<pre><code class="lang-yaml"> <span class="hljs-string">terraform</span> <span class="hljs-string">validate</span>
</code></pre>
</li>
<li><p><strong>Formatear el código de Terraform</strong>: Antes de aplicar la configuración, puedes formatear tu archivo <a target="_blank" href="http://main.tf"><code>main.tf</code></a> para que siga las mejores prácticas de estilo de código.</p>
<pre><code class="lang-yaml"> <span class="hljs-string">terraform</span> <span class="hljs-string">fmt</span>
</code></pre>
</li>
<li><p><strong>Generar un plan de ejecución</strong>: Este comando te muestra el plan de lo que Terraform va a hacer. Verás los recursos que se van a crear, modificar o eliminar.</p>
<pre><code class="lang-yaml"> <span class="hljs-string">terraform</span> <span class="hljs-string">plan</span>
</code></pre>
<p> Esto es útil para confirmar que todo está bien antes de aplicar los cambios.</p>
</li>
<li><p><strong>Aplicar la configuración</strong>: Si todo está correcto, ejecuta el siguiente comando para crear los recursos y desplegar el contenedor Docker.</p>
<pre><code class="lang-yaml"> <span class="hljs-string">terraform</span> <span class="hljs-string">apply</span>
</code></pre>
<p> Terraform te pedirá que confirmes antes de proceder. Si todo está bien, escribe <code>yes</code> para confirmar.</p>
</li>
</ol>
<h2 id="heading-paso-3-ver-el-contenedor-en-ejecucion"><strong>Paso 3: Ver el contenedor en ejecución</strong></h2>
<p>Una vez que Terraform haya terminado de crear el contenedor, podrás acceder a él desde tu navegador. Abre un navegador y navega a:</p>
<pre><code class="lang-yaml"><span class="hljs-string">http://localhost:8080</span>
</code></pre>
<p>Verás la página:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746232597929/efc4cd69-894b-4dcd-8770-40fcab511bbf.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-comprobacion-del-contenedor-docker"><strong>Comprobación del contenedor Docker</strong>:</h3>
<p>Si quieres asegurarte de que el contenedor está funcionando correctamente, puedes ejecutar el siguiente comando para ver los contenedores activos:</p>
<pre><code class="lang-bash">docker ps
</code></pre>
<p>Esto mostrará el contenedor <code>terraform-web</code> en ejecución en el puerto 8080.</p>
<h2 id="heading-paso-4-limpiar-los-recursos"><strong>Paso 4: Limpiar los recursos</strong></h2>
<p>Si ya no necesitas el contenedor y deseas liberar los recursos, puedes destruir todo lo creado con Terraform ejecutando:</p>
<pre><code class="lang-bash">terraform destroy
</code></pre>
<p>Esto eliminará tanto el contenedor como el archivo <code>index.html</code> y cualquier otro recurso que Terraform haya creado.</p>
<hr />
<h2 id="heading-paso-a-paso">Paso a paso</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746236811921/0158010c-5396-46e2-bc02-b888f835b075.gif" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-proximos-pasos-mejorando-la-estructura-de-tu-proyecto-de-terraform"><strong>Próximos Pasos: Mejorando la Estructura de tu Proyecto de Terraform</strong></h2>
<p>Una vez que hayas trabajado con este ejemplo básico, puedes mejorar la estructura de tu proyecto de Terraform para hacerlo más modular, eficiente y fácil de mantener. Aquí te doy algunas recomendaciones para organizar y escalar tu infraestructura con Terraform:</p>
<h3 id="heading-1-uso-de-archivos-de-configuracion-separados"><strong>1. Uso de archivos de configuración separados</strong></h3>
<p>Para mantener tu proyecto organizado, puedes separar diferentes aspectos de tu infraestructura en varios archivos de configuración. Por ejemplo, puedes tener:</p>
<ul>
<li><p><a target="_blank" href="http://variables.tf"><code>variables.tf</code></a>: Para definir variables que se utilizarán en tu configuración.</p>
</li>
<li><p><a target="_blank" href="http://outputs.tf"><code>outputs.tf</code></a>: Para definir los outputs que necesitas mostrar después de aplicar la configuración.</p>
</li>
<li><p><a target="_blank" href="http://main.tf"><code>main.tf</code></a>: Donde se define la mayoría de los recursos de infraestructura.</p>
</li>
</ul>
<p>Esto ayuda a mantener tu proyecto limpio y más fácil de modificar, especialmente cuando trabajas en proyectos más grandes.</p>
<h3 id="heading-2-gestionar-valores-con-variables"><strong>2. Gestionar valores con variables</strong></h3>
<p>Es recomendable utilizar <strong>variables</strong> en lugar de codificar valores directamente en tu archivo <a target="_blank" href="http://main.tf"><code>main.tf</code></a>. De esta forma, puedes reutilizar los mismos valores en diferentes partes de tu configuración y cambiar los valores sin modificar directamente el código.</p>
<p>Ejemplo de un archivo <a target="_blank" href="http://variables.tf"><code>variables.tf</code></a>:</p>
<pre><code class="lang-yaml"><span class="hljs-string">variable</span> <span class="hljs-string">"container_name"</span> {
  <span class="hljs-string">type</span>    <span class="hljs-string">=</span> <span class="hljs-string">string</span>
  <span class="hljs-string">default</span> <span class="hljs-string">=</span> <span class="hljs-string">"terraform-web"</span>
}

<span class="hljs-string">variable</span> <span class="hljs-string">"nginx_image"</span> {
  <span class="hljs-string">type</span>    <span class="hljs-string">=</span> <span class="hljs-string">string</span>
  <span class="hljs-string">default</span> <span class="hljs-string">=</span> <span class="hljs-string">"nginx:alpine"</span>
}
</code></pre>
<p>Y luego referenciar estas variables en tu <a target="_blank" href="http://main.tf"><code>main.tf</code></a>:</p>
<pre><code class="lang-yaml"><span class="hljs-string">resource</span> <span class="hljs-string">"docker_container"</span> <span class="hljs-string">"web"</span> {
  <span class="hljs-string">image</span> <span class="hljs-string">=</span> <span class="hljs-string">var.nginx_image</span>
  <span class="hljs-string">name</span>  <span class="hljs-string">=</span> <span class="hljs-string">var.container_name</span>
}
</code></pre>
<h3 id="heading-3-uso-de-backends-remotos-para-gestionar-el-estado"><strong>3. Uso de backends remotos para gestionar el estado</strong></h3>
<p>Si trabajas en equipo o tienes múltiples entornos, es importante usar un <strong>backend remoto</strong> para gestionar el estado de Terraform. Usar backends como <strong>S3</strong> o <strong>Terraform Cloud</strong> te permite almacenar el estado de manera centralizada, evitando problemas de inconsistencia cuando varias personas o sistemas interactúan con la infraestructura.</p>
<h3 id="heading-4-planificacion-y-validacion-constante"><strong>4. Planificación y validación constante</strong></h3>
<p>Recuerda siempre ejecutar el comando <code>terraform plan</code> antes de aplicar cambios en producción. Esto te permite visualizar los cambios que Terraform va a hacer y evita sorpresas.</p>
<hr />
<h3 id="heading-genera-tu-propio-proyecto-con-ia"><strong>Genera tu propio proyecto con IA</strong></h3>
<p>Si quieres crear tu propio entorno de Terraform y Docker, puedes usar este <strong>prompt</strong> para generar el código:</p>
<p><strong>Prompt:</strong></p>
<p>"Crear un contenedor Docker utilizando Terraform con la imagen <code>nginx:alpine</code>, donde se suba un archivo <code>index.html</code> con un mensaje personalizado. Utilizar los proveedores <code>docker</code> version 3.4.0 y <code>local</code> de Terraform para gestionar el contenedor y el archivo local. Asegúrate de que el contenedor exponga el puerto 8080 y muestre el contenido del archivo <code>index.html</code> cuando se acceda desde un navegador. Además, configura outputs para mostrar el nombre, y los puertos del contenedor después de aplicarlo."</p>
<hr />
<h2 id="heading-conclusion"><strong>Conclusión</strong></h2>
<p>En este tutorial, aprendiste a desplegar un contenedor Docker utilizando Terraform con la imagen <code>nginx:alpine</code> y a montar un archivo <code>index.html</code> con un mensaje personalizado. Esta es una excelente forma de comenzar a trabajar con Terraform y Docker, dos herramientas poderosas que te permiten automatizar la infraestructura y mejorar tu flujo de trabajo en DevOps.</p>
<hr />
<h2 id="heading-recursos-adicionales"><strong>Recursos adicionales</strong></h2>
<p>Si deseas profundizar más en Terraform y Docker, te dejo algunos recursos útiles:</p>
<ul>
<li><p><a target="_blank" href="https://developer.hashicorp.com/terraform/docs">Documentación de Terraform</a></p>
</li>
<li><p><a target="_blank" href="https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs">Docker Provider de Terraform</a></p>
</li>
<li><p><a target="_blank" href="https://docs.docker.com/">Documentación oficial de Docker</a></p>
</li>
</ul>
<hr />
<p>Recuerda, cada paso que des te acerca más a dominar la infraestructura como código. No importa si estás comenzando o si ya tienes experiencia, lo importante es seguir aprendiendo y explorando nuevas herramientas. ¡Lo mejor de todo es que nunca es tarde para empezar a transformar tu forma de trabajar con la tecnología! 🌟</p>
<hr />
<h2 id="heading-sigueme-en-redes-sociales"><strong>Sígueme en Redes Sociales</strong></h2>
<p>Si te ha gustado este tutorial y quieres seguir aprendiendo sobre DevOps, Terraform, Docker y más, no dudes en seguirme en mis redes sociales:</p>
<ul>
<li><p><strong>Twitter</strong>: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p><strong>LinkedIn</strong>: <a target="_blank" href="https://www.linkedin.com/in/rossana-suarez/">Rossana Suarez</a></p>
</li>
<li><p><strong>YouTube</strong>: <a target="_blank" href="https://www.youtube.com/channel/UCyJBO9So_cD_zQihqvv_8wQ">295devops</a></p>
</li>
<li><p><strong>Instagram</strong>: <a target="_blank" href="https://www.instagram.com/roxsross/">@roxsross</a></p>
</li>
</ul>
<hr />
<p><strong>¡No olvides compartir este post con tu comunidad!</strong> 💬 Si tienes dudas o sugerencias, ¡déjalas en los comentarios! Juntos seguimos aprendiendo y creciendo. 🚀</p>
]]></content:encoded></item><item><title><![CDATA[20 Trucos de IA para Dominar tu Flujo de Trabajo DevOps y Acelerar Resultados]]></title><description><![CDATA[En el mundo acelerado de DevOps, el tiempo es siempre un factor limitante. Cuando trabajas con infraestructuras complejas, diagnosticar fallos y lidiar con tareas repetitivas puede ser abrumador. Pero, ¿y si pudieras aprovechar la inteligencia artifi...]]></description><link>https://blog.295devops.com/20-trucos-de-ia-para-dominar-tu-flujo-de-trabajo-devops-y-acelerar-resultados</link><guid isPermaLink="true">https://blog.295devops.com/20-trucos-de-ia-para-dominar-tu-flujo-de-trabajo-devops-y-acelerar-resultados</guid><category><![CDATA[Devops]]></category><category><![CDATA[AI]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Fri, 02 May 2025 15:38:57 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746195123356/c632622b-83fa-4d0a-9cd2-a166fd51bc7a.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>En el mundo acelerado de DevOp</strong>s, el tiempo es siempre un factor limitante. Cuando trabajas con infraestructuras complejas, diagnosticar fallos y lidiar con tareas repetitivas puede ser abrumador. Pero, ¿y si pudieras aprovechar la inteligencia artificial (IA) para agilizar tu trabajo y aumentar tu productividad? No es un sueño, es una posibilidad real. <strong>Aprendiendo a utilizar los prompts adecuados, los DevOps pueden automatizar tareas, diagnosticar problemas y mejorar la eficiencia del flujo de trabajo</strong>.</p>
<p>Herramientas como <strong><mark>Amazon Q CLI, ChatGPT, Claude, DeepSeek y GitHub Copilot</mark></strong> están aquí para transformar la forma en que trabajas. Al aprender a utilizar los prompts adecuados, los <strong>DevOps</strong> pueden automatizar tareas, diagnosticar problemas y optimizar la eficiencia en sus flujos de trabajo.</p>
<p>En este artículo, <strong><mark>te comparto 20 prompts de IA altamente efectivos que pueden transformar la forma en que enfrentas los desafíos comunes de DevOps</mark></strong>. Estas fórmulas prácticas, probadas en el campo, han ahorrado incontables horas, simplificado la depuración y ayudado a los equipos a cumplir sus plazos de manera más eficiente. <strong>¡Vamos a ver cómo la IA puede potenciar tu flujo de trabajo!</strong></p>
<p><img src="https://pbs.twimg.com/media/Go0wjgYXsAAwAZv?format=jpg&amp;name=small" alt="Imagen" class="image--center mx-auto" /></p>
<h3 id="heading-1-soluciona-errores-en-el-pipeline-cicd-rapidamente">1. <strong>Soluciona Errores en el Pipeline CI/CD Rápidamente</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Analiza este error de pipeline CI/CD y sugiere soluciones:<br />[Pega los logs de error]<br />Contexto:</p>
<ul>
<li><p>Sistema CI/CD: GitLab</p>
</li>
<li><p>Aplicación: Node.js</p>
</li>
<li><p>Las pruebas pasan localmente pero fallan en el pipeline después de una actualización de dependencias."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-2-genera-documentacion-clara-de-infraestructura">2. <strong>Genera Documentación Clara de Infraestructura</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera documentación para esta infraestructura:</p>
<ul>
<li><p>Componentes: [Lista de servicios, dependencias]</p>
</li>
<li><p>Incluir: Visión general arquitectónica, componentes clave, flujo de datos, consideraciones de seguridad, puntos de fallo comunes."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-3-escribe-scripts-para-tareas-repetitivas">3. <strong>Escribe Scripts para Tareas Repetitivas</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Escribe un script bash que:</p>
<ul>
<li><p>Respaldos de bases de datos MySQL</p>
</li>
<li><p>Comprime los respaldos</p>
</li>
<li><p>Los sube a S3</p>
</li>
<li><p>Elimina respaldos mayores de 5 días</p>
</li>
<li><p>Envia un correo de estado con los logs de éxito/error."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-4-optimiza-las-reglas-de-monitoreo-y-alertas">4. <strong>Optimiza las Reglas de Monitoreo y Alertas</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Optimiza las reglas de alertas de Prometheus:</p>
<ul>
<li><p>Problemas actuales: falsos positivos para picos de CPU, alertas faltantes para problemas de conexión a bases de datos.</p>
</li>
<li><p>Entorno: Kubernetes, microservicios en Go/Java, PostgreSQL/Redis."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-5-genera-codigo-terraform-para-infraestructura">5. <strong>Genera Código Terraform para Infraestructura</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera la configuración de Terraform para infraestructura AWS:</p>
<ul>
<li>S3 + CloudFront para recursos estáticos”</li>
</ul>
<p><strong><mark>Opción compleja:</mark></strong></p>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera la configuración de Terraform para infraestructura AWS:</p>
<ul>
<li><p>Tier web balanceado en dos zonas de disponibilidad</p>
</li>
<li><p>Tier de aplicación con autoescalado y réplicas de lectura de RDS</p>
</li>
<li><p>S3 + CloudFront para recursos estáticos</p>
</li>
<li><p>Grupos de seguridad e IAM adecuados."</p>
</li>
</ul>
</blockquote>
</blockquote>
<h3 id="heading-6-diagnostica-problemas-de-kubernetes-al-instante">6. <strong>Diagnostica Problemas de Kubernetes al Instante</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Diagnostica el siguiente problema de Kubernetes:</p>
<ul>
<li><p>Síntomas: Los Pods se caen continuamente y se reinician</p>
</li>
<li><p>Logs de error: [pegar logs relevantes]</p>
</li>
<li><p>Entorno: AWS EKS Kubernetes 1.30</p>
</li>
<li><p>Qué he probado: Reiniciar despliegues, revisar presión de CPU/memoria."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-7-crea-runbooks-para-respuestas-a-incidentes">7. <strong>Crea Runbooks para Respuestas a Incidentes</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Crea un runbook de respuesta a incidentes para fallos de base de datos Postgres:</p>
<ul>
<li>Incluir: Pasos de evaluación, causas comunes, procedimientos de recuperación, escalación, análisis post-incidente."</li>
</ul>
</blockquote>
<h3 id="heading-8-analiza-vulnerabilidades-de-seguridad-rapidamente">8. <strong>Analiza Vulnerabilidades de Seguridad Rápidamente</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Analiza la vulnerabilidad CVE-2023-XXXXX para nuestro entorno:</p>
<ul>
<li><p>Entorno: 2 microservicios (Node.js 20), Kubernetes, APIs expuestas detrás de Cloudflare.</p>
</li>
<li><p>Proveer: Evaluación de exposición, servicios afectados, pasos inmediatos de mitigación, plan de remediación a largo plazo."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-9-optimiza-los-costos-en-la-nube-con-ia">9. <strong>Optimiza los Costos en la Nube con IA</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Analiza la asignación de costos en AWS y sugiere optimizaciones:</p>
<ul>
<li>Uso: Entornos de desarrollo 24/7, procesamiento nocturno, picos de tráfico, instancias EC2 infrautilizadas."</li>
</ul>
</blockquote>
<h3 id="heading-10-escribe-postmortems-sin-culpas">10. <strong>Escribe Postmortems sin Culpas</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Ayúdame a escribir un postmortem sin culpas para este incidente:</p>
<ul>
<li><p>Detalles: Disrupción de servicio de 4 horas en sistema de procesamiento de pagos</p>
</li>
<li><p>Causa raíz: Agotamiento del pool de conexiones a base de datos</p>
</li>
<li><p>Factores contribuyentes: Picos de tráfico, monitoreo insuficiente</p>
</li>
<li><p>Resolución: Aumento del tamaño del pool, se agregaron cortafuegos."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-11-automatiza-la-creacion-de-tickets-de-incidente">11. <strong>Automatiza la Creación de Tickets de Incidente</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Crea un ticket de incidente para el equipo de soporte:</p>
<ul>
<li><p>Incidente: Fallo en la base de datos</p>
</li>
<li><p>Impacto: 4 horas de inactividad en producción</p>
</li>
<li><p>Causa raíz: Conexión al servicio de la base de datos no disponible</p>
</li>
<li><p>Resolución: Reinicio del servicio y ajuste de la configuración."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-12-genera-un-plan-de-continuidad-del-negocio">12. <strong>Genera Un Plan de Continuidad del Negocio</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera un plan de continuidad del negocio para nuestros servicios en la nube:</p>
<ul>
<li><p>Entorno: AWS, microservicios en Kubernetes</p>
</li>
<li><p>Incluir: Estrategias de recuperación ante desastres, planes de redundancia y backups."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-13-revisa-y-mejora-la-configuracion-de-seguridad-en-aws">13. <strong>Revisa y Mejora la Configuración de Seguridad en AWS</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Revisa la configuración de seguridad de nuestra infraestructura AWS:</p>
<ul>
<li><p>Entorno: EKS, RDS, S3, IAM</p>
</li>
<li><p>Sugerir mejoras en las políticas de IAM, encriptación de datos y controles de acceso."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-14-automatiza-la-gestion-de-configuraciones-con-ansible">14. <strong>Automatiza la Gestión de Configuraciones con Ansible</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Escribe un playbook de Ansible para configurar:</p>
<ul>
<li><p>Servidor web Nginx en Ubuntu 22.04</p>
</li>
<li><p>Instalar y configurar Git, Docker, Node.js y PostgreSQL."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-15-mejora-la-gestion-de-logs-en-el-sistema">15. <strong>Mejora la Gestión de Logs en el Sistema</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Mejora la configuración de gestión de logs en Kubernetes:</p>
<ul>
<li><p>Entorno: EKS, Fluentd, Elasticsearch y Kibana</p>
</li>
<li><p>Sugerir mejoras en la retención de logs, agregación y visualización."</p>
</li>
</ul>
</blockquote>
<h3 id="heading-16-configura-alertas-personalizadas-en-slack">16. <strong>Configura Alertas Personalizadas en Slack</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Crea una alerta personalizada para los errores de la base de datos:</p>
<ul>
<li>Enviar una notificación a Slack con el mensaje de error y el nombre de la base de datos afectada cuando un servicio esté caído más de 5 minutos."</li>
</ul>
</blockquote>
<h3 id="heading-17-automatiza-el-despliegue-de-aplicaciones-con-helm">17. <strong>Automatiza el Despliegue de Aplicaciones con Helm</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera un archivo Helm para desplegar una aplicación web Node.js en Kubernetes:</p>
<ul>
<li>Incluir configuración para autoescalado, servicio de base de datos y despliegue de contenedores."</li>
</ul>
</blockquote>
<h3 id="heading-18-optimiza-la-configuracion-de-gitlab-cicd">18. <strong>Optimiza la Configuración de GitLab CI/CD</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Optimiza mi configuración de GitLab CI/CD:</p>
<ul>
<li>Incluir pipelines paralelos, caching adecuado y estrategias de despliegue para mejorar la velocidad y reducir el tiempo de ejecución."</li>
</ul>
</blockquote>
<h3 id="heading-19-automatiza-la-revision-de-codigo-con-herramientas-de-ia">19. <strong>Automatiza la Revisión de Código con Herramientas de IA</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Automatiza la revisión de código con herramientas como SonarQube:</p>
<ul>
<li>Incluir reglas personalizadas para detectar vulnerabilidades y malas prácticas en el código."</li>
</ul>
</blockquote>
<h3 id="heading-20-gestiona-el-versionado-de-api-de-forma-automatica">20. <strong>Gestiona el Versionado de API de Forma Automática</strong></h3>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera una estrategia de versionado de API utilizando OpenAPI y Swagger:</p>
<ul>
<li>Incluir control de versiones, cambios de endpoint y estrategia de migración."</li>
</ul>
</blockquote>
<hr />
<h2 id="heading-probemos-los-prompt">Probemos los prompt:</h2>
<h3 id="heading-soluciona-errores-en-el-pipeline-cicd-rapidamente"><strong><mark>Soluciona Errores en el Pipeline CI/CD Rápidamente:</mark></strong></h3>
<h3 id="heading-asistente-de-ia-claudehttpsclaudeainew"><strong><mark>Asistente de IA: </mark></strong> <a target="_blank" href="https://claude.ai/new"><strong><mark>Claude</mark></strong></a></h3>
<p>"Analiza el siguiente error de pipeline CI/CD y sugiere soluciones:</p>
<p>Contexto:</p>
<ul>
<li><p><strong>Sistema CI/CD:</strong> GitLab</p>
</li>
<li><p><strong>Aplicación:</strong> SonarQube</p>
</li>
<li><p><strong>Comando ejecutado:</strong></p>
</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-string">$</span> <span class="hljs-string">sonar-scanner</span> <span class="hljs-string">\</span>
<span class="hljs-string">-Dsonar.projectKey=my-project</span> <span class="hljs-string">\</span>
<span class="hljs-string">-Dsonar.sources=.</span> <span class="hljs-string">\</span>
<span class="hljs-string">-Dsonar.host.url=https://sonarqube.295devops.com/</span> <span class="hljs-string">\</span>
<span class="hljs-string">-Dsonar.login=xxxxxxxxxxx</span>
</code></pre>
<ul>
<li><strong>Error:</strong></li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-attr">ERROR: Unrecognized option:</span>  <span class="hljs-string">-Dsonar.sources=.</span>
<span class="hljs-attr">INFO:</span> 
<span class="hljs-attr">INFO: usage:</span> <span class="hljs-string">sonar-scanner</span> [<span class="hljs-string">options</span>]
<span class="hljs-attr">INFO: Options:</span>
<span class="hljs-string">-D,--define</span> <span class="hljs-string">&lt;arg&gt;</span>     <span class="hljs-string">Define</span> <span class="hljs-string">property</span>
<span class="hljs-string">-h,--help</span>             <span class="hljs-string">Display</span> <span class="hljs-string">help</span> <span class="hljs-string">information</span>
<span class="hljs-string">-v,--version</span>          <span class="hljs-string">Display</span> <span class="hljs-string">version</span> <span class="hljs-string">information</span>
<span class="hljs-string">-X,--debug</span>            <span class="hljs-string">Produce</span> <span class="hljs-string">execution</span> <span class="hljs-string">debug</span> <span class="hljs-string">output</span>
</code></pre>
<h3 id="heading-respuesta-de-claude"><strong><mark>Respuesta de Claude:</mark></strong></h3>
<p>Analizaré este error de pipeline CI/CD en GitLab con SonarQube y sugeriré soluciones adecuadas.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746196102726/9eb67408-c077-4a76-8255-9b1f03d8e687.png" alt /></p>
<h2 id="heading-analisis-del-error">Análisis del error</h2>
<p>El problema principal es que el comando de SonarQube está fallando con el error: <code>ERROR: Unrecognized option: -Dsonar.sources=.</code></p>
<p>Este error indica que la opción <code>-Dsonar.sources=.</code> no es reconocida por el ejecutable SonarQube que se está utilizando en el pipeline, a pesar de que funciona correctamente en el entorno local.</p>
<h2 id="heading-causas-probables">Causas probables</h2>
<ol>
<li><p><strong>Versión incompatible</strong>: Después de la actualización de dependencias, la versión de SonarQube Scanner en el pipeline podría ser diferente a la local.</p>
</li>
<li><p><strong>Sintaxis incorrecta</strong>: La forma de pasar parámetros puede haber cambiado en la nueva versión.</p>
</li>
<li><p><strong>Configuración de entorno</strong>: Posible conflicto entre variables de entorno o configuraciones predeterminadas.</p>
</li>
<li><p><strong>Permisos insuficientes</strong>: El usuario de CI podría no tener permisos adecuados para acceder a las fuentes.</p>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">(continúa con el análisis y las soluciones sugeridas).</div>
</div>

<hr />
<h3 id="heading-genera-codigo-terraform-para-infraestructura"><strong>Genera Código Terraform para Infraestructura</strong></h3>
<h3 id="heading-asistente-amazon-q-cli"><strong><mark>Asistente Amazon q cli</mark></strong></h3>
<p>Información sobre el asistente <a target="_blank" href="https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line.html">amazonq</a></p>
<p><strong>El Prompt:</strong></p>
<blockquote>
<p>"Genera la configuración de Terraform para infraestructura AWS:</p>
<ul>
<li>S3 + CloudFront para recursos estáticos”</li>
</ul>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746196268823/03532f1c-db35-42e0-9591-15494b602f2d.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-respuesta-de-amazon-q-cli"><mark>Respuesta de Amazon Q CLI</mark></h3>
<p>Te genera una salida en la terminal con el resultado</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746196354201/59c3a834-e517-4226-94c2-b38223a3833c.png" alt class="image--center mx-auto" /></p>
<p>… y ademas si te parece bien, apruebas y te genera el archivo main.tf</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746196494632/65c026a9-aad8-438b-92cb-f5a5dd81865e.png" alt class="image--center mx-auto" /></p>
<hr />
<h3 id="heading-optimiza-los-costos-en-la-nube-con-ia"><strong>Optimiza los Costos en la Nube con IA</strong></h3>
<h3 id="heading-asistente-chatgpt"><mark>Asistente ChatGPT</mark></h3>
<blockquote>
<p>"Analiza la asignación de costos en AWS y sugiere optimizaciones:</p>
<ul>
<li>Uso: Entornos de desarrollo 24/7, procesamiento nocturno, picos de tráfico, instancias EC2 infrautilizadas."</li>
</ul>
</blockquote>
<h3 id="heading-respuesta-de-chatgpt"><mark>Respuesta de ChatGPT:</mark></h3>
<p>Para analizar la asignación de costos en AWS y sugerir optimizaciones en el contexto de entornos de desarrollo 24/7, procesamiento nocturno, picos de tráfico y EC2 infrautilizadas, se deben considerar varias estrategias de optimización. Aquí te dejo un análisis y algunas recomendaciones:</p>
<h3 id="heading-analisis-de-la-situacion">Análisis de la situación:</h3>
<ol>
<li><p><strong>Entornos de desarrollo 24/7:</strong></p>
<ul>
<li><p>Los entornos de desarrollo en AWS que están activos constantemente pueden resultar costosos debido al uso continuo de instancias EC2, almacenamiento y otros recursos.</p>
</li>
<li><p>Las instancias EC2 en ejecución sin necesidad de estar siempre activas generan costos innecesarios.</p>
</li>
</ul>
</li>
</ol>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text"><strong>y continua …..</strong></div>
</div>

<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746196784814/10cfa6f1-3a4b-4bb1-b2ec-e73de5dc21a8.png" alt class="image--center mx-auto" /></p>
<hr />
<p><strong>¡Recuerda siempre validar las respuestas generadas por la IA!</strong> Aunque estas herramientas son poderosas, <strong>la supervisión</strong> sigue siendo esencial para garantizar que las soluciones sean apropiadas para tu entorno específico. Asegúrate de revisar los resultados, aplicar tu criterio y realizar ajustes cuando sea necesario.</p>
<p><img src="https://pbs.twimg.com/media/GoQvbmXWcAEpvAc?format=jpg&amp;name=small" alt="Imagen" class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-como-usar-la-ia-de-forma-responsable-en-devops">Cómo Usar la IA de Forma Responsable en DevOps</h2>
<p>Si bien estos prompts de IA pueden aumentar tu productividad, es importante considerar la privacidad y la seguridad de los datos. Siempre sanitiza los logs antes de compartirlos con herramientas de IA para proteger la información sensible, como claves de API o datos personales.</p>
<p><strong>Al integrar estos prompts de IA en tu flujo de trabajo DevOps</strong>, podrás resolver problemas complejos más rápido, automatizar tareas repetitivas y mejorar la eficiencia de tus procesos. <mark>La IA no reemplaza tu experiencia, pero ciertamente la amplifica, permitiéndote enfocarte en tareas de mayor nivel mientras ella se encarga del trabajo rutinario.</mark></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746198930074/072991b7-8cb5-4051-9550-c12e54f64609.png" alt class="image--center mx-auto" /></p>
<hr />
<p><strong>Si te ha parecido útil este contenido, no dudes en compartirlo con tu comunidad.</strong></p>
<p><strong>¡Sigue mis redes sociales para más consejos y recursos de DevOps!</strong></p>
<ul>
<li><p><a target="_blank" href="https://twitter.com/roxsross">Twitter</a></p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/roxsross">LinkedIn</a></p>
</li>
<li><p><a target="_blank" href="https://www.instagram.com/roxsross">Instagram</a></p>
</li>
<li><p><a target="_blank" href="https://www.youtube.com/channel/295devops">YouTube</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[🐳 De lo Local se Aprende: Desplegando tu Primera App con Docker y DynamoDB Local]]></title><description><![CDATA[Si estás comenzando en el mundo del backend o querés practicar cómo construir aplicaciones que eventualmente puedan desplegarse en la nube, esta guía es para vos.
No necesitás una cuenta de AWS ni pagar por infraestructura. En este post te muestro có...]]></description><link>https://blog.295devops.com/de-lo-local-se-aprende-desplegando-tu-primera-app-con-docker-y-dynamodb-local</link><guid isPermaLink="true">https://blog.295devops.com/de-lo-local-se-aprende-desplegando-tu-primera-app-con-docker-y-dynamodb-local</guid><category><![CDATA[Devops]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[roxsops]]></category><category><![CDATA[Docker]]></category><category><![CDATA[AWS]]></category><category><![CDATA[DynamoDB]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Thu, 01 May 2025 18:07:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1746111984801/06364464-0aac-4bf9-a3a4-9d57a6758870.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Si estás comenzando en el mundo del backend o querés practicar cómo construir aplicaciones que eventualmente puedan desplegarse en la nube, esta guía es para vos.</p>
<p><mark>No necesitás una cuenta de AWS ni pagar por infraestructura. En este post te muestro cómo levantar </mark> <strong><mark>una aplicación de votación con Flask</mark></strong> <mark>usando </mark> <strong><mark>Docker y DynamoDB Local</mark></strong><mark>, simulando un entorno cloud en tu propia máquina.</mark></p>
<h2 id="heading-que-vamos-a-construir"><strong>¿Qué vamos a construir?</strong></h2>
<p>Una pequeña app REST que te permite enviar votos, consultarlos, eliminarlos y almacenarlos usando una base de datos NoSQL como DynamoDB. Y todo esto lo vamos a ejecutar de forma local.</p>
<p><img src="https://github.com/roxsross/workshop-ecs/raw/master/docs/1.png" alt /></p>
<hr />
<h2 id="heading-requisitos-previos"><strong>Requisitos previos</strong></h2>
<p>Antes de comenzar, asegurate de tener instalado:</p>
<ul>
<li><p>Docker y Docker Compose que viene incluidas en <a target="_blank" href="https://docs.docker.com/desktop/">Docker Desktop</a></p>
</li>
<li><p>Python 3.x</p>
</li>
<li><p>(Opcional) <a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html">AWS CLI</a></p>
</li>
<li><p>Revisar la documentación sobre <a target="_blank" href="https://aws.amazon.com/es/dynamodb/">DynamoDB</a></p>
</li>
<li><p><a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.DownloadingAndRunning.html">Sobre DynamoDB Local</a></p>
</li>
<li><p>Toda la Fuerza de la IA: Amazon Q, ChatGPT, deepseek, RoxsGPT 🤭</p>
</li>
</ul>
<hr />
<h2 id="heading-configurar-un-entorno-virtual-en-python-opcional-pero-recomendado">🐍 Configurar un entorno virtual en Python (opcional pero recomendado)</h2>
<p>Para mantener tu entorno limpio y evitar conflictos de dependencias entre proyectos, podés crear un entorno virtual usando <code>venv</code>. Es una buena práctica, sobre todo cuando trabajás con Flask u otras librerías.</p>
<h4 id="heading-1-crear-el-entorno-virtual">1. Crear el entorno virtual</h4>
<p>Desde la raíz del proyecto, ejecutá:</p>
<pre><code class="lang-bash">python3 -m venv venv
</code></pre>
<p>Esto creará una carpeta llamada <code>venv</code> con un entorno aislado de Python.</p>
<h4 id="heading-2-activar-el-entorno-virtual">2. Activar el entorno virtual</h4>
<ul>
<li>En Linux/macOS:</li>
</ul>
<pre><code class="lang-bash"><span class="hljs-built_in">source</span> venv/bin/activate
</code></pre>
<ul>
<li>En Windows (CMD):</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-string">venv\Scripts\activate</span>
</code></pre>
<ul>
<li>En PowerShell:</li>
</ul>
<pre><code class="lang-powershell">venv\Scripts\Activate.ps1
</code></pre>
<p>Una vez activado, verás el prefijo <code>(venv)</code> en tu consola.</p>
<h4 id="heading-3-instalar-dependencias">3. Instalar dependencias</h4>
<p>Con el entorno activo, podés instalar las librerías del proyecto (por ejemplo, Flask y Boto3):</p>
<pre><code class="lang-bash">pip install -r requirements.txt
</code></pre>
<blockquote>
<p>⚠️ Si no tenés un archivo <code>requirements.txt</code>, podés instalar manualmente con <code>pip install flask boto3</code> y luego generar el archivo con <code>pip freeze &gt; requirements.txt</code>.</p>
</blockquote>
<hr />
<h2 id="heading-que-es-dynamodb-y-por-que-lo-usamos-en-este-proyecto">🗃️ ¿Qué es DynamoDB (y por qué lo usamos en este proyecto)?</h2>
<p><strong>Amazon DynamoDB</strong> es un servicio de base de datos NoSQL de alto rendimiento ofrecido por AWS. A diferencia de una base relacional (como MySQL o PostgreSQL), <strong>DynamoDB almacena los datos en forma de tablas con claves primarias, pero sin esquemas rígidos</strong>, lo que lo hace ideal para aplicaciones modernas y escalables.</p>
<h4 id="heading-caracteristicas-clave">🚀 Características clave:</h4>
<ul>
<li><p>Es <strong>serverless</strong>: no necesitás preocuparte por servidores ni escalabilidad.</p>
</li>
<li><p>Permite consultas ultra rápidas a gran escala.</p>
</li>
<li><p>Se usa mucho en arquitecturas modernas, como microservicios y apps serverless.</p>
</li>
</ul>
<h3 id="heading-y-que-es-dynamodb-local">🤓 ¿Y qué es DynamoDB Local?</h3>
<p>Para no depender de internet ni gastar créditos de AWS mientras aprendés, podés correr <strong>DynamoDB Local</strong> en tu máquina, que emula el comportamiento real del servicio. ¡Perfecto para desarrollos y pruebas locales!</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">En este proyecto, usamos DynamoDB para <strong>almacenar los votos de forma rápida y simple</strong>, sin necesidad de configurar un servidor de base de datos tradicional.</div>
</div>

<hr />
<h2 id="heading-arquitectura-de-la-aplicacion">🧱 Arquitectura de la aplicación</h2>
<p>Tu stack ahora se compone de <strong>tres componentes principales</strong>:</p>
<ol>
<li><p><strong>Frontend (HTML + JS)</strong></p>
<ul>
<li><p>Vive dentro del servicio Flask (<code>vote</code>) en la carpeta <code>templates/</code>.</p>
</li>
<li><p>Permite a los usuarios votar y ver resultados desde el navegador.</p>
</li>
</ul>
</li>
<li><p><strong>Backend (Flask + Python)</strong></p>
<ul>
<li><p>Expone una API REST (<code>/api/votes</code>, <code>/api/stats</code>, etc.).</p>
</li>
<li><p>Sirve el HTML y recibe interacciones del usuario.</p>
</li>
<li><p>Se comunica con DynamoDB Local a través de Boto3.</p>
</li>
</ul>
</li>
<li><p><strong>DynamoDB Local (Base de datos NoSQL)</strong></p>
<ul>
<li><p>Ejecutada en un contenedor independiente ó puedes correrlo local.</p>
</li>
<li><p>Guarda votos persistidos.</p>
</li>
<li><p>Inicializada al inicio con <code>init_</code><a target="_blank" href="http://db.py"><code>db.py</code></a>.</p>
</li>
</ul>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1746113473391/fe4f6f99-6caf-4f7f-9b59-7c5714208758.png" alt class="image--center mx-auto" /></p>
<hr />
<h2 id="heading-flujo-de-interaccion">🔁 Flujo de interacción</h2>
<ol>
<li><p>El usuario entra a <a target="_blank" href="http://localhost:8080"><code>http://localhost:8080</code></a> y ve la interfaz de votación.</p>
</li>
<li><p>Al hacer clic en “Votar por Gatos”, el navegador llama al endpoint <code>/api/cats</code>.</p>
</li>
<li><p>Flask procesa la petición y actualiza DynamoDB Local.</p>
</li>
<li><p>La interfaz recupera los votos actualizados con <code>/api/getvotes</code> y muestra los resultados.</p>
</li>
<li><p>Todo esto corre <strong>localmente con Docker</strong>, sin conexión a AWS real.</p>
</li>
</ol>
<hr />
<h2 id="heading-repositorio-del-codigo">💻 Repositorio del Código</h2>
<p>Cloná este repositorio desde <strong>GitHub</strong>:</p>
<p><a target="_blank" href="https://github.com/roxsross/workshop-ecs">https://github.com/roxsross/workshop-ecs</a></p>
<p>Y accedé a la carpeta del proyecto:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/roxsross/workshop-ecs
<span class="hljs-built_in">cd</span> workshop-ecs
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">Aunque el repositorio está preparado para usarse con ECS, en este blog nos vamos a enfocar únicamente en su ejecución local.</div>
</div>

<hr />
<h2 id="heading-entendiendo-los-servicios">⚙️ Entendiendo los servicios</h2>
<p>Esta aplicación se compone de dos contenedores definidos en <code>docker-compose.yml</code>:</p>
<ul>
<li><p><strong>vote</strong>: aplicación en Flask que maneja los votos.</p>
</li>
<li><p><strong>vote-db</strong>: contenedor que ejecuta DynamoDB Local.</p>
</li>
</ul>
<p>La app se compone de dos servicios definidos en <code>compose.yml</code>:</p>
<ul>
<li><p><strong>vote</strong>: Servicio en Flask que recibe y gestiona los votos.</p>
</li>
<li><p><strong>vote-db</strong>: Contenedor que ejecuta DynamoDB Local.</p>
</li>
</ul>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">vote:</span>
    <span class="hljs-attr">build:</span>
      <span class="hljs-attr">context:</span> <span class="hljs-string">.</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8080:8080"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DDB_AWS_REGION=us-east-1</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DDB_TABLE_NAME=votes</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">ENV=local</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">vote-db</span>

  <span class="hljs-attr">vote-db:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">amazon/dynamodb-local</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"8000:8000"</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">AWS_ACCESS_KEY_ID=FAKE</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">AWS_SECRET_ACCESS_KEY=FAKE</span>
</code></pre>
<p>El contenedor de Flask se comunica con DynamoDB Local utilizando credenciales falsas, ya que este modo de ejecución no necesita autenticación real.</p>
<p>Para manejos de variables de entorno te recomiendo lo siguiente: <a target="_blank" href="https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/">https://docs.docker.com/compose/how-tos/environment-variables/set-environment-variables/</a></p>
<hr />
<h2 id="heading-construir-los-contenedores">🧱 Construir los Contenedores</h2>
<p>Usá el siguiente comando para construir los servicios con Docker Compose:</p>
<pre><code class="lang-bash">docker compose build
</code></pre>
<hr />
<h2 id="heading-inicializar-dynamodb-local">🔌 Inicializar DynamoDB Local</h2>
<p>Primero levantá el servicio de base de datos:</p>
<pre><code class="lang-yaml"><span class="hljs-string">docker</span> <span class="hljs-string">compose</span> <span class="hljs-string">up</span> <span class="hljs-string">vote-db</span> <span class="hljs-string">-d</span>
</code></pre>
<p>Luego, ejecutá el script <code>init_</code><a target="_blank" href="http://db.py"><code>db.py</code></a> para crear la tabla y pre-cargar datos:</p>
<pre><code class="lang-yaml"><span class="hljs-string">python</span> <span class="hljs-string">init_db.py</span>
</code></pre>
<p>📋 Ejemplo de salida esperada:</p>
<pre><code class="lang-yaml"><span class="hljs-string">INFO</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Creando</span> <span class="hljs-string">tabla</span> <span class="hljs-string">votes...</span>
<span class="hljs-string">INFO</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Tabla</span> <span class="hljs-string">creada</span> <span class="hljs-string">correctamente.</span>
<span class="hljs-string">INFO</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Inicializando</span> <span class="hljs-string">contador</span> <span class="hljs-string">para</span> <span class="hljs-string">'cats'</span>
<span class="hljs-string">INFO</span> <span class="hljs-bullet">-</span> <span class="hljs-string">Inicializando</span> <span class="hljs-string">contador</span> <span class="hljs-string">para</span> <span class="hljs-string">'dogs'</span>
</code></pre>
<blockquote>
<p>Este paso es clave para que la app funcione correctamente.</p>
</blockquote>
<hr />
<h2 id="heading-levantar-la-aplicacion">🚀 Levantar la Aplicación</h2>
<p>Ahora sí, levantá todo el stack local:</p>
<pre><code class="lang-yaml"><span class="hljs-string">docker</span> <span class="hljs-string">compose</span> <span class="hljs-string">up</span> <span class="hljs-string">-d</span>
</code></pre>
<p>La aplicación Flask estará disponible en:<br />👉 <a target="_blank" href="http://localhost:8080">http://localhost:8080</a></p>
<hr />
<h2 id="heading-endpoints-disponibles">🔗 Endpoints Disponibles</h2>
<p>Podés interactuar con la app vía API REST:</p>
<h3 id="heading-1-get-apivotes">1. <code>GET /api/votes</code></h3>
<p>Obtiene todos los votos almacenados.</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">http://localhost:8080/api/getvotes</span>
</code></pre>
<hr />
<h3 id="heading-2-get-apicats">2. <code>GET /api/cats</code></h3>
<p>Gestionar un voto a la opción gatos</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">-X</span> <span class="hljs-string">GET</span> <span class="hljs-string">http://localhost:8080/api/cats</span>
</code></pre>
<hr />
<h3 id="heading-3-get-apidogs">3. <code>GET /api/dogs</code></h3>
<p>Elimina un voto por ID.</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">-X</span> <span class="hljs-string">GET</span> <span class="hljs-string">http://localhost:8080/api/dogs</span>
</code></pre>
<h3 id="heading-4-get-apireset">4. <code>GET /api/reset</code></h3>
<p>Reinicia los votos de "cats" y "dogs" a 0.</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">-X</span> <span class="hljs-string">POST</span> <span class="hljs-string">http://localhost:8080/api/reset</span>
</code></pre>
<h3 id="heading-5-get-apihistory">5. <code>GET /api/history</code></h3>
<p>Obtiene el historial de votos para una entidad específica (por ejemplo, "cats" o "dogs"). Puedes limitar el número de registros con el parámetro limit</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">-X</span> <span class="hljs-string">GET</span> <span class="hljs-string">"http://localhost:8080/api/history/cats?limit=5"</span>
</code></pre>
<h3 id="heading-6-get-apistats">6. <code>GET /api/stats</code></h3>
<p>Devuelve estadísticas como el total de votos, la distribución de votos y el líder actual.</p>
<pre><code class="lang-yaml"><span class="hljs-string">curl</span> <span class="hljs-string">-X</span> <span class="hljs-string">GET</span> <span class="hljs-string">http://localhost:8080/api/stats</span>
</code></pre>
<hr />
<h2 id="heading-probar-la-conexion-con-aws-cli-opcional">🧪 Probar la Conexión con AWS CLI (opcional)</h2>
<p>Si querés ver las tablas directamente desde AWS CLI:</p>
<pre><code class="lang-yaml"><span class="hljs-string">export</span> <span class="hljs-string">AWS_ACCESS_KEY_ID=FAKE</span>
<span class="hljs-string">export</span> <span class="hljs-string">AWS_SECRET_ACCESS_KEY=FAKE</span>
<span class="hljs-string">aws</span> <span class="hljs-string">dynamodb</span> <span class="hljs-string">list-tables</span> <span class="hljs-string">--endpoint-url</span> <span class="hljs-string">http://localhost:8000</span>
</code></pre>
<hr />
<h2 id="heading-apagar-y-limpiar-los-contenedores">🧹 Apagar y Limpiar los Contenedores</h2>
<p>Cuando termines, podés apagar todo con:</p>
<pre><code class="lang-yaml"><span class="hljs-string">docker</span> <span class="hljs-string">compose</span> <span class="hljs-string">down</span>
</code></pre>
<p>Y si querés eliminar volúmenes:</p>
<pre><code class="lang-yaml"><span class="hljs-string">docker</span> <span class="hljs-string">compose</span> <span class="hljs-string">down</span> <span class="hljs-string">--volumes</span>
</code></pre>
<hr />
<h2 id="heading-docker-te-parece-complejo">🐳 ¿Docker te parece complejo?</h2>
<p>No te preocupes, al principio a todos nos pasó. Pero te prometo que con práctica se vuelve una de tus herramientas favoritas.</p>
<p>Si querés dar tus primeros pasos y entender bien cómo funciona, te dejo este workshop oficial para empezar:</p>
<p>👉 <a target="_blank" href="https://docs.docker.com/get-started/workshop/">Iniciá con Docker – Workshop oficial de Docker</a></p>
<p><mark>Animate a practicar, romper cosas, reconstruir y aprender. ¡Así se crece! 💪🚀</mark></p>
<hr />
<h2 id="heading-mira-el-video-corriendo-el-ejercicio">🎥 Mirá el video corriendo el ejercicio</h2>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.youtube.com/watch?v=FJoIbOs03Vc">https://www.youtube.com/watch?v=FJoIbOs03Vc</a></div>
<p> </p>
<hr />
<h2 id="heading-reflexion-final">🌱 Reflexión Final</h2>
<p>Empezar en local no significa quedarse atrás.<br />💻 Aprender a levantar tu propia app, gestionar una base de datos y simular un entorno cloud es una habilidad <strong>clave</strong>.</p>
<p><mark>Lo que construís en tu máquina hoy... 🔥 mañana puede escalar a producción en AWS, ECS o donde vos decidas.</mark></p>
<hr />
<h2 id="heading-recursos">📁 Recursos</h2>
<ul>
<li><p>Código fuente: <a target="_blank" href="https://github.com/roxsross/workshop-ecs">https://github.com/roxsross/workshop-ecs</a></p>
</li>
<li><p><a target="_blank" href="https://github.com/roxsross/workshop-ecs">Documentación oficial de</a> <a target="_blank" href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DynamoDBLocal.html">Dynam</a><a target="_blank" href="https://github.com/roxsross/workshop-ecs">oDB Local</a></p>
</li>
</ul>
<hr />
<h2 id="heading-conclusion"><strong>Conclusión</strong></h2>
<p>Empezar a desarrollar en local es uno de los mejores caminos para aprender cómo funcionan los servicios reales. Esta guía te permite practicar la interacción entre una aplicación en Flask y una base de datos NoSQL como DynamoDB, sin necesidad de subir nada a la nube.</p>
<p><strong>Lo que hoy ejecutás en tu laptop/Notebook, mañana puede escalar a servicios como AWS ECS o Fargate. Pero antes de despegar, es importante entender cómo funciona todo desde el piso.</strong></p>
<hr />
<h2 id="heading-seguime-y-sumate-a-la-comunidad">📲 Seguime y sumate a la comunidad</h2>
<p>Si te gustó esta guía, compartila con tu comunidad. Y si querés más contenido como este, podés seguirme en mi canal de Youtube 295DEVOPS, donde subo tutoriales y workshops enfocados en DevOps, cloud y desarrollo práctico.</p>
<ul>
<li><p>💜 YouTube (tutoriales y charlas): <a target="_blank" href="https://www.youtube.com/@295devops">295DEVOPS</a></p>
</li>
<li><p>🐦 Twitter/X: <a target="_blank" href="https://twitter.com/roxsross">@roxsross</a></p>
</li>
<li><p>📸 Instagram: <a target="_blank" href="https://instagram.com/roxsross">@roxsross</a></p>
</li>
<li><p>📝 Blog: blog.295devops.com</p>
</li>
<li><p>🐙 GitHub: <a target="_blank" href="https://github.com/roxsross">github.com/roxsross</a></p>
</li>
</ul>
<p>¡Gracias por llegar hasta acá! Y recordá: <strong>lo que hoy probás en local, mañana lo podés escalar a lo grande</strong></p>
<p>Nos vemos!</p>
]]></content:encoded></item><item><title><![CDATA[DevOps en la era de la IA: Aprender, olvidar y volver a aprender]]></title><description><![CDATA[¿Alguna vez sentiste que tu cerebro intenta hacer malabares con demasiadas habilidades técnicas al mismo tiempo? ¿Como si siempre estuvieras corriendo detrás de nuevos frameworks, servicios en la nube y prácticas de desarrollo que parecen multiplicar...]]></description><link>https://blog.295devops.com/devops-en-la-era-de-la-ia-aprender-olvidar-y-volver-a-aprender</link><guid isPermaLink="true">https://blog.295devops.com/devops-en-la-era-de-la-ia-aprender-olvidar-y-volver-a-aprender</guid><category><![CDATA[Devops]]></category><category><![CDATA[motivation]]></category><category><![CDATA[Tecnología]]></category><category><![CDATA[roxsross]]></category><category><![CDATA[IA]]></category><category><![CDATA[roxsops]]></category><dc:creator><![CDATA[Rossana Suarez]]></dc:creator><pubDate>Sat, 26 Apr 2025 15:33:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1745680850416/3e9ce897-6823-4b79-8551-070e2439e3eb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>¿Alguna vez sentiste que tu cerebro intenta hacer malabares con demasiadas habilidades técnicas al mismo tiempo? ¿Como si siempre estuvieras corriendo detrás de nuevos frameworks, servicios en la nube y prácticas de desarrollo que parecen multiplicarse de un día para otro? Si te sentís identificada o identificado con esto, te cuento que no sos la única persona. <strong>¡Bienvenidos al club!</strong></p>
<p><img src="https://sdmntprnorthcentralus.oaiusercontent.com/files/00000000-33cc-622f-a4a7-ce9106b6158f/raw?se=2025-04-26T16%3A31%3A34Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=1185bb6e-ac13-5435-ba57-ceffae345c87&amp;skoid=de76bc29-7017-43d4-8d90-7a49512bae0f&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-04-25T23%3A06%3A09Z&amp;ske=2025-04-26T23%3A06%3A09Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=MafWBweHVtpIq%2Bm93ePonaToXnYQJ9dHUQEywaquNIA%3D" alt /></p>
<h3 id="heading-el-dilema-del-profesional-tech">El dilema del profesional tech</h3>
<p>Soy <strong>Roxs</strong>, DevOps desde hace años, y he pasado por muchas etapas en mi carrera: desde mis inicios como desarrolladora hasta convertirme en una especialista en DevOps. He invertido innumerables horas en aprender herramientas a fondo y perfeccionar mi conocimiento. Pero, de repente, algo cambia en la industria: surgen nuevas tecnologías, y ese conocimiento que tanto esfuerzo costó obtener comienza a sentirse insuficiente.</p>
<p>Hace poco tuve una charla sincera con otros profesionales del sector, y surgió algo que muchos pensamos pero pocos decimos en voz alta: la presión constante por absorber nuevos conocimientos técnicos, mientras que las habilidades humanas como la comunicación efectiva, la resolución de problemas o el trabajo en equipo suelen quedar relegadas.</p>
<h3 id="heading-la-montana-infinita-de-conocimientos">La montaña infinita de conocimientos</h3>
<p>Pensá por un segundo en todo lo que una persona dedicada al DevOps tiene que saber hoy:</p>
<ul>
<li><p>Detalles específicos de proveedores en la nube (AWS, Azure, GCP).</p>
</li>
<li><p>Kubernetes y orquestación de contenedores.</p>
</li>
<li><p>Infraestructura como código (Terraform, CloudFormation).</p>
</li>
<li><p>Pipelines de integración y despliegue continuo (CI/CD).</p>
</li>
<li><p>Lenguajes de programación y scripting.</p>
</li>
<li><p>Sistemas operativos.</p>
</li>
<li><p>Redes y seguridad informática.</p>
</li>
<li><p>Herramientas de monitoreo y observabilidad.</p>
</li>
<li><p>Control de versiones.</p>
</li>
<li><p><strong>Inteligencia Artificial aplicada al desarrollo (IA Developer Experience)</strong></p>
</li>
</ul>
<p><img src="https://sdmntprnorthcentralus.oaiusercontent.com/files/00000000-38fc-622f-9639-c8a7399a40cf/raw?se=2025-04-26T16%3A29%3A48Z&amp;sp=r&amp;sv=2024-08-04&amp;sr=b&amp;scid=999e31a0-e4ad-530d-9b4b-55d4b41cc72e&amp;skoid=de76bc29-7017-43d4-8d90-7a49512bae0f&amp;sktid=a48cca56-e6da-484e-a814-9c849652bcb3&amp;skt=2025-04-26T06%3A35%3A48Z&amp;ske=2025-04-27T06%3A35%3A48Z&amp;sks=b&amp;skv=2024-08-04&amp;sig=Dhpm5UBBKvrGGbLuVO7704AdbNcVzUqLhKl5ciYcHK8%3D" alt="Imagen generada" /></p>
<p>La IA está revolucionando la manera en que trabajamos y aprendemos, potenciando nuestras habilidades y cambiando las expectativas del mercado. Cada vez más, herramientas impulsadas por IA como GitHub Copilot, Amazon Q y diversas soluciones de inteligencia artificial están redefiniendo la experiencia del desarrollador y automatizando tareas repetitivas, permitiéndonos enfocarnos en lo verdaderamente importante: resolver problemas de manera creativa y efectiva.</p>
<p><mark>¡Y la lista sigue creciendo! Como decía alguien hace poco: "Cada vez que parpadeo aparece un nuevo framework, servicio en la nube o mejor práctica que supuestamente debo dominar. ¡Es una locura!"</mark></p>
<h3 id="heading-cambiando-el-enfoque-aprender-es-nuestro-trabajo">Cambiando el enfoque: Aprender es nuestro trabajo</h3>
<p>En medio de tanta frustración, surgió una idea poderosa que cambió mi manera de ver las cosas: "Nos pagan por aprender".</p>
<p>Este enfoque transforma el aprendizaje continuo en algo esencial y emocionante. Como dijo una colega con 30 años de experiencia: "Mi habilidad más valiosa es la capacidad de aprender sobre la marcha".</p>
<p>Otra compañera DevOps coincidió: "Nunca vamos a dejar de aprender herramientas nuevas… nuestro trabajo es básicamente ‘descubrir cómo hacerlo’. Y justamente eso me encanta, porque siempre me empuja a crecer".</p>
<h3 id="heading-el-arte-de-olvidar">El arte de olvidar</h3>
<p>Algo curioso que surgió de estas conversaciones es que olvidar no solo es inevitable, sino beneficioso.</p>
<p>Una ingeniera de fiabilidad (SRE) comentó algo que resonó conmigo profundamente: "No intento retener todo en la cabeza, es inútil. Prefiero fortalecer mi habilidad para resolver problemas por mí misma. De hecho, olvidar cosas es la mejor manera de perfeccionarme en esto".</p>
<p><mark>Esto puede sonar contradictorio, pero tiene mucho sentido. La industria tecnológica no premia a quienes memorizan comandos o configuraciones, sino a quienes saben resolver problemas con rapidez y eficacia.</mark></p>
<h3 id="heading-mis-herramientas-para-gestionar-el-exceso-de-informacion">Mis herramientas para gestionar el exceso de información</h3>
<p>En mi experiencia, hay ciertas técnicas que me ayudan mucho a no ahogarme en información:</p>
<ul>
<li><p><strong>Notas detalladas y buscables:</strong> Tomo notas constantemente, sabiendo que probablemente olvidaré ciertos detalles en días o semanas.</p>
</li>
<li><p><strong>Enfocarme en los fundamentos:</strong> Las bases como Linux, redes, virtualización, contenedores, kuberntenes, roxsops, permanecen constantes y siempre útiles.</p>
</li>
<li><p><strong>Documentación organizada:</strong> Utilizo notion y guardo documentación detallada para futuras referencias rápidas.</p>
</li>
<li><p><strong>Repositorios personales:</strong> Mantengo ejemplos básicos y plantillas de infraestructura y desarrollo en repos personales, como GitHub o GitLab.</p>
</li>
</ul>
<h3 id="heading-lo-humano-tambien-cuenta-y-mucho">Lo humano también cuenta (¡y mucho!)</h3>
<p>A pesar de que las demandas técnicas son intensas, nunca subestimes la importancia de las habilidades interpersonales. Una buena compañera, una comunicación clara y una actitud proactiva en los momentos difíciles son cosas que realmente se valoran en equipos saludables.</p>
<p>Como dijo una colega líder de plataforma con décadas de experiencia: "Una buena empresa valora que seas una persona solidaria, que puedas comunicarte con claridad, y que estés dispuesta a ayudar cuando las cosas se ponen difíciles".</p>
<h3 id="heading-buscando-equilibrio">Buscando equilibrio</h3>
<p>Entonces, ¿cómo evitar quemarse frente a tantos cambios tecnológicos?</p>
<ul>
<li><p><strong>Aceptar lo imposible:</strong> No podemos saber todo, y eso está bien. No ejerzas una presión irreal sobre vos.</p>
</li>
<li><p><strong>Aprender a aprender:</strong> Desarrollá métodos eficientes para aprender nuevas tecnologías rápidamente, empezando simple y avanzando en pequeños pasos.</p>
</li>
<li><p><strong>Establecer límites:</strong> No dediques todo tu tiempo libre exclusivamente al aprendizaje técnico; el equilibrio es clave para mantener el bienestar.</p>
</li>
<li><p><strong>Elegir bien dónde trabajar:</strong> Elegí empresas que valoren tu capacidad para aprender y resolver problemas por sobre la cantidad absoluta de conocimiento acumulado.</p>
</li>
</ul>
<h3 id="heading-abrazando-el-cambio-continuo">Abrazando el cambio continuo</h3>
<p>Quizás lo más lindo de trabajar en tecnología es justamente eso: que nunca deja de cambiar. Lo que para algunas personas es estrés, para otras es justamente lo que hace apasionante esta carrera.</p>
<p>Como escuché hace poco: "Esta es una de las pocas profesiones que constantemente cambia. Para mí, eso significa aprender algo nuevo cada día. Por eso nunca me aburro".</p>
<h3 id="heading-mirando-hacia-adelante">Mirando hacia adelante</h3>
<p>El panorama tecnológico seguirá cambiando, surgirán nuevas herramientas, otras quedarán atrás. Pero en medio de estos cambios constantes, hay habilidades que nunca pierden valor: la curiosidad, la adaptabilidad y la capacidad para aprender.</p>
<p><mark>La próxima vez que te sientas desbordada o desbordado por otra tecnología que "deberías" dominar, recordá: la verdadera habilidad no es saberlo todo, sino saber cómo resolver cualquier cosa que se presente.</mark></p>
<p><strong>¡Sigamos disfrutando de este camino lleno de aprendizajes y aventuras tecnológicas!</strong></p>
]]></content:encoded></item></channel></rss>