D7.3 Docker Volumes — Θεωρία για Ansible Users 💾

Το πρόβλημα

Τα Docker containers είναι ephemeral — όταν σταματήσουν ή διαγραφούν, χάνουν τα δεδομένα τους. Για persistent data χρειάζεσαι volumes.

📝 Αναλογία με Ansible:

Ansible facts cache:
  Αποθηκεύεις facts → τα βρίσκεις αύριο ✅

Docker container χωρίς volume:
  Γράφεις σε /var/lib/postgresql/data → διαγράφεται το container → χάθηκε ❌

Docker container με volume:
  Γράφεις σε /var/lib/postgresql/data → διαγράφεται το container → τα δεδομένα μένουν ✅

Οι 3 τρόποι αποθήκευσης

┌─────────────────────────────────────────────────────────┐
│                                                         │
│  1. Named Volumes                                       │
│  ───────────────                                        │
│  Docker Host                                            │
│  /var/lib/docker/volumes/my_volume/_data                │
│           │                                             │
│           └──────────────► Container /data              │
│                                                         │
│  ✅ Managed by Docker                                   │
│  ✅ Portable                                            │
│  ✅ Best practice για databases                         │
│                                                         │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  2. Bind Mounts                                         │
│  ─────────────                                          │
│  Docker Host                                            │
│  /opt/myapp/config/nginx.conf                           │
│           │                                             │
│           └──────────────► Container /etc/nginx/nginx.conf
│                                                         │
│  ✅ Πλήρης έλεγχος αρχείων από host                    │
│  ✅ Best practice για config files                      │
│  ❌ Host-specific (δεν είναι portable)                  │
│                                                         │
├─────────────────────────────────────────────────────────┤
│                                                         │
│  3. tmpfs Mounts                                        │
│  ──────────────                                         │
│  RAM (εξαφανίζεται με reboot/stop)                      │
│           │                                             │
│           └──────────────► Container /tmp               │
│                                                         │
│  ✅ Πολύ γρήγορο                                       │
│  ✅ Ευαίσθητα δεδομένα (δεν γράφονται σε disk)         │
│  ❌ Δεν είναι persistent                                │
└─────────────────────────────────────────────────────────┘

Named Volumes vs Bind Mounts — Πότε τι

Named Volumes:
✅ Database data (postgres, mysql, redis)
✅ Application data (uploads, media files)
✅ Logs που πρέπει να επιβιώνουν restarts
✅ Shared data μεταξύ containers
❌ Configuration files (αλλαγές δύσκολες)

Bind Mounts:
✅ Configuration files (nginx.conf, app.env)
✅ SSL certificates
✅ Development (live code reload)
✅ Static web content
❌ Database data (permissions, ownership issues)

tmpfs:
✅ Sensitive env variables
✅ Cache που δεν χρειάζεται persistence
✅ High-performance temp storage
❌ Οτιδήποτε χρειάζεσαι μετά reboot

Volume syntax στο docker_container

tasks:

  - name: Container με volumes
    community.docker.docker_container:
      name:  myapp
      image: myapp:latest
      volumes:
        # ── Named volume ──────────────────────
        - "db_data:/var/lib/postgresql/data"
        #   ↑ volume name    ↑ container path

        # ── Bind mount (read-write) ───────────
        - "/opt/myapp/config:/etc/myapp:rw"
        #   ↑ host path      ↑ container  ↑ mode

        # ── Bind mount (read-only) ────────────
        - "/etc/ssl/certs:/etc/ssl/certs:ro"
        #   ↑ host certs     ↑ container  ↑ readonly!

        # ── tmpfs mount ───────────────────────
        - "tmpfs:/tmp"
        #  ↑ keyword  ↑ container path

Volume ownership & permissions

Ένα από τα πιο συνηθισμένα προβλήματα:

Πρόβλημα:
  Δημιουργείς named volume → Docker το κατέχει ως root
  App τρέχει ως user 1000  → PermissionError! ❌

Λύση 1: init container
  Τρέξε μια φορά: chown 1000:1000 /data

Λύση 2: Ansible preinit
  Δημιούργησε το directory στον host με τα σωστά permissions
  ΠΡΙΝ το bind mount

Λύση 3: Docker entrypoint
  Το image διορθώνει permissions στο startup
tasks:

  # ── Λύση 2: Ansible preinit ───────────────
  - name: Δημιουργία data directory με σωστά permissions
    ansible.builtin.file:
      path:  /opt/myapp/data
      state: directory
      owner: "1000"      # ← app user UID
      group: "1000"
      mode:  '0750'

  - name: Deploy container με bind mount
    community.docker.docker_container:
      name:  myapp
      image: myapp:latest
      volumes:
        - "/opt/myapp/data:/app/data:rw"    # ← σωστά permissions ✅
      user: "1000:1000"    # ← container user

Volume sharing μεταξύ containers

tasks:

  # ── Shared volume: app + backup ───────────
  - name: App container
    community.docker.docker_container:
      name:    myapp
      image:   myapp:latest
      state:   started
      volumes:
        - "app_data:/app/data:rw"     # ← read-write

  - name: Backup sidecar container
    community.docker.docker_container:
      name:    backup_agent
      image:   "restic:latest"
      state:   started
      volumes:
        - "app_data:/data:ro"         # ← read-only ✅
        - "backup_target:/backup:rw"
      # ↑ backup agent διαβάζει app data
      #   αλλά ΔΕΝ μπορεί να γράψει σε αυτά

Σύνοψη D7.3

Docker Volumes — Θεωρία
│
├── 3 τύποι:
│   ├── Named volumes → managed by Docker
│   │   └── Syntax: "volume_name:/container/path"
│   ├── Bind mounts  → host directory/file
│   │   └── Syntax: "/host/path:/container/path:ro|rw"
│   └── tmpfs        → RAM only
│       └── Syntax: "tmpfs:/container/path"
│
├── Πότε τι:
│   ├── Database data  → named volume ✅
│   ├── Config files   → bind mount ✅
│   └── Temp/secrets   → tmpfs ✅
│
├── Permissions:
│   ├── Named volumes → Docker (root) κατέχει
│   └── Preinit με Ansible → file module πριν mount
│
└── Sharing:
    └── Πολλά containers → ίδιο volume
        (app: rw, backup: ro)