Greenbone 社群版(OpenVAS) 使用 docker-compose + cron 排程每日自動更新 feed

由於近期官方更新(v26.2.0 – 2026-02-24),連帶docker-compose.yml又改了 請參考「官方ChangeLog

以前裝過無數次OpenVAS,不論是否使用Docker,一天到晚就卡更新feed,常更新不完,每次要掃描時,就要開始擔心feed更新不完,這次改使用 docker-compose.yml + cron排程使用shell script方式進行每日自動更新 (排除 watchtower 自動更新,用watchtower更新會只有部份image更新重啟,有時就會造成錯誤)

執行環境:Rocky Linux 9 or 10 + Docker CE + docker compose plugin
路徑: /docker/openvas
GVM https port: 9392 (並配合haproxy+certbot,提供https對外服務,v26.2.0後的docker-compose.yml,您亦可用其nginx直接提供https對外服務)

mkdir -p /docker/openvas
cd /docker/openvas

docker-compose.yml (2026/01/14更新,新增pg-gvm-migrator,避免 DB schema 升級失敗造成 pg-gvm 起不來。此範例基於官方 Greenbone Community Containers compose 調整。2026/03/13更新,因26.2.0更新,官方又修改了docker-compose,改用了nginx,因我前面還有使用haproxy,因此就沒有使用nginx直接提供443 port https,而是將nginx port再改為9392 port,維持現狀,不過9392port由http變成https了)

name: greenbone-community-edition

services:
  vulnerability-tests:
    image: registry.community.greenbone.net/community/vulnerability-tests
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - vt_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  notus-data:
    image: registry.community.greenbone.net/community/notus-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - notus_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  scap-data:
    image: registry.community.greenbone.net/community/scap-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - scap_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  cert-bund-data:
    image: registry.community.greenbone.net/community/cert-bund-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - cert_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  dfn-cert-data:
    image: registry.community.greenbone.net/community/dfn-cert-data
    environment:
      KEEP_ALIVE: 1
    volumes:
      - cert_data_vol:/mnt
    depends_on:
      cert-bund-data:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  data-objects:
    image: registry.community.greenbone.net/community/data-objects
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - data_objects_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  report-formats:
    image: registry.community.greenbone.net/community/report-formats
    environment:
      FEED_RELEASE: "24.10"
      KEEP_ALIVE: 1
    volumes:
      - data_objects_vol:/mnt
    depends_on:
      data-objects:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  gpg-data:
    image: registry.community.greenbone.net/community/gpg-data
    volumes:
      - gpg_data_vol:/mnt
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  redis-server:
    image: registry.community.greenbone.net/community/redis-server
    restart: on-failure
    volumes:
      - redis_socket_vol:/run/redis/
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  pg-gvm:
    image: registry.community.greenbone.net/community/pg-gvm:stable
    restart: on-failure:10
    volumes:
      - psql_data_vol:/var/lib/postgresql
      - psql_socket_vol:/var/run/postgresql
    depends_on:
      pg-gvm-migrator:
        condition: service_completed_successfully
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  pg-gvm-migrator:
    image: registry.community.greenbone.net/community/pg-gvm-migrator:stable
    restart: no
    volumes:
      - psql_data_vol:/var/lib/postgresql
      - psql_socket_vol:/var/run/postgresql

  gvmd:
    image: registry.community.greenbone.net/community/gvmd:stable
    restart: on-failure
    environment:
      MTA_HOST: ${MAIL_HOST}
      MTA_PORT: ${MAIL_PORT}
      MTA_TLS: ${MAIL_TLS}
      MTA_STARTTLS: ${MAIL_STARTTLS}
      MTA_AUTH: ${MAIL_AUTH}
      MTA_USER: ${MAIL_USER}
      MTA_FROM: ${MAIL_FROM}
      MTA_PASSWORD: ${MAIL_PASSWORD}
    volumes:
      - gvmd_data_vol:/var/lib/gvm
      - scap_data_vol:/var/lib/gvm/scap-data/
      - cert_data_vol:/var/lib/gvm/cert-data
      - data_objects_vol:/var/lib/gvm/data-objects/gvmd
      - vt_data_vol:/var/lib/openvas/plugins
      - psql_data_vol:/var/lib/postgresql
      - gvmd_socket_vol:/run/gvmd
      - ospd_openvas_socket_vol:/run/ospd
      - psql_socket_vol:/var/run/postgresql
    depends_on:
      pg-gvm:
        condition: service_started
      scap-data:
        condition: service_healthy
      cert-bund-data:
        condition: service_healthy
      dfn-cert-data:
        condition: service_healthy
      data-objects:
        condition: service_healthy
      report-formats:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  gsa:
    image: registry.community.greenbone.net/community/gsa:stable-slim
    environment:
      MOUNT_PATH: "/mnt/web"
      KEEP_ALIVE: 1
    healthcheck:
      test: ["CMD-SHELL", "test -e /run/gsa/copying.done"]
      start_period: 5s
    volumes:
      - gsa_data_vol:/mnt/web
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  gsad:
    image: registry.community.greenbone.net/community/gsad:stable
    restart: on-failure
    environment:
      GSAD_ARGS: "--listen=0.0.0.0 --http-only --api-only -f"
    volumes:
      - gvmd_socket_vol:/run/gvmd
    depends_on:
      gvmd:
        condition: service_started
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  gvm-config:
    image: registry.community.greenbone.net/community/gvm-config:latest
    environment:
      ENABLE_NGINX_CONFIG: true
      ENABLE_TLS_GENERATION: true
    volumes:
      - nginx_config_vol:/mnt/nginx/configs
      - nginx_certificates_vol:/mnt/nginx/certs
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  nginx:
    image: registry.community.greenbone.net/community/nginx:latest
    ports:
      - 9392:443
#      - 9392:9392
    volumes:
      - nginx_config_vol:/etc/nginx/conf.d:ro
      - nginx_certificates_vol:/etc/nginx/certs:ro
      - gsa_data_vol:/usr/share/nginx/html:ro
    depends_on:
      gvm-config:
        condition: service_completed_successfully
      gsa:
        condition: service_healthy
      gsad:
        condition: service_started
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  # Sets log level of openvas to the set LOG_LEVEL within the env
  # and changes log output to /var/log/openvas instead /var/log/gvm
  # to reduce likelihood of unwanted log interferences
  configure-openvas:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    volumes:
      - openvas_data_vol:/mnt
      - openvas_log_data_vol:/var/log/openvas
    command:
      - /bin/sh
      - -c
      - |
        printf "table_driven_lsc = yes\nopenvasd_server = http://openvasd:80\n" > /mnt/openvas.conf
        sed "s/127/128/" /etc/openvas/openvas_log.conf | sed 's/gvm/openvas/' > /mnt/openvas_log.conf
        chmod 644 /mnt/openvas.conf
        chmod 644 /mnt/openvas_log.conf
        touch /var/log/openvas/openvas.log
        chmod 666 /var/log/openvas/openvas.log
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

  # shows logs of openvas
  openvas:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    restart: on-failure
    volumes:
      - openvas_data_vol:/etc/openvas
      - openvas_log_data_vol:/var/log/openvas
    command:
      - /bin/sh
      - -c
      - |
        cat /etc/openvas/openvas.conf
        tail -f /var/log/openvas/openvas.log
    depends_on:
      configure-openvas:
        condition: service_completed_successfully
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  openvasd:
    image: registry.community.greenbone.net/community/openvas-scanner:stable
    restart: on-failure
    environment:
      # `service_notus` is set to disable everything but notus,
      # if you want to utilize openvasd directly removed `OPENVASD_MODE`
      OPENVASD_MODE: service_notus
      GNUPGHOME: /etc/openvas/gnupg
      LISTENING: 0.0.0.0:80
    volumes:
      - openvas_data_vol:/etc/openvas
      - openvas_log_data_vol:/var/log/openvas
      - gpg_data_vol:/etc/openvas/gnupg
      - notus_data_vol:/var/lib/notus
    # enable port forwarding when you want to use the http api from your host machine
    # ports:
    #   - 127.0.0.1:3000:80
    depends_on:
      vulnerability-tests:
        condition: service_healthy
      notus-data:
        condition: service_healthy
      configure-openvas:
        condition: service_completed_successfully
      gpg-data:
        condition: service_completed_successfully
    networks:
      default:
        aliases:
          - openvasd
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  ospd-openvas:
    image: registry.community.greenbone.net/community/ospd-openvas:stable
    restart: on-failure
    hostname: ospd-openvas.local
    cap_add:
      - NET_ADMIN # for capturing packages in promiscuous mode
      - NET_RAW # for raw sockets e.g. used for the boreas alive detection
    security_opt:
      - seccomp=unconfined
      - apparmor=unconfined
    command:
      [
        "ospd-openvas",
        "-f",
        "--config",
        "/etc/gvm/ospd-openvas.conf",
        "--notus-feed-dir",
        "/var/lib/notus/advisories",
        "-m",
        "666",
      ]
    volumes:
      - gpg_data_vol:/etc/openvas/gnupg
      - vt_data_vol:/var/lib/openvas/plugins
      - notus_data_vol:/var/lib/notus
      - ospd_openvas_socket_vol:/run/ospd
      - redis_socket_vol:/run/redis/
      - openvas_data_vol:/etc/openvas/
      - openvas_log_data_vol:/var/log/openvas
    depends_on:
      redis-server:
        condition: service_started
      gpg-data:
        condition: service_completed_successfully
      configure-openvas:
        condition: service_completed_successfully
      vulnerability-tests:
        condition: service_healthy
      notus-data:
        condition: service_healthy
    labels:
      - "com.centurylinklabs.watchtower.enable=false"
    logging:
      driver: "json-file"
      options:
        max-size: "50m"
        max-file: "3"

  gvm-tools:
    image: registry.community.greenbone.net/community/gvm-tools
    volumes:
      - gvmd_socket_vol:/run/gvmd
      - ospd_openvas_socket_vol:/run/ospd
    depends_on:
      - gvmd
      - ospd-openvas
    labels:
      - "com.centurylinklabs.watchtower.enable=false"

volumes:
  gpg_data_vol:
  scap_data_vol:
  cert_data_vol:
  data_objects_vol:
  gvmd_data_vol:
  psql_data_vol:
  vt_data_vol:
  notus_data_vol:
  psql_socket_vol:
  gvmd_socket_vol:
  ospd_openvas_socket_vol:
  redis_socket_vol:
  openvas_data_vol:
  openvas_log_data_vol:
  gsa_data_vol:
  nginx_config_vol:
  nginx_certificates_vol:

新增檔案 .env (如果需要發通知信的話,否則docker-compose.yml中,gvmd:的environment相對應的參數設定可移除)

# SMTP Settings
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_TLS=on
MAIL_STARTTLS=on
MAIL_AUTH=on
MAIL_USER=your_google_account
MAIL_FROM=your@gmail.com
MAIL_PASSWORD=your_google_app_password

新增檔案 update.sh (記得要chmod +x update.sh)

#!/bin/bash

# 設定目錄
OPENVAS_DIR="/docker/openvas"
cd "$OPENVAS_DIR" || exit 1

echo "--- [$(date)] 開始執行維護任務 ---"

# 1. 預先清空應用程式日誌
echo "正在清理 Volume 內的應用程式日誌..."
find /var/lib/docker/volumes/greenbone-community-edition_openvas_log_data_vol/_data -name "*.log" -exec truncate -s 0 {} +

# 2. 下載影像並包含重試機制 (解決 TLS Timeout 問題)
echo "正在下載最新影像..."
MAX_RETRIES=5
COUNT=0
while [ $COUNT -lt $MAX_RETRIES ]; do
    /usr/bin/docker compose pull -q && break
    COUNT=$((COUNT + 1))
    echo "下載失敗,10 秒後進行第 $COUNT 次重試..."
    sleep 10
done

# 3. 重新啟動服務以套用新影像與 Logging 限制
echo "正在重啟容器..."
/usr/bin/docker compose down
sleep 5
/usr/bin/docker compose up -d
sleep 60

# 4. 深度清理磁碟
echo "正在清理過期影像與快取..."
# 清理未使用且超過 30 天的 image
/usr/bin/docker image prune -f --filter "until=720h"
/usr/bin/docker system prune -f

echo "--- [$(date)] 維護完成,剩餘空間:$(df -h / | awk 'NR==2 {print $4}') ---"

在 /etc/crontab 加入 (每天 04:00 自動執行,可自行調整)

0 4 * * * root /docker/openvas/update.sh >> /var/log/openvas_update.log 2>&1

首次部署時,請先在 /docker/openvas 目錄手動執行一次 docker compose pull && docker compose up -d,確認 GVM 初始化與 feed 首次同步完成後,再交給 crontab 例行更新。

Reference: Greenbone Community Documentation – Containers

發佈留言