DEV Community

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

Posted on • Originally published at adventofdocker.com

12 3 3 3 3

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

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Explore a sea of insights with this enlightening post, highly esteemed within the nurturing DEV Community. Coders of all stripes are invited to participate and contribute to our shared knowledge.

Expressing gratitude with a simple "thank you" can make a big impact. Leave your thanks in the comments!

On DEV, exchanging ideas smooths our way and strengthens our community bonds. Found this useful? A quick note of thanks to the author can mean a lot.

Okay