{"id":4497,"date":"2026-02-09T21:35:15","date_gmt":"2026-02-09T16:05:15","guid":{"rendered":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/"},"modified":"2026-02-09T21:35:15","modified_gmt":"2026-02-09T16:05:15","slug":"docker-best-practices-build-production-ready-containers","status":"publish","type":"post","link":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/","title":{"rendered":"Docker Best Practices: Build Production-Ready Containers"},"content":{"rendered":"<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-69e1f4a196e1e\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-69e1f4a196e1e\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-1'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Grave_We_Dug_with_Default_Dockerfiles\" >The Grave We Dug with Default Dockerfiles<\/a><ul class='ez-toc-list-level-2' ><li class='ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#A_Technical_Post-Mortem_and_Remediation_Guide\" >A Technical Post-Mortem and Remediation Guide<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#1_The_Sin_of_the_%E2%80%9CLatest%E2%80%9D_Tag_and_the_Moving_Target\" >1. The Sin of the &#8220;Latest&#8221; Tag and the Moving Target<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#2_Layer_Bloat_and_the_Multi-Stage_Salvation\" >2. Layer Bloat and the Multi-Stage Salvation<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-2\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-2\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#3_The_Security_Theater_of_Root_Containers\" >3. The Security Theater of Root Containers<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-10\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-3\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-11\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-3\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-12\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#4_Cache_Invalidation_and_the_Order_of_Operations\" >4. Cache Invalidation and the Order of Operations<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-13\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-4\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-14\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-4\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-15\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#5_The_dockerignore_Void\" >5. The .dockerignore Void<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-16\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-5\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-17\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-5\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-18\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#6_PID_1_and_the_Zombie_Process_Apocalypse\" >6. PID 1 and the Zombie Process Apocalypse<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-19\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-6\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-20\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-6\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-21\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#7_The_Filesystem_Truth_ADD_vs_COPY\" >7. The Filesystem Truth: ADD vs COPY<\/a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-22\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Sin-7\" >The Sin<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-23\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Penance-7\" >The Penance<\/a><\/li><\/ul><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-24\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#The_Anatomy_of_the_Overlay2_Failure\" >The Anatomy of the Overlay2 Failure<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-25\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#Checklist_for_the_Uninitiated\" >Checklist for the Uninitiated<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class=\"ez-toc-link ez-toc-heading-26\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#Related_Articles\" >Related Articles<\/a><\/li><\/ul><\/li><\/ul><\/nav><\/div>\n<h1><span class=\"ez-toc-section\" id=\"The_Grave_We_Dug_with_Default_Dockerfiles\"><\/span>The Grave We Dug with Default Dockerfiles<span class=\"ez-toc-section-end\"><\/span><\/h1>\n<h2><span class=\"ez-toc-section\" id=\"A_Technical_Post-Mortem_and_Remediation_Guide\"><\/span>A Technical Post-Mortem and Remediation Guide<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<pre class=\"codehilite\"><code class=\"language-bash\">$ docker build -t api-service:latest .\n[+] Building 412.4s (9\/12)\n =&gt; [internal] load build definition from Dockerfile                       0.1s\n =&gt; [internal] load .dockerignore                                          0.1s\n =&gt; [internal] load metadata for docker.io\/library\/node:latest             1.2s\n =&gt; [1\/8] FROM docker.io\/library\/node:latest                               0.0s\n =&gt; [2\/8] WORKDIR \/app                                                     0.5s\n =&gt; [3\/8] COPY . .                                                        84.2s\n =&gt; [4\/8] RUN npm install                                                210.4s\n =&gt; [5\/8] RUN npm run build                                               45.1s\n =&gt; [6\/8] EXPOSE 3000                                                      0.0s\n =&gt; [7\/8] CMD [&quot;npm&quot;, &quot;start&quot;]                                             0.0s\n =&gt; exporting to image                                                    70.2s\n =&gt; =&gt; exporting layers                                                   70.1s\n =&gt; =&gt; writing image sha256:4f52...                                        0.1s\n =&gt; =&gt; naming to docker.io\/library\/api-service:latest                      0.0s\n\n$ docker images --format &quot;table {{.Repository}}\\t{{.Tag}}\\t{{.Size}}&quot;\nREPOSITORY          TAG                 SIZE\napi-service         latest              2.84GB\n\n$ docker inspect api-service:latest | grep -i &quot;user&quot;\n            &quot;User&quot;: &quot;&quot;,\n\n$ curl -I http:\/\/production-api-01:3000\/health\nHTTP\/1.1 502 Bad Gateway\n# Incident Log: 03:14 AM. Node memory exhaustion. \n# Overlay2 disk pressure at 98%. \n# Deployment rolled back. SRE team (me) awake for 48 hours.\n<\/code><\/pre>\n<p>I am staring at a 2.84GB container image. It contains a simple Node.js API that should, by all rights, occupy no more than 150MB. This isn&#8217;t just &#8220;inefficiency.&#8221; This is professional negligence. This is the result of &#8220;tutorial-driven development,&#8221; where someone copied a Dockerfile from a 2017 Medium post and called it a day. <\/p>\n<p>The production failure tonight wasn&#8217;t a code bug. It was a failure of the infrastructure to breathe under the weight of its own bloat. When the <code>overlay2<\/code> storage driver hit the disk limit because of layer accumulation, the kubelet started evicting pods. Because the images were nearly 3GB, the pull time for the replacement pods exceeded the liveness probe thresholds. We entered a death spiral. <\/p>\n<p>We are going to fix this. We are going to implement <strong>docker best<\/strong> practices, or I am going to start deleting repositories without warning.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"1_The_Sin_of_the_%E2%80%9CLatest%E2%80%9D_Tag_and_the_Moving_Target\"><\/span>1. The Sin of the &#8220;Latest&#8221; Tag and the Moving Target<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The first thing I saw in the logs was <code>FROM node:latest<\/code>. This is a suicide note. When you use <code>latest<\/code>, you are telling the build daemon, &#8220;I don&#8217;t care what version of the OS or the runtime I use. Just give me whatever was pushed five minutes ago.&#8221; <\/p>\n<p>Last night, <code>latest<\/code> updated. It brought in a new version of Debian with a different GLIBC version that conflicted with one of our native C++ bindings. The build passed. The tests passed in a stale CI environment. Production died. <\/p>\n<p>To follow <strong>docker best<\/strong> practices, you must pin your versions. Not just the language runtime, but the underlying OS distribution.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:latest\nWORKDIR \/app\nCOPY . .\nRUN npm install\nCMD [&quot;node&quot;, &quot;index.js&quot;]\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\"># Pinning to a specific LTS version on a stable, slim OS release\nFROM node:20.11.0-alpine3.19\n\n# Set environment to production to ensure devDependencies are ignored\nENV NODE_ENV=production\n\nWORKDIR \/app\n\n# We will address the rest of this disaster in the following sections.\n<\/code><\/pre>\n<p>By using <code>node:20.11.0-alpine3.19<\/code>, we guarantee immutability. Alpine Linux uses <code>musl<\/code> instead of <code>glibc<\/code>, which reduces the attack surface and the footprint. If you need <code>glibc<\/code>, use <code>node:20.11.0-bookworm-slim<\/code>. Never, under any circumstances, allow a tag to be a moving target in a production pipeline.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"2_Layer_Bloat_and_the_Multi-Stage_Salvation\"><\/span>2. Layer Bloat and the Multi-Stage Salvation<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I ran <code>docker history api-service:latest<\/code> and I nearly threw my monitor out the window. Every <code>RUN<\/code> command, every <code>COPY<\/code>, every <code>ADD<\/code> creates a new layer on the filesystem. In the &#8220;Sin&#8221; example above, the <code>npm install<\/code> layer was 800MB because it included all the <code>devDependencies<\/code>, build tools, and the npm cache. Even if you delete them in a later <code>RUN<\/code> command, they stay in the previous layer. They are ghosts that haunt your disk space forever.<\/p>\n<p>The <strong>docker best<\/strong> way to handle this is multi-stage builds. You use one heavy image to build your assets and a second, microscopic image to run them.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-2\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:20.11.0\nWORKDIR \/app\nCOPY . .\nRUN npm install &amp;&amp; npm run build\n# The node_modules and source code are now baked into this layer forever.\nCMD [&quot;node&quot;, &quot;dist\/main.js&quot;]\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-2\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\"># Stage 1: The Builder\nFROM node:20.11.0-alpine3.19 AS builder\nWORKDIR \/app\nCOPY package*.json .\/\nRUN npm ci # Clean install for reproducible builds\nCOPY . .\nRUN npm run build\n\n# Stage 2: The Runner\nFROM node:20.11.0-alpine3.19\nWORKDIR \/app\nENV NODE_ENV=production\n\n# Only copy the compiled assets and production dependencies\nCOPY --from=builder \/app\/dist .\/dist\nCOPY --from=builder \/app\/node_modules .\/node_modules\nCOPY package*.json .\/\n\n# Look at that. No build tools. No source code. No junk.\nCMD [&quot;node&quot;, &quot;dist\/main.js&quot;]\n<\/code><\/pre>\n<p>Using <code>dive<\/code> on the new image shows a reduction from 2.84GB to 162MB. The <code>overlay2<\/code> driver no longer has to manage 15 layers of garbage. We are copying only what is necessary for execution. This is not a suggestion; it is a requirement for survival.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"3_The_Security_Theater_of_Root_Containers\"><\/span>3. The Security Theater of Root Containers<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Every single container in our cluster was running as <code>root<\/code>. If an attacker exploits a vulnerability in the application, they aren&#8217;t just a user; they are the superuser of that container&#8217;s namespace. If they find a way to escape the container, they are root on the host. <\/p>\n<p>A <strong>docker best<\/strong> practice that is ignored 90% of the time is the principle of least privilege. Most official images, including the Node Alpine image, already have a non-privileged user created (usually named <code>node<\/code>). Use it.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-3\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:20.11.0-alpine3.19\nWORKDIR \/app\nCOPY . .\n# Running as root by default. \n# If someone escapes the app, they own the container.\nCMD [&quot;node&quot;, &quot;index.js&quot;]\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-3\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:20.11.0-alpine3.19\n# Create a dedicated group and user if the base image doesn't have one\n# But for Node Alpine, 'node' user (UID 1000) already exists.\n\nWORKDIR \/app\n\n# Ensure the app directory is owned by our non-root user\nCOPY --chown=node:node --from=builder \/app\/dist .\/dist\nCOPY --chown=node:node --from=builder \/app\/node_modules .\/node_modules\n\nUSER node\n\n# Now, even if the app is compromised, the attacker is trapped in a \n# low-privilege shell with no ability to install packages or modify system files.\nCMD [&quot;node&quot;, &quot;dist\/main.js&quot;]\n<\/code><\/pre>\n<p>I shouldn&#8217;t have to explain why <code>sudo<\/code> doesn&#8217;t belong in a container. If your application needs to modify the host&#8217;s network stack or mount filesystems, you aren&#8217;t building a container; you&#8217;re building a security nightmare.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"4_Cache_Invalidation_and_the_Order_of_Operations\"><\/span>4. Cache Invalidation and the Order of Operations<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>The build logs showed <code>COPY . .<\/code> happening before <code>npm install<\/code>. This is why the build took 7 minutes every time someone changed a single comment in a README file. Docker&#8217;s layer caching is based on the checksum of the files being copied. If you copy the entire directory, any change to any file invalidates the cache for that layer and every subsequent layer.<\/p>\n<p>To adhere to <strong>docker best<\/strong> practices, you must copy your dependency manifests <em>first<\/em>, install your dependencies, and <em>then<\/em> copy your source code.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-4\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:20.11.0-alpine3.19\nWORKDIR \/app\nCOPY . . \nRUN npm install # This runs EVERY time any file changes.\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-4\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">FROM node:20.11.0-alpine3.19\nWORKDIR \/app\n\n# Copy only the files that define dependencies\nCOPY package*.json .\/\n\n# This layer is cached unless package.json or package-lock.json changes\nRUN npm ci --only=production\n\n# Now copy the rest of the source. \n# Changes here won't trigger a re-install of node_modules.\nCOPY . . \n<\/code><\/pre>\n<p>This simple reordering reduced our CI build time from 7 minutes to 45 seconds. We are no longer wasting CPU cycles on the build farm re-downloading the internet for every minor commit. <\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"5_The_dockerignore_Void\"><\/span>5. The .dockerignore Void<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Why was the image 2.84GB? Because the build context included the <code>.git<\/code> folder, the local <code>node_modules<\/code>, the <code>dist<\/code> folder from the developer&#8217;s machine, and a 1GB <code>test-data.log<\/code> file that someone forgot to delete. <\/p>\n<p>When you run <code>docker build<\/code>, the first thing the CLI does is &#8220;Sending build context to Docker daemon.&#8221; If you don&#8217;t have a <code>.dockerignore<\/code> file, you are sending every piece of junk in your project folder over the socket.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-5\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>(No <code>.dockerignore<\/code> file exists. The daemon receives 2GB of data before the build even starts.)<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-5\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Create a <code>.dockerignore<\/code> file. It is as important as the Dockerfile itself.<\/p>\n<pre class=\"codehilite\"><code class=\"language-text\"># .dockerignore\n.git\nnode_modules\nnpm-debug.log\ndist\nDockerfile\n.dockerignore\n.env\n.aws\ntests\/\ndocs\/\n*.md\n<\/code><\/pre>\n<p>By excluding these, the build context drops from gigabytes to kilobytes. The <strong>docker best<\/strong> approach is to be subtractive. If the container doesn&#8217;t need it to run, it doesn&#8217;t belong in the context.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"6_PID_1_and_the_Zombie_Process_Apocalypse\"><\/span>6. PID 1 and the Zombie Process Apocalypse<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>In Linux, PID 1 is the init process. It has two jobs: reaping orphaned child processes and handling signals like <code>SIGTERM<\/code> and <code>SIGINT<\/code>. Node.js, Python, and Java were not designed to run as PID 1. They don&#8217;t reap zombies, and they often ignore signals.<\/p>\n<p>When I tried to stop the failing containers last night, they took 30 seconds to die. Why? Because they ignored <code>SIGTERM<\/code>, and Kubernetes eventually had to <code>SIGKILL<\/code> them. This leads to data corruption and unclean shutdowns.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-6\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\"># Node runs as PID 1. It doesn't know how to handle signals properly.\nCMD [&quot;node&quot;, &quot;index.js&quot;]\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-6\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Use a minimal init system like <code>tini<\/code>. It is included in many base images or can be added easily. It handles the signal forwarding and zombie reaping so your app doesn&#8217;t have to.<\/p>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\"># Install tini\nRUN apk add --no-cache tini\nENTRYPOINT [&quot;\/sbin\/tini&quot;, &quot;--&quot;]\n\n# Now node runs as a child of tini\nCMD [&quot;node&quot;, &quot;dist\/main.js&quot;]\n<\/code><\/pre>\n<p>Alternatively, use the <code>--init<\/code> flag at runtime, but for production-grade <strong>docker best<\/strong> compliance, bake it into the image or use a base image that handles it.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"7_The_Filesystem_Truth_ADD_vs_COPY\"><\/span>7. The Filesystem Truth: ADD vs COPY<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>I saw <code>ADD<\/code> being used to move local files. Stop it. <code>ADD<\/code> is a complex command that can fetch remote URLs and extract tarballs automatically. It is unpredictable and carries security risks (like Zip Slip vulnerabilities). <\/p>\n<p>Unless you are specifically pulling a remote tarball and want it extracted in one go, use <code>COPY<\/code>. It is transparent. It is simple. It is the <strong>docker best<\/strong> practice for a reason.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"The_Sin-7\"><\/span>The Sin<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\">ADD my-app.tar.gz \/app\/\nADD https:\/\/internal-tool.com\/binary \/usr\/local\/bin\/tool\n<\/code><\/pre>\n<h3><span class=\"ez-toc-section\" id=\"The_Penance-7\"><\/span>The Penance<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<pre class=\"codehilite\"><code class=\"language-dockerfile\"># Be explicit.\nCOPY my-app.tar.gz \/tmp\/\nRUN tar -xzf \/tmp\/my-app.tar.gz -C \/app\/ &amp;&amp; rm \/tmp\/my-app.tar.gz\n\n# Use curl for remote files so you can check checksums and handle errors\nRUN apk add --no-cache curl \\\n    &amp;&amp; curl -sSL https:\/\/internal-tool.com\/binary -o \/usr\/local\/bin\/tool \\\n    &amp;&amp; chmod +x \/usr\/local\/bin\/tool \\\n    &amp;&amp; apk del curl\n<\/code><\/pre>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"The_Anatomy_of_the_Overlay2_Failure\"><\/span>The Anatomy of the Overlay2 Failure<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Let&#8217;s talk about why the disk filled up. Docker uses a storage driver, usually <code>overlay2<\/code>, to manage the layers. Each layer is a directory on the host&#8217;s filesystem (usually under <code>\/var\/lib\/docker\/overlay2<\/code>). When you write a file in a container, it uses a &#8220;copy-on-write&#8221; strategy. <\/p>\n<p>If you have a 1GB log file in your image and you run <code>RUN rm \/app\/log.file<\/code>, the file is &#8220;deleted&#8221; in the new layer, but it still exists in the previous layer. The total disk usage is still 1GB plus the metadata for the deletion. <\/p>\n<p>This is why the &#8220;Sin&#8221; Dockerfile was so lethal.<br \/>\n1. <code>COPY . .<\/code> brought in 1GB of junk. (Layer 1: +1GB)<br \/>\n2. <code>RUN npm install<\/code> added 800MB of modules. (Layer 2: +800MB)<br \/>\n3. <code>RUN npm run build<\/code> added 200MB of assets. (Layer 3: +200MB)<\/p>\n<p>Even if the final stage only needed 200MB, the host was storing 2GB for every single version of that image. Multiply that by 10 microservices and 5 previous versions kept for rollbacks, and you have a disk-space catastrophe.<\/p>\n<hr \/>\n<h2><span class=\"ez-toc-section\" id=\"Checklist_for_the_Uninitiated\"><\/span>Checklist for the Uninitiated<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>If you are going to push code to my cluster, you will verify the following. I will not ask twice.<\/p>\n<ol>\n<li><strong>Is the base image pinned?<\/strong> No <code>latest<\/code>. No <code>major<\/code> version tags only. Use <code>node:20.11.0-alpine3.19<\/code>.<\/li>\n<li><strong>Is it multi-stage?<\/strong> If your final image contains a compiler, a git client, or a package manager cache, you failed.<\/li>\n<li><strong>Is it non-root?<\/strong> Check <code>docker inspect<\/code> on your image. If <code>\"User\": \"\"<\/code> or <code>\"User\": \"root\"<\/code>, fix it.<\/li>\n<li><strong>Is there a .dockerignore?<\/strong> If you are sending your <code>.git<\/code> folder to the daemon, you are doing it wrong.<\/li>\n<li><strong>Are the layers ordered for caching?<\/strong> Manifests first, then install, then code.<\/li>\n<li><strong>Is PID 1 handled?<\/strong> Use <code>tini<\/code> or a similar init process.<\/li>\n<li><strong>Is the image size reasonable?<\/strong> If a microservice is over 200MB, you better have a damn good reason (like a machine learning model).<\/li>\n<\/ol>\n<p>I am going to sleep for four hours. When I wake up, I expect to see the image sizes in the registry trending downward. If I see another 2GB image, I am revoking your <code>docker push<\/code> permissions and you can go back to deploying via FTP like it&#8217;s 1999. <\/p>\n<p>The grave is deep enough. Stop digging.<\/p>\n<h2><span class=\"ez-toc-section\" id=\"Related_Articles\"><\/span>Related Articles<span class=\"ez-toc-section-end\"><\/span><\/h2>\n<p>Explore more insights and best practices:<\/p>\n<ul>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/how-to-upgrade-to-python-3-9-0-on-ubuntu-18-04-lts\/\">How To Upgrade To Python 3 9 0 On Ubuntu 18 04 Lts<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/fixed-nginx-showing-blank-php-pages-with-fastcgi-or-php-fpm\/\">Fixed Nginx Showing Blank Php Pages With Fastcgi Or Php Fpm<\/a><\/li>\n<li><a href=\"https:\/\/itsupportwale.com\/blog\/install-and-secure-phpmyadmin-with-nginx-on-ubuntu-18-04\/\">Install And Secure Phpmyadmin With Nginx On Ubuntu 18 04<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>The Grave We Dug with Default Dockerfiles A Technical Post-Mortem and Remediation Guide $ docker build -t api-service:latest . [+] Building 412.4s (9\/12) =&gt; [internal] load build definition from Dockerfile 0.1s =&gt; [internal] load .dockerignore 0.1s =&gt; [internal] load metadata for docker.io\/library\/node:latest 1.2s =&gt; [1\/8] FROM docker.io\/library\/node:latest 0.0s =&gt; [2\/8] WORKDIR \/app 0.5s =&gt; [3\/8] &#8230; <a title=\"Docker Best Practices: Build Production-Ready Containers\" class=\"read-more\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\" aria-label=\"Read more  on Docker Best Practices: Build Production-Ready Containers\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4497","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Docker Best Practices: Build Production-Ready Containers - ITSupportWale<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Docker Best Practices: Build Production-Ready Containers - ITSupportWale\" \/>\n<meta property=\"og:description\" content=\"The Grave We Dug with Default Dockerfiles A Technical Post-Mortem and Remediation Guide $ docker build -t api-service:latest . [+] Building 412.4s (9\/12) =&gt; [internal] load build definition from Dockerfile 0.1s =&gt; [internal] load .dockerignore 0.1s =&gt; [internal] load metadata for docker.io\/library\/node:latest 1.2s =&gt; [1\/8] FROM docker.io\/library\/node:latest 0.0s =&gt; [2\/8] WORKDIR \/app 0.5s =&gt; [3\/8] ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\" \/>\n<meta property=\"og:site_name\" content=\"ITSupportWale\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-09T16:05:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Techie\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Techie\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\"},\"author\":{\"name\":\"Techie\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\"},\"headline\":\"Docker Best Practices: Build Production-Ready Containers\",\"datePublished\":\"2026-02-09T16:05:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\"},\"wordCount\":1442,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\",\"name\":\"Docker Best Practices: Build Production-Ready Containers - ITSupportWale\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\"},\"datePublished\":\"2026-02-09T16:05:15+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/itsupportwale.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Docker Best Practices: Build Production-Ready Containers\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"name\":\"ITSupportWale\",\"description\":\"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\",\"name\":\"itsupportwale\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"contentUrl\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"width\":1119,\"height\":144,\"caption\":\"itsupportwale\"},\"image\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\",\"name\":\"Techie\",\"sameAs\":[\"https:\/\/itsupportwale.com\",\"iswblogadmin\"],\"url\":\"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Docker Best Practices: Build Production-Ready Containers - ITSupportWale","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/","og_locale":"en_US","og_type":"article","og_title":"Docker Best Practices: Build Production-Ready Containers - ITSupportWale","og_description":"The Grave We Dug with Default Dockerfiles A Technical Post-Mortem and Remediation Guide $ docker build -t api-service:latest . [+] Building 412.4s (9\/12) =&gt; [internal] load build definition from Dockerfile 0.1s =&gt; [internal] load .dockerignore 0.1s =&gt; [internal] load metadata for docker.io\/library\/node:latest 1.2s =&gt; [1\/8] FROM docker.io\/library\/node:latest 0.0s =&gt; [2\/8] WORKDIR \/app 0.5s =&gt; [3\/8] ... Read more","og_url":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/","og_site_name":"ITSupportWale","article_publisher":"https:\/\/www.facebook.com\/Itsupportwale-298547177495978","article_published_time":"2026-02-09T16:05:15+00:00","og_image":[{"width":512,"height":512,"url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png","type":"image\/png"}],"author":"Techie","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Techie","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#article","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/"},"author":{"name":"Techie","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d"},"headline":"Docker Best Practices: Build Production-Ready Containers","datePublished":"2026-02-09T16:05:15+00:00","mainEntityOfPage":{"@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/"},"wordCount":1442,"commentCount":0,"publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/","url":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/","name":"Docker Best Practices: Build Production-Ready Containers - ITSupportWale","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/#website"},"datePublished":"2026-02-09T16:05:15+00:00","breadcrumb":{"@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/itsupportwale.com\/blog\/docker-best-practices-build-production-ready-containers\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/itsupportwale.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Docker Best Practices: Build Production-Ready Containers"}]},{"@type":"WebSite","@id":"https:\/\/itsupportwale.com\/blog\/#website","url":"https:\/\/itsupportwale.com\/blog\/","name":"ITSupportWale","description":"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides","publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/itsupportwale.com\/blog\/#organization","name":"itsupportwale","url":"https:\/\/itsupportwale.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","contentUrl":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","width":1119,"height":144,"caption":"itsupportwale"},"image":{"@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Itsupportwale-298547177495978"]},{"@type":"Person","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d","name":"Techie","sameAs":["https:\/\/itsupportwale.com","iswblogadmin"],"url":"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4497","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/comments?post=4497"}],"version-history":[{"count":0,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4497\/revisions"}],"wp:attachment":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/media?parent=4497"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/categories?post=4497"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/tags?post=4497"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}