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

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more

Top comments (0)

The Most Contextual AI Development Assistant

Pieces.app image

Our centralized storage agent works on-device, unifying various developer tools to proactively capture and enrich useful materials, streamline collaboration, and solve complex problems through a contextual understanding of your unique workflow.

👥 Ideal for solo developers, teams, and cross-company projects

Learn more

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️