<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Docker best practices - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Docker best practices - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 07 Jun 2026 22:34:43 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/docker-best-practices/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Docker Remove Image: How to Delete Docker Images Explained with Examples ]]>
                </title>
                <description>
                    <![CDATA[ By Marcelo Costa We live in an era where storage is becoming cheaper everyday. We can just send everything to the cloud and pay almost nothing. So why would we need to worry about deleting Docker images? First of all, there are still some mission cri... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/docker-remove-image-how-to-delete-docker-images-explained-with-examples/</link>
                <guid isPermaLink="false">66d851bcbdc56847ac959f42</guid>
                
                    <category>
                        <![CDATA[ Docker best practices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Docker ]]>
                    </category>
                
                    <category>
                        <![CDATA[ docker image ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 22 Jul 2020 21:45:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2020/07/DockerErase3.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Marcelo Costa</p>
<p>We live in an era where storage is becoming cheaper everyday. We can just send everything to the cloud and pay almost nothing.</p>
<p>So why would we need to worry about deleting Docker images?</p>
<p>First of all, there are still some mission critical workloads that can't be moved to the cloud, especially those in heavily regulated industries like law or healthcare.  </p>
<p>But to better answer that question, I would say that we as developers often find ourselves out of space on our local machines.</p>
<p> Let's do a quick analysis of this <a target="_blank" href="https://cloud.google.com/blog/products/gcp/google-bigquery-public-datasets-now-include-stack-overflow-q-a">StackOverflow public dataset</a> to explore that further:</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> tag,
       title,
       answer_count,
       favorite_count,
       score,
       view_count VIEWS
<span class="hljs-keyword">FROM</span>
  (<span class="hljs-keyword">SELECT</span> title,
          answer_count,
          favorite_count,
          view_count,
          score,
          <span class="hljs-keyword">SPLIT</span>(tags, <span class="hljs-string">'|'</span>) tags
   <span class="hljs-keyword">FROM</span> <span class="hljs-string">`bigquery-public-data.stackoverflow.posts_questions`</span> 
         posts_questions), <span class="hljs-keyword">UNNEST</span>(tags) tag
<span class="hljs-keyword">WHERE</span> tag = <span class="hljs-string">'docker'</span>
  <span class="hljs-keyword">AND</span> title <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%space left%'</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> VIEWS <span class="hljs-keyword">DESC</span>
</code></pre>
<p><strong>Query Results:</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2020/07/Screen-Shot-2020-07-21-at-2.11.43-PM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>So it does't happen just with me, right? Look at how many views we have on those StackOverflow posts. If you are wondering, the number is <strong>465687</strong> views for posts matching the search query.</p>
<p>Luckily for us, today we are going to see some <strong>easy-to-use</strong> examples on how to delete our dangling and unused docker images to help ourselves out. </p>
<h2 id="heading-what-are-dangling-and-unused-docker-images">What are dangling and unused Docker images?</h2>
<div>
<img src="https://www.freecodecamp.org/news/content/images/2020/07/hanging3.png" alt="drawing" width="600" height="400" loading="lazy">
</div>

<p>What is the difference between dangling and unused images, you might ask?</p>
<p>A dangling image means that you've created a new build of the image but haven't given it a new name. Think about those old, forgotten images that no one knows what to do with anymore – those are "dangling images". </p>
<p>They are left untagged and display <code>&lt;none&gt;</code> on their name when you run <code>docker images</code>.</p>
<p>On the other hand, an unused image means that it has not been assigned or is not being used in a container. </p>
<p>For example, when running <code>docker ps -a</code> – it will list all your currently running containers plus exited containers. Any images being used inside any of containers are shown as "used images", and any others are unused.</p>
<h2 id="heading-delete-docker-images">Delete Docker Images</h2>
<p>Now let's see some examples of how to delete Docker images.</p>
<h3 id="heading-our-case-study">Our case study</h3>
<div>
<img src="https://www.freecodecamp.org/news/content/images/2020/07/busyCat.png" alt="drawing" width="600" height="400" loading="lazy">
</div>

<p>The Busy Cat Corp is a fictional company that captures cat behavior data, and provides recommendations to cat owners on how to make their pets busier and happier.  </p>
<p>All their workloads are containerized, and they use the following database images:<br><a target="_blank" href="https://hub.docker.com/_/cassandra">cassandra</a>, <a target="_blank" href="https://hub.docker.com/_/postgres">postgres</a>, <a target="_blank" href="https://hub.docker.com/_/mysql">mysql</a> and <a target="_blank" href="https://hub.docker.com/_/mongo">mongo</a>.</p>
<p>Their developers are constantly running out of space on their machines, and they are top users of StackOverflow – aren't we all?  </p>
<p>So they asked us for some quick examples of how to delete some images and get their space back.</p>
<p>First let's take a look at the machine of one of their developers.</p>
<pre><code class="lang-bash">docker images
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">REPOSITORY  TAG          IMAGE ID            CREATED              SIZE
&lt;none&gt;       &lt;none&gt;      9c872a6119cc        About a minute ago   384MB
mysql        latest      5ac22cccc3ae        43 hours ago         544MB
cassandra    3           9fab0c92a93d        4 days ago           384MB
adoptopenjdk 8-jre...    2bf0172ac69b        4 days ago           210MB
mongo        latest      6d11486a97a7        2 weeks ago          388MB
postgres     latest      b97bae343e06        6 weeks ago          313MB
</code></pre>
<p>That's cool, they have all the images from their workloads downloaded. But look at the disk space – it's more than <strong>2GB</strong>! Let's see what we can do for them.</p>
<h3 id="heading-delete-docker-dangling-images">Delete Docker dangling images</h3>
<p>We'll start by looking for dangling images.</p>
<pre><code>docker images -qf <span class="hljs-string">"dangling=true"</span>
</code></pre><p><strong>Output</strong></p>
<pre><code class="lang-bash">REPOSITORY  TAG          IMAGE ID            CREATED              SIZE
&lt;none&gt;       &lt;none&gt;      9c872a6119cc        About a minute ago   384MB
</code></pre>
<p>We have one, so we are going to clear it up.</p>
<p><strong>Delete the dangling image</strong></p>
<pre><code>docker rmi $(docker images -qf <span class="hljs-string">"dangling=true"</span>)
</code></pre><div>
<img src="https://www.freecodecamp.org/news/content/images/2020/06/flamenco-done.png" alt="drawing" width="600" height="400" loading="lazy">
</div>

<h3 id="heading-delete-docker-unused-images">Delete Docker unused images</h3>
<p>Next we are looking for unused images.</p>
<pre><code>docker ps -a
</code></pre><p><strong>Output</strong></p>
<pre><code class="lang-bash">CONTAINER ID  IMAGE   CREATED           NAMES
b6387b343b81  mysql   16 minutes ago    some-mysql
</code></pre>
<p>We only have one container running the  <code>mysql</code>  image, so all the other images are unused. </p>
<p>So that we don't have to do it manually, we can put together a script that shows all of the unused images to verify them.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Get all the images currently in use</span>
USED_IMAGES=($( \
    docker ps -a --format <span class="hljs-string">'{{.Image}}'</span> | \
    sort -u | \
    uniq | \
    awk -F <span class="hljs-string">':'</span> <span class="hljs-string">'$2{print $1":"$2}!$2{print $1":latest"}'</span> \
))

<span class="hljs-comment"># Get all the images currently available</span>
ALL_IMAGES=($( \
    docker images --format <span class="hljs-string">'{{.Repository}}:{{.Tag}}'</span> | \
    sort -u \
))

<span class="hljs-comment"># Print the unused images</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">${ALL_IMAGES[@]}</span>"</span>; <span class="hljs-keyword">do</span>
    UNUSED=<span class="hljs-literal">true</span>
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-string">"<span class="hljs-variable">${USED_IMAGES[@]}</span>"</span>; <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">if</span> [[ <span class="hljs-string">"<span class="hljs-variable">$i</span>"</span> == <span class="hljs-string">"<span class="hljs-variable">$j</span>"</span> ]]; <span class="hljs-keyword">then</span>
            UNUSED=<span class="hljs-literal">false</span>
        <span class="hljs-keyword">fi</span>
    <span class="hljs-keyword">done</span>
    <span class="hljs-keyword">if</span> [[ <span class="hljs-string">"<span class="hljs-variable">$UNUSED</span>"</span> == <span class="hljs-literal">true</span> ]]; <span class="hljs-keyword">then</span>
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$i</span> is not being used."</span>
    <span class="hljs-keyword">fi</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">adoptopenjdk:8-jre-hotspot-bionic is not being used.
cassandra:3 is not being used.
mongo:latest is not being used.
postgres:latest is not being used.
</code></pre>
<p>Then it deletes the unused images.</p>
<pre><code># Get all the images currently <span class="hljs-keyword">in</span> use
USED_IMAGES=($( \
    docker ps -a --format <span class="hljs-string">'{{.Image}}'</span> | \
    sort -u | \
    uniq | \
    awk -F <span class="hljs-string">':'</span> <span class="hljs-string">'$2{print $1":"$2}!$2{print $1":latest"}'</span> \
))

# Get all the images currently available
ALL_IMAGES=($( \
    docker images --format <span class="hljs-string">'{{.Repository}}:{{.Tag}}'</span> | \
    sort -u \
))

# Remove the unused images
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-string">"${ALL_IMAGES[@]}"</span>; <span class="hljs-keyword">do</span>
    UNUSED=<span class="hljs-literal">true</span>
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-string">"${USED_IMAGES[@]}"</span>; <span class="hljs-keyword">do</span>
        <span class="hljs-keyword">if</span> [[ <span class="hljs-string">"$i"</span> == <span class="hljs-string">"$j"</span> ]]; then
            UNUSED=<span class="hljs-literal">false</span>
        fi
    done
    <span class="hljs-keyword">if</span> [[ <span class="hljs-string">"$UNUSED"</span> == <span class="hljs-literal">true</span> ]]; then
        docker rmi <span class="hljs-string">"$i"</span>
    fi
done
</code></pre><p>After deleting both dangling and unused images we can look at what we have left.</p>
<pre><code class="lang-bash">docker images
</code></pre>
<p><strong>Output</strong></p>
<pre><code class="lang-bash">REPOSITORY  TAG          IMAGE ID            CREATED              SIZE
mysql        latest      5ac22cccc3ae        43 hours ago         544MB
</code></pre>
<p>So we only have the <code>mysql</code>  image remaining, that's great!</p>
<div>
<img src="https://www.freecodecamp.org/news/content/images/2020/06/flamenco-done.png" alt="drawing" width="600" height="400" loading="lazy">
</div>

<h3 id="heading-delete-all-obsolete-docker-images-with-prune">Delete all obsolete Docker images with prune</h3>
<p>Those commands sound great, but a second developer said they didn't care about the differences between dangling and unused images. </p>
<p>All they wanted was to clear obsolete images and get their disk space back.</p>
<blockquote>
<p>Personally this is what I usually do.</p>
</blockquote>
<p>So we can just use Docker's prune commands.</p>
<pre><code># First <span class="hljs-keyword">delete</span> all stopped containers
docker container prune

# Then <span class="hljs-keyword">delete</span> both dangling and unused images
docker image prune --all
</code></pre><p>This will delete both unused and dangling images. Or in other words images without at least one container associated with them. </p>
<p>Note: this is why we needed to first delete the stopped containers in the code above.</p>
<h2 id="heading-wrapping-up"><strong>Wrapping </strong>up<em>**</em></h2>
<p>In this article we saw how to delete Docker Images, and we used a fictional company to explain it with some easy-to-use examples.</p>
<p>It's important to point out that you shouldn't use Docker to keep a history of your old images. For a developer environment that's fine, and you can even automate the image clean up workload if you have to deal with a lot of them. </p>
<p>But for a production workload, you should be using a Container Registry solution to handle your Docker images. </p>
<p>There are many Container Registry solutions out there, like Google Cloud Platform with <a target="_blank" href="https://cloud.google.com/artifact-registry">Artifact Registry</a> and Docker Enterprise with <a target="_blank" href="https://docs.mirantis.com/docker-enterprise/v3.0/dockeree-products/dtr.html">Docker Trusted Registry</a>. And if you are in the open source world, you can just use <a target="_blank" href="https://hub.docker.com/">Docker Hub</a> :).  </p>
<p>Thanks for reading!</p>
<ul>
<li>Illustrations from <a target="_blank" href="https://icons8.com/">Icons8</a></li>
</ul>
<p>If you found this helpful, or wish to challenge or extend anything raised here, feel free to contact me on <a target="_blank" href="https://twitter.com/mesmacosta">Twitter</a> or <a target="_blank" href="https://www.linkedin.com/in/mesmacosta">Linkedin</a>. Let's connect!</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
