<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: MapDevops</title>
    <description>The latest articles on DEV Community by MapDevops (@mapdevops_039ce941da).</description>
    <link>https://dev.to/mapdevops_039ce941da</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1901082%2F7360e125-e8ac-4371-abcd-70060fbf8930.png</url>
      <title>DEV Community: MapDevops</title>
      <link>https://dev.to/mapdevops_039ce941da</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mapdevops_039ce941da"/>
    <language>en</language>
    <item>
      <title>Stop Fighting AWS Networking — Deploy Your Container in 3 Steps</title>
      <dc:creator>MapDevops</dc:creator>
      <pubDate>Mon, 23 Mar 2026 11:32:48 +0000</pubDate>
      <link>https://dev.to/mapdevops_039ce941da/stop-fighting-aws-networking-deploy-your-container-in-3-steps-5d6a</link>
      <guid>https://dev.to/mapdevops_039ce941da/stop-fighting-aws-networking-deploy-your-container-in-3-steps-5d6a</guid>
      <description>&lt;h1&gt;
  
  
  You Just Want to Deploy a Docker Container. AWS Has Other Plans.
&lt;/h1&gt;

&lt;p&gt;You've got a Dockerfile. It works on your machine. It works in CI. You just want to put it on the internet.&lt;/p&gt;

&lt;p&gt;So you open the AWS console and within 15 minutes you're reading about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPCs, CIDR blocks, and subnet math&lt;/li&gt;
&lt;li&gt;Internet Gateways vs. NAT Gateways&lt;/li&gt;
&lt;li&gt;Route tables (public vs. private, and why they're different)&lt;/li&gt;
&lt;li&gt;Application Load Balancers, target groups, listener rules&lt;/li&gt;
&lt;li&gt;Security groups that reference &lt;em&gt;other&lt;/em&gt; security groups&lt;/li&gt;
&lt;li&gt;ECS task definitions, services, execution roles, task roles&lt;/li&gt;
&lt;li&gt;Auto Scaling policies, CloudWatch alarms, Container Insights&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You wanted &lt;code&gt;docker run&lt;/code&gt;. AWS handed you a 200-page networking textbook.&lt;/p&gt;

&lt;p&gt;I've been there. Multiple times. And after the third time I rebuilt this from scratch for a new project, I decided to actually do it &lt;em&gt;right&lt;/em&gt; — and never do it again.&lt;/p&gt;

&lt;p&gt;But first, let me show you the mistake almost everyone makes on their first try.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trap: Fargate in a Public Subnet
&lt;/h2&gt;

&lt;p&gt;Here's what most tutorials teach you (and what the AWS "Getting Started" wizard defaults to):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a VPC with &lt;strong&gt;public&lt;/strong&gt; subnets&lt;/li&gt;
&lt;li&gt;Put your Fargate tasks in those public subnets&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;assign_public_ip = true&lt;/code&gt; so the tasks can pull images from ECR&lt;/li&gt;
&lt;li&gt;Attach a security group that allows inbound traffic on your container port&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;It works.&lt;/strong&gt; Your container is reachable. You ship it. You move on.&lt;/p&gt;

&lt;p&gt;But here's what you just did:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your containers have &lt;strong&gt;public IP addresses&lt;/strong&gt;. They are directly addressable from the entire internet.&lt;/li&gt;
&lt;li&gt;That security group you wrote? It's the &lt;em&gt;only&lt;/em&gt; thing between a bad actor and your application process.&lt;/li&gt;
&lt;li&gt;Every container is an attack surface. Not just the ALB — &lt;strong&gt;every running task&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If someone finds a vulnerability in your app (or its dependencies), they have a direct network path to exploit it.&lt;/li&gt;
&lt;li&gt;You skipped the NAT Gateway to save ~$32/month. Your containers are now exposed to save the cost of a nice dinner.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't a theoretical risk. Port scanners hit every public IP on AWS continuously. If your container has a debug endpoint, an unpatched dependency, or even a misconfigured health check — it's findable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "save money, skip the NAT" shortcut is a security incident waiting to happen.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Correct Architecture
&lt;/h2&gt;

&lt;p&gt;Here's what a production Fargate deployment should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                          Internet
                              |
                         +----v----+
                         |   IGW   |
                         +----+----+
                              | HTTP/HTTPS
              +---------------v----------------------+
              |              VPC  10.0.0.0/16         |
              |                                       |
              |   +-----------------------------+     |
              |   |  ALB  (SG: 80,443 inbound)  |     |
              |   +------+-------------+--------+     |
              |          |             |              |
              |  +-------v------+ +---v-----------+  |
              |  | Public Subnet| | Public Subnet |  |
              |  |   us-east-1a | |   us-east-1b  |  |
              |  |  [NAT GW]   | |               |  |
              |  +--------------+ +---------------+  |
              |          |             |              |
              |  +-------v------+ +---v-----------+  |
              |  |Private Subnet| |Private Subnet |  |
              |  |   us-east-1a | |   us-east-1b  |  |
              |  |  [Fargate]   | |  [Fargate]    |  |
              |  |  SG:ALB only | |  SG:ALB only  |  |
              |  +--------------+ +---------------+  |
              +--------------------------------------+
                     |                    |
              CloudWatch Logs          ECR / IAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Internet -&amp;gt; ALB&lt;/strong&gt; (lives in public subnets, accepts HTTP/HTTPS)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ALB -&amp;gt; Fargate tasks&lt;/strong&gt; (live in private subnets, accept traffic &lt;em&gt;only&lt;/em&gt; from the ALB's security group)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fargate -&amp;gt; Internet&lt;/strong&gt; (outbound only, through the NAT Gateway — for pulling images, calling APIs, etc.)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your containers have &lt;strong&gt;no public IPs&lt;/strong&gt;. They are unreachable from the internet. The ALB is the only entry point, and it only forwards traffic that matches your listener rules.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Security Model
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ALB Security Group&lt;/strong&gt;: Inbound 80/443 from &lt;code&gt;0.0.0.0/0&lt;/code&gt;. That's it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECS Task Security Group&lt;/strong&gt;: Inbound from the &lt;strong&gt;ALB security group only&lt;/strong&gt;, on the container port. Zero other ingress.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;assign_public_ip = false&lt;/code&gt;&lt;/strong&gt; on every task. Non-negotiable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Execution Role&lt;/strong&gt;: Scoped to &lt;code&gt;AmazonECSTaskExecutionRolePolicy&lt;/code&gt; — pull images, write logs, nothing more.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Task Role&lt;/strong&gt;: Empty by default. You add &lt;em&gt;only&lt;/em&gt; what your app needs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Cost Reality
&lt;/h3&gt;

&lt;p&gt;Yes, the NAT Gateway costs ~$32/month. Here's the cost breakdown you should actually care about:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Default&lt;/th&gt;
&lt;th&gt;What It Controls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;single_nat_gateway&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One NAT GW (~$32/mo). Set &lt;code&gt;false&lt;/code&gt; for HA across AZs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;task_cpu&lt;/code&gt; / &lt;code&gt;task_memory&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;256 / 512&lt;/td&gt;
&lt;td&gt;Fargate bills per vCPU-second and GB-second.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min_capacity&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Auto Scaling floor.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;$32/month is the cost of doing this correctly. It's less than a single hour of incident response when your public-subnet containers get probed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Problem: Building This in Terraform
&lt;/h2&gt;

&lt;p&gt;Understanding the architecture is one thing. &lt;strong&gt;Implementing it in Terraform is another.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's what you actually need to write:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VPC with calculated CIDR blocks for public and private subnets across multiple AZs&lt;/li&gt;
&lt;li&gt;Internet Gateway + NAT Gateway + Elastic IP&lt;/li&gt;
&lt;li&gt;Route tables (separate for public and private) with correct associations&lt;/li&gt;
&lt;li&gt;ALB with target group, listener, and health check configuration&lt;/li&gt;
&lt;li&gt;ECS cluster with Container Insights enabled&lt;/li&gt;
&lt;li&gt;Task definition with proper CPU/memory combinations (and they have to match — &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html" rel="noopener noreferrer"&gt;see the matrix&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Two IAM roles (execution + task) with trust policies&lt;/li&gt;
&lt;li&gt;Two security groups with cross-references&lt;/li&gt;
&lt;li&gt;Auto Scaling target, plus policies for CPU &lt;em&gt;and&lt;/em&gt; memory&lt;/li&gt;
&lt;li&gt;CloudWatch log group with configurable retention&lt;/li&gt;
&lt;li&gt;Variable validation (Terraform won't stop you from setting &lt;code&gt;task_cpu = 999&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first time I built this, it took me roughly 25 hours — including debugging subnet routing, figuring out why tasks couldn't pull images (missing NAT), and learning that Fargate CPU/memory values aren't arbitrary.&lt;/p&gt;

&lt;p&gt;The second time took about 10 hours because I still forgot half the edge cases.&lt;/p&gt;

&lt;p&gt;The third time, I turned it into a boilerplate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shortcut
&lt;/h2&gt;

&lt;p&gt;I packaged everything above into a &lt;strong&gt;production-ready Terraform boilerplate&lt;/strong&gt; that deploys in 3 steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; — Edit &lt;code&gt;terraform.tfvars&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;project_name&lt;/span&gt;    &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"myapp"&lt;/span&gt;
&lt;span class="nx"&gt;container_image&lt;/span&gt; &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nginx:latest"&lt;/span&gt;
&lt;span class="nx"&gt;aws_region&lt;/span&gt;      &lt;span class="err"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; — Run the deploy script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; — Get your URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform output alb_dns_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Secure VPC, ALB, NAT Gateway, private Fargate tasks, Auto Scaling, CloudWatch — all wired up and validated.&lt;/p&gt;

&lt;p&gt;It also includes &lt;strong&gt;full LocalStack support&lt;/strong&gt;, so you can test the entire infrastructure locally without spending a cent on AWS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;localstack start &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .env
./deploy.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What's included
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Modular, documented Terraform — not a giant &lt;code&gt;main.tf&lt;/code&gt; with 500 uncommented lines&lt;/li&gt;
&lt;li&gt;Input validation — Terraform will reject invalid CPU/memory combos &lt;em&gt;before&lt;/em&gt; you deploy&lt;/li&gt;
&lt;li&gt;Deploy and destroy scripts with confirmation prompts&lt;/li&gt;
&lt;li&gt;Security best practices enforced by default (private subnets, least-privilege IAM, no public IPs)&lt;/li&gt;
&lt;li&gt;Cost optimization built in (single NAT Gateway toggle, right-sized defaults)&lt;/li&gt;
&lt;li&gt;CloudWatch Container Insights for observability&lt;/li&gt;
&lt;li&gt;Secrets management guidance (SSM / Secrets Manager, not env vars)&lt;/li&gt;
&lt;li&gt;Architecture diagram (draw.io, editable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://payhip.com/b/zyGAq" rel="noopener noreferrer"&gt;Get the boilerplate&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You'll save 20+ hours of Terraform debugging and get an architecture you can actually defend in a security review. I wish I'd had this the first three times I built it.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Questions about the architecture or how to extend it? Drop a comment — happy to help.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Stop Wasting 10+ Hours Setting Up Docker for Every New Project</title>
      <dc:creator>MapDevops</dc:creator>
      <pubDate>Mon, 23 Mar 2026 10:44:10 +0000</pubDate>
      <link>https://dev.to/mapdevops_039ce941da/stop-wasting-10-hours-setting-up-docker-for-every-new-project-361</link>
      <guid>https://dev.to/mapdevops_039ce941da/stop-wasting-10-hours-setting-up-docker-for-every-new-project-361</guid>
      <description>&lt;p&gt;You know the drill.&lt;/p&gt;

&lt;p&gt;New project. New repo. Now spend the next &lt;strong&gt;10–15 hours&lt;/strong&gt; writing Dockerfiles, configuring Nginx, wiring up docker-compose, setting up health checks, adding a CI pipeline, figuring out monitoring...&lt;/p&gt;

&lt;p&gt;And you haven't written a single line of business logic yet.&lt;/p&gt;

&lt;p&gt;I've done this setup dozens of times across freelance gigs, side projects, and production systems. So I packaged the result into &lt;strong&gt;ready-to-use Docker boilerplates&lt;/strong&gt; that let you skip straight to building features.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Inside Each Boilerplate
&lt;/h2&gt;

&lt;p&gt;Every boilerplate is a &lt;strong&gt;complete, standalone project&lt;/strong&gt; you unzip and run. No frameworks to learn, no CLI tools to install. Just Docker.&lt;/p&gt;

&lt;p&gt;Here's what you get out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ &lt;strong&gt;Multi-stage Dockerfiles&lt;/strong&gt; — optimized images, non-root users, layer caching&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;docker-compose.yml&lt;/strong&gt; — all services wired together with health checks&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Monitoring stack&lt;/strong&gt; — Prometheus + Grafana pre-configured&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;GitHub Actions CI&lt;/strong&gt; — test + build pipeline ready to go&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Makefile&lt;/strong&gt; — &lt;code&gt;make up&lt;/code&gt;, &lt;code&gt;make down&lt;/code&gt;, &lt;code&gt;make logs&lt;/code&gt;, &lt;code&gt;make test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Environment management&lt;/strong&gt; — &lt;code&gt;.env.example&lt;/code&gt; with sensible defaults&lt;/li&gt;
&lt;li&gt;✅ &lt;strong&gt;Security hardened&lt;/strong&gt; — Helmet, CORS, non-root containers, no source in prod images&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3 Stacks Available
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. React + Express + PostgreSQL
&lt;/h3&gt;

&lt;p&gt;The classic. Battle-tested stack used by thousands of production apps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│   React      │────▶│   Express    │────▶│  PostgreSQL  │
│  (Nginx:80)  │     │    (:3000)   │     │   (:5432)    │
└──────────────┘     └──────────────┘     └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Frontend: &lt;strong&gt;React 18 + Vite&lt;/strong&gt; → built and served by Nginx&lt;/li&gt;
&lt;li&gt;Backend: &lt;strong&gt;Express.js&lt;/strong&gt; with health endpoints and pg driver&lt;/li&gt;
&lt;li&gt;Database: &lt;strong&gt;PostgreSQL 16&lt;/strong&gt; with init script and seed data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; REST APIs, CRUD apps, SaaS MVPs, any project where you want full control over frontend and backend separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. React + Express + MongoDB
&lt;/h3&gt;

&lt;p&gt;Same frontend and backend architecture, swapped to a document database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend: &lt;strong&gt;React 18 + Vite&lt;/strong&gt; → built and served by Nginx&lt;/li&gt;
&lt;li&gt;Backend: &lt;strong&gt;Express.js + Mongoose&lt;/strong&gt; with health endpoints&lt;/li&gt;
&lt;li&gt;Database: &lt;strong&gt;MongoDB 7&lt;/strong&gt; with init script&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; apps with flexible schemas, content platforms, prototypes where you don't want to think about migrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Next.js + PostgreSQL
&lt;/h3&gt;

&lt;p&gt;Modern fullstack in a single container. No separate backend, no Nginx.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌──────────────┐     ┌──────────────┐
│   Next.js    │────▶│  PostgreSQL  │
│  App (:3000) │     │   (:5432)    │
└──────────────┘     └──────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;App: &lt;strong&gt;Next.js 14&lt;/strong&gt; with standalone output, API routes for &lt;code&gt;/health&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Database: &lt;strong&gt;PostgreSQL 16&lt;/strong&gt; with init script and seed data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; fullstack apps, server-rendered pages, projects where you want one deployment unit.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Unzip&lt;/span&gt;
unzip react-express-postgres.zip &lt;span class="nt"&gt;-d&lt;/span&gt; my-project
&lt;span class="nb"&gt;cd &lt;/span&gt;my-project

&lt;span class="c"&gt;# 2. Configure&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; .env.example .env

&lt;span class="c"&gt;# 3. Run&lt;/span&gt;
make up

&lt;span class="c"&gt;# 4. Verify&lt;/span&gt;
curl http://localhost:3000/health
&lt;span class="c"&gt;# → {"status":"ok"}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. All services running, health checks passing, monitoring available at &lt;code&gt;localhost:9090&lt;/code&gt; (Prometheus) and &lt;code&gt;localhost:3001&lt;/code&gt; (Grafana).&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring Included
&lt;/h2&gt;

&lt;p&gt;Every boilerplate ships with a &lt;strong&gt;Prometheus + Grafana&lt;/strong&gt; stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.yml &lt;span class="nt"&gt;-f&lt;/span&gt; monitoring/docker-compose.monitoring.yml up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No extra config needed. Prometheus scrapes your backend health endpoint. Grafana connects to Prometheus automatically. Default login: &lt;code&gt;admin/admin&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The CI Pipeline
&lt;/h2&gt;

&lt;p&gt;Each boilerplate includes a &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt; that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tests&lt;/strong&gt; — installs deps, runs &lt;code&gt;npm test&lt;/code&gt; for each service&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builds&lt;/strong&gt; — builds Docker images to verify they compile&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Push to GitHub and your pipeline is already green.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;Clean, predictable, no surprises:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-project/
├── backend/          # Express API (or app/ for Next.js)
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── frontend/         # React + Vite (not in Next.js variant)
│   ├── Dockerfile
│   ├── package.json
│   └── src/
├── db/               # Init script (SQL or JS)
├── monitoring/       # Prometheus + Grafana
├── .github/workflows/ci.yml
├── docker-compose.yml
├── Makefile
├── .env.example
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Who Is This For?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Freelancers&lt;/strong&gt; who start new client projects every month and are tired of copy-pasting Docker configs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indie hackers&lt;/strong&gt; who want to ship an MVP this weekend, not next month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Junior developers&lt;/strong&gt; who want to learn Docker with a real, working setup instead of toy examples&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Teams&lt;/strong&gt; who need a consistent starting point across projects&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What You're NOT Getting
&lt;/h2&gt;

&lt;p&gt;This is not a framework. There's no vendor lock-in, no CLI, no magic.&lt;/p&gt;

&lt;p&gt;You get &lt;strong&gt;plain files&lt;/strong&gt; — Dockerfiles, compose files, JavaScript, SQL. Read them, modify them, own them. If you know Docker basics, you'll understand everything in 10 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://payhip.com/b/xXER3" rel="noopener noreferrer"&gt;ReactJS + Express + Postgresql stack — $29&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://payhip.com/b/wyZtu" rel="noopener noreferrer"&gt;ReactJS + Express + Mongo stack — $29&lt;/a&gt;&lt;/strong&gt;&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://payhip.com/b/KJaD6" rel="noopener noreferrer"&gt;Next.JS + Postgresql stack — $29&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://payhip.com/b/GrUvt" rel="noopener noreferrer"&gt;All 3 stacks bundle — $49&lt;/a&gt;&lt;/strong&gt; (save 40%)&lt;/p&gt;

&lt;p&gt;Each purchase includes all future updates. Unzip, run, and start building what actually matters — your product.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>webdev</category>
      <category>devops</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
