DEV Community

Cover image for Day 7: Docker Volumes
Jonas Scholz
Jonas Scholz Subscriber

Posted on • Originally published at adventofdocker.com

Day 7: Docker Volumes

This is a crosspost from adventofdocker.com

Yesterday we learned that containers are ephemeral - any changes made inside a container are lost when it stops. But what if you need to persist data? That's where volumes come in!

Let's modify our HTTP server to save some data:

package main

import (
    "fmt"
    "net/http"
    "os"
    "time"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        // Record new visit
        timestamp := time.Now().Format(time.RFC3339) + "\n"
        os.MkdirAll("data", 0755)
        f, _ := os.OpenFile("data/visits.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
        f.WriteString(timestamp)
        f.Close()

        // Read and display all visits
        data, err := os.ReadFile("data/visits.txt")
        if err != nil {
            fmt.Fprintf(w, "Error reading visits!")
            return
        }

        fmt.Fprintf(w, "New visit recorded at %s\n\nAll visits:\n%s", timestamp, string(data))
    })

    fmt.Println("Listening on port 8080")
    http.ListenAndServe(":8080", nil)
}
Enter fullscreen mode Exit fullscreen mode

Our Dockerfile stays the same:

FROM golang
COPY . .
RUN go build -o main main.go
EXPOSE 8080
CMD ["./main"]
Enter fullscreen mode Exit fullscreen mode

Let's build and run it:

$ docker build -t hello-world-go .
$ docker run -p 8080:8080 hello-world-go
Enter fullscreen mode Exit fullscreen mode

When you visit localhost:8080, each visit gets recorded and displayed. However, if you stop and restart the container, all your visits are gone! This is because containers are ephemeral - any changes made inside them are lost when they stop.

Solving with Docker Volumes

We can fix this by using volumes. First, create a named volume:

$ docker volume create mydata
Enter fullscreen mode Exit fullscreen mode

Now run the container with the volume mounted:

$ docker run -p 8080:8080 -v mydata:/data hello-world-go
Enter fullscreen mode Exit fullscreen mode

The -v mydata:/data flag mounts our volume named mydata to the /data directory inside the container. Try it out:

  1. Visit localhost:8080 a few times - you'll see the list grow with each visit
  2. Stop the container with docker stop <container_id>
  3. Start a new container with the same volume:
$ docker run -p 8080:8080 -v mydata:/data hello-world-go
Enter fullscreen mode Exit fullscreen mode

Your visits are still there! The data persists even when containers are stopped or removed.

Managing Volumes

List all volumes:

$ docker volume ls
DRIVER VOLUME NAME
local mydata
Enter fullscreen mode Exit fullscreen mode

Inspect a volume:

$ docker volume inspect mydata
[
    {
        "CreatedAt": "2024-12-07T...",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/mydata/_data",
        "Name": "mydata",
        "Options": {},
        "Scope": "local"
    }
]
Enter fullscreen mode Exit fullscreen mode

Remove a volume:

$ docker volume rm mydata
Enter fullscreen mode Exit fullscreen mode

You can also use anonymous volumes by omitting the volume name:

$ docker run -v /data hello-world-go
Enter fullscreen mode Exit fullscreen mode

Docker will create a random volume name for you. These are harder to manage but useful for temporary data.

Bind Mounts

Instead of using a Docker-managed volume, you can mount a directory from your host directly:

$ docker run -v $(pwd)/data:/data hello-world-go
Enter fullscreen mode Exit fullscreen mode

This mounts the ./data directory from your current location into the container. Great for development, I recommend reading more about bind mounts here.

That's it for today! Tomorrow we'll have our first quiz to test what you've learned this week. Make sure you're comfortable with:

  • Basic Docker commands
  • Building images
  • Running containers
  • Port mapping
  • Layers
  • Volumes

Until then, happy coding! 🐳🎄

Jonas

Top comments (0)