D2.2 Docker Daemon Configuration ⚙️

Τι είναι το Docker Daemon;

┌─────────────────────────────────────────────────────────┐
│  dockerd (Docker Daemon)                                │
│  ├── Background service που τρέχει πάντα                │
│  ├── Διαχειρίζεται: containers, images, networks,       │
│  │   volumes                                            │
│  ├── Ρυθμίζεται μέσω: /etc/docker/daemon.json           │
│  └── Systemd service: docker.service                    │
└─────────────────────────────────────────────────────────┘

/etc/docker/daemon.json — Οι ρυθμίσεις

{
  "log-driver":    "json-file",
  "log-opts": {
    "max-size":    "10m",
    "max-file":    "3"
  },
  "storage-driver": "overlay2",
  "data-root":     "/var/lib/docker",
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  },
  "live-restore":  true,
  "userland-proxy": false,
  "ipv6":          false,
  "dns":           ["8.8.8.8", "8.8.4.4"],
  "registry-mirrors": [],
  "insecure-registries": []
}

Ανάλυση κάθε ρύθμισης

Logging Configuration:

# Logging options
docker_daemon_logging:
  log-driver: json-file    # ← τύπος logging
  # Επιλογές: json-file, syslog, journald,
  #           gelf, fluentd, awslogs, splunk

  log-opts:
    max-size: "10m"        # ← max μέγεθος log file
    max-file: "3"          # ← max αριθμός log files
    # → 3 × 10MB = 30MB max per container
# Χωρίς ρύθμιση → logs μεγαλώνουν ασταμάτητα!
# Αφού ρυθμίσεις, έλεγξε:
docker info | grep "Logging Driver"
# Logging Driver: json-file ✅

Storage Driver:

# Storage driver — πώς αποθηκεύονται τα layers
docker_daemon_storage:
  storage-driver: overlay2    # ← συνιστάται για Linux
  # overlay2 → modern, fast, default σε νέα kernels
  # devicemapper → παλιό, αποφύγετε
  # btrfs → αν έχεις btrfs filesystem
  # aufs → παλιό Ubuntu

  data-root: /var/lib/docker  # ← πού αποθηκεύεται
  # Αλλαγή αν / partition είναι μικρό!
  # π.χ. data-root: /mnt/data/docker

Network Configuration:

docker_daemon_network:
  # DNS servers για containers
  dns:
    - "8.8.8.8"
    - "8.8.4.4"

  # Default bridge network subnet
  bip: "172.17.0.1/16"

  # IPv6 support
  ipv6: false

  # userland-proxy: false → καλύτερη performance
  userland-proxy: false

Registry Configuration:

docker_daemon_registry:
  # Mirror για Docker Hub (γρηγορότερο pull)
  registry-mirrors:
    - "https://mirror.example.com"

  # Private registry χωρίς SSL (dev μόνο!)
  insecure-registries:
    - "registry.local:5000"

Performance & Security:

docker_daemon_performance:
  # Κράτα containers ζωντανά αν daemon restarts
  live-restore: true        # ← ΠΑΝΤΑ true σε production!

  # Max open files per container
  default-ulimits:
    nofile:
      Name: nofile
      Hard: 64000
      Soft: 64000

  # Seccomp profile
  seccomp-profile: ""       # ← default profile

  # AppArmor (Ubuntu/Debian)
  apparmor: ""              # ← default profile

Πλήρες daemon.json ανά Περιβάλλον

Development:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "storage-driver": "overlay2",
  "live-restore":   true,
  "debug":          true,
  "insecure-registries": ["localhost:5000"]
}

Production:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "50m",
    "max-file": "5"
  },
  "storage-driver": "overlay2",
  "live-restore":   true,
  "userland-proxy": false,
  "ipv6":           false,
  "dns":            ["8.8.8.8", "8.8.4.4"],
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  },
  "features": {
    "buildkit": true
  }
}

Ansible Implementation

defaults/main.yml — Docker Daemon:

cat >> ~/ansible/roles/docker/defaults/main.yml << 'EOF'

# ── Daemon Configuration ──────────────────────
docker_daemon_config:
  # Logging
  log-driver: json-file
  log-opts:
    max-size: "{{ docker_log_max_size | default('10m') }}"
    max-file: "{{ docker_log_max_files | default('3') }}"

  # Storage
  storage-driver: overlay2

  # Data location
  data-root: "{{ docker_data_root | default('/var/lib/docker') }}"

  # Performance
  live-restore:    true
  userland-proxy:  false

  # Network
  ipv6: false
  dns:  "{{ docker_dns | default(['8.8.8.8', '8.8.4.4']) }}"

  # BuildKit
  features:
    buildkit: true

# ── Logging ───────────────────────────────────
docker_log_max_size:  "10m"
docker_log_max_files: "3"

# ── Data ──────────────────────────────────────
docker_data_root: "/var/lib/docker"

# ── DNS ───────────────────────────────────────
docker_dns:
  - "8.8.8.8"
  - "8.8.4.4"
EOF

tasks/configure.yml — Full Version:

cat > ~/ansible/roles/docker/tasks/configure.yml << 'EOF'
---
# ============================================================
# Docker Daemon Configuration
# ============================================================

# ── Ensure data directory ─────────────────────
- name: Ensure Docker data directory exists
  ansible.builtin.file:
    path:  "{{ docker_data_root }}"
    state: directory
    owner: root
    group: root
    mode:  '0711'

# ── daemon.json ───────────────────────────────
- name: Deploy Docker daemon configuration
  ansible.builtin.copy:
    dest:    /etc/docker/daemon.json
    owner:   root
    group:   root
    mode:    '0644'
    content: "{{ docker_daemon_config | to_nice_json }}"
    backup:  true
  notify: Restart Docker
  register: daemon_config

# ── Systemd override ──────────────────────────
- name: Create systemd override directory
  ansible.builtin.file:
    path:  /etc/systemd/system/docker.service.d
    state: directory
    mode:  '0755'

- name: Deploy systemd override
  ansible.builtin.copy:
    dest:  /etc/systemd/system/docker.service.d/override.conf
    mode:  '0644'
    content: |
      [Service]
      # Restart policy
      Restart=always
      RestartSec=5s

      # Limits
      LimitNOFILE=1048576
      LimitNPROC=infinity
      LimitCORE=infinity

      # Timeouts
      TimeoutStartSec=0
  notify:
    - Reload systemd
    - Restart Docker

# ── sysctl optimizations ──────────────────────
- name: Configure sysctl for Docker
  ansible.posix.sysctl:
    name:       "{{ item.name }}"
    value:      "{{ item.value }}"
    state:      present
    reload:     true
    sysctl_set: true
  loop:
    - name:  net.ipv4.ip_forward
      value: "1"              # ← απαραίτητο για Docker!
    - name:  net.bridge.bridge-nf-call-iptables
      value: "1"
    - name:  net.bridge.bridge-nf-call-ip6tables
      value: "1"
    - name:  vm.max_map_count
      value: "262144"         # ← για Elasticsearch
  ignore_errors: true

# ── Verify configuration ──────────────────────
- name: Verify Docker daemon config syntax
  ansible.builtin.command:
    cmd: docker info
  register:     docker_info
  changed_when: false
  ignore_errors: true

- name: Configuration report
  ansible.builtin.debug:
    msg:
      - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - "Docker Daemon Configuration"
      - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
      - "Config file: /etc/docker/daemon.json"
      - "Changed    : {{ daemon_config.changed }}"
      - "Data root  : {{ docker_data_root }}"
      - "Log driver : {{ docker_daemon_config['log-driver'] }}"
      - "Storage    : {{ docker_daemon_config['storage-driver'] }}"
      - "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
EOF

handlers/main.yml — Updated:

cat > ~/ansible/roles/docker/handlers/main.yml << 'EOF'
---
# ============================================================
# Docker Role Handlers
# ============================================================

- name: Restart Docker
  ansible.builtin.service:
    name:  docker
    state: restarted
  ignore_errors: "{{ ansible_check_mode }}"

- name: Reload Docker
  ansible.builtin.service:
    name:  docker
    state: reloaded
  ignore_errors: "{{ ansible_check_mode }}"

- name: Reload systemd
  ansible.builtin.systemd:
    daemon_reload: true
EOF

Template Approach — daemon.json.j2

# Εναλλακτικά με template
cat > ~/ansible/roles/docker/templates/daemon.json.j2 << 'EOF'
{
  "log-driver": "{{ docker_log_driver | default('json-file') }}",
  "log-opts": {
    "max-size": "{{ docker_log_max_size | default('10m') }}",
    "max-file": "{{ docker_log_max_files | default('3') }}"
  },
  "storage-driver": "{{ docker_storage_driver | default('overlay2') }}",
  "data-root": "{{ docker_data_root | default('/var/lib/docker') }}",
  "live-restore": true,
  "userland-proxy": false,
  "ipv6": {{ docker_ipv6_enabled | default(false) | lower }},
  "dns": {{ docker_dns | default(['8.8.8.8', '8.8.4.4']) | to_json }},
  {% if docker_registry_mirrors is defined and docker_registry_mirrors | length > 0 %}
  "registry-mirrors": {{ docker_registry_mirrors | to_json }},
  {% endif %}
  {% if docker_insecure_registries is defined and docker_insecure_registries | length > 0 %}
  "insecure-registries": {{ docker_insecure_registries | to_json }},
  {% endif %}
  "features": {
    "buildkit": true
  }
}
EOF

Επαλήθευση Configuration

# Έλεγχος daemon.json
ansible nextcloud -m ansible.builtin.command \
    -a "cat /etc/docker/daemon.json" \
    --become

# Έλεγχος docker info
ansible nextcloud -m ansible.builtin.command \
    -a "docker info" \
    --become

# Έλεγχος logging driver
ansible nextcloud -m ansible.builtin.shell \
    -a "docker info | grep -i 'logging driver'" \
    --become

# Έλεγχος storage driver
ansible nextcloud -m ansible.builtin.shell \
    -a "docker info | grep -i 'storage driver'" \
    --become

# Έλεγχος ip_forward
ansible nextcloud -m ansible.builtin.command \
    -a "sysctl net.ipv4.ip_forward" \
    --become

Σύνοψη D2.2

Docker Daemon Configuration
├── /etc/docker/daemon.json
│   ├── Logging:  log-driver, max-size, max-file
│   ├── Storage:  storage-driver, data-root
│   ├── Network:  dns, ipv6, userland-proxy
│   ├── Perf:     live-restore, ulimits
│   └── Registry: mirrors, insecure-registries
│
├── Systemd override:
│   └── /etc/systemd/system/docker.service.d/
│       └── Restart policy, LimitNOFILE
│
├── sysctl:
│   ├── net.ipv4.ip_forward = 1 (απαραίτητο!)
│   ├── bridge-nf-call-iptables = 1
│   └── vm.max_map_count = 262144
│
└── Environments:
    ├── Dev:  debug=true, insecure-registries
    └── Prod: live-restore=true, ulimits, no debug