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)