title: What is the practical purpose of VOLUME in Dockerfile?
body: <p>First of all, I want to make it clear I've done due diligence in researching this topic. Very closely related is <a href="https://stackoverflow.com/questions/34809646/what-is-the-purpose-of-volume-in-dockerfile">this SO question</a>, which doesn't really address my confusion.</p>
  
  <p>I understand that when <code>VOLUME</code> is specified in a Dockerfile, this instructs Docker to create an unnamed volume for the duration of the container which is mapped to the specified directory inside of it. For example:</p>
  
  <pre><code># Dockerfile
  VOLUME ["/foo"]
  </code></pre>
  
  <p>This would create a volume to contain any data stored in <code>/foo</code> inside the container. The volume (when viewed via <code>docker volume ls</code>) would show up as a random jumble of numbers.</p>
  
  <p>Each time you do <code>docker run</code>, this volume is not reused. This is the key point causing confusion here. To me, the goal of a volume is to contain state persistent across <em>all instances</em> of an image (all containers started from it). So basically if I do this, <em>without explicit volume mappings</em>:</p>
  
  <pre><code>#!/usr/bin/env bash
  # Run container for the first time
  docker run -t foo
  
  # Kill the container and re-run it again. Note that the previous 
  # volume would now contain data because services running in `foo`
  # would have written data to that volume.
  docker container stop foo
  docker container rm foo
  
  # Run container a second time
  docker run -t foo
  </code></pre>
  
  <p>I expect the unnamed volume to be reused between the 2 <code>run</code> commands. However, this is not the case. Because I did not explicitly map a volume via the <code>-v</code> option, a new volume is created for each <code>run</code>.</p>
  
  <p>Here's important part number 2: Since I'm required to explicitly specify <code>-v</code> to share persistent state between <code>run</code> commands, why would I ever specify <code>VOLUME</code> in my Dockerfile? Without <code>VOLUME</code>, I can do this (using the previous example):</p>
  
  <pre><code>#!/usr/bin/env bash
  # Create a volume for state persistence
  docker volume create foo_data
  
  # Run container for the first time
  docker run -t -v foo_data:/foo foo
  
  # Kill the container and re-run it again. Note that the previous 
  # volume would now contain data because services running in `foo`
  # would have written data to that volume.
  docker container stop foo
  docker container rm foo
  
  # Run container a second time
  docker run -t -v foo_data:/foo foo
  </code></pre>
  
  <p>Now, truly, the second container will have data mounted to <code>/foo</code> that was there from the previous instance. I can do this without <code>VOLUME</code> in my Dockerfile. From the command line, I can turn any directory inside the container into a mount to either a bound directory on the host or a volume in Docker.</p>
  
  <p>So my question is: What is the point of <code>VOLUME</code> when you have to explicitly map named volumes to containers via commands on the host anyway? Either I'm missing something or this is just confusing and obfuscated.</p>
  
  <p>Note that all of my assertions here are based on my observations of how docker behaves, as well as what I've gathered from the documentation.</p>