

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

# Configurer des intégrations open source avec Docker (Linux)
<a name="linux-docker-setup"></a>

Pour un processus de déploiement rationalisé, vous pouvez utiliser Docker pour configurer Node-RED®, InfluxDB® et Grafana® dans un environnement Linux. Cette méthode utilise des conteneurs préconfigurés, ce qui permet un déploiement rapide et une gestion simplifiée des composants.

## Conditions préalables à la configuration de Docker
<a name="linux-docker-prerequisites"></a>

Avant de commencer, vérifiez que vous disposez des éléments suivants :
+ Une passerelle V3 compatible MQTT. Pour de plus amples informations, veuillez consulter [Passerelles V3 compatibles MQTT pour Edge AWS IoT SiteWise](mqtt-enabled-v3-gateway.md).
+ Le plugin Docker Compose. Pour connaître les étapes d'installation, consultez la section [Installer le Docker Compose plug-in](https://docs.docker.com/compose/install/linux/) dans la documentation des manuels *Docker*.

## Déployez les services
<a name="linux-docker-deployment"></a>

Ce déploiement exécute SiteWise Edge, InfluxDB, Node-RED et Grafana sur le même hôte.

### Configuration de l'environnement
<a name="linux-docker-env-setup"></a>

1. Obtenez un accès root :

   ```
   sudo -i
   ```

1. Créez un fichier .env ou exportez les variables d'environnement suivantes :

   ```
   export INFLUXDB_PASSWORD=your-secure-influxdb-password
   export INFLUXDB_TOKEN=your-secure-influxdb-token
   export GRAFANA_PASSWORD=your-secure-grafana-password
   ```

### Configuration du réseau Docker
<a name="linux-docker-network-config"></a>
+ Créez un réseau de ponts en utilisant le nom`SiteWiseEdgeNodeRedDemoNetwork`.

  ```
  docker network create --driver=bridge SiteWiseEdgeNodeRedDemoNetwork
  ```

### Préparez le Docker Compose fichier
<a name="linux-docker-compose-file"></a>

Copiez le contenu du fichier YAML suivant sur votre périphérique de passerelle SiteWise Edge.

#### Agrandir pour afficher l'exemple de fichier Docker Compose YAML
<a name="collapsible-section-docker-compose-file"></a>

```
services:
  influxdb:
    image: influxdb:latest
    container_name: influxdb
    ports:
      - "127.0.0.1:8086:8086"
    volumes:
      - influxdb-storage:/.influxdbv2
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUXDB_PASSWORD}
      - DOCKER_INFLUXDB_INIT_ORG=iot-sitewise-edge
      - DOCKER_INFLUXDB_INIT_BUCKET=WindFarmData
      - DOCKER_INFLUXDB_INIT_RETENTION=0
      - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${INFLUXDB_TOKEN}
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "127.0.0.1:3000:3000"
    volumes:
      - grafana-storage:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=${GRAFANA_PASSWORD}
      - GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource
      - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
      - GF_PATHS_CONFIG=/etc/grafana/grafana.ini
      - GF_LOG_LEVEL=info
    configs:
      - source: grafana_datasource
        target: /etc/grafana/provisioning/datasources/influxdb.yaml
      - source: grafana_preload_dashboard_config
        target: /etc/grafana/provisioning/dashboards/dashboard.yml
      - source: grafana_preload_dashboard
        target: /etc/grafana/provisioning/dashboards/demo_dashboard.json
    depends_on:
      - influxdb
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

  nodered:
    build:
      context: .
      dockerfile_inline: |
        FROM nodered/node-red:latest
        RUN npm install node-red-contrib-influxdb
    container_name: nodered
    ports:
      - "127.0.0.1:1880:1880"
    volumes:
      - node_red_data:/data
    environment:
      - NODE_RED_ENABLE_SAFE_MODE=false
      - NODE_RED_ENABLE_PALETTE_EDIT=true
      - NODE_RED_AUTO_INSTALL_MODULES=true
    configs:
      - source: nodered_flows
        target: /data/flows.json
      - source: nodered_settings
        target: /data/settings.js
      - source: nodered_flows_cred
        target: /data/flows_cred.json
    depends_on:
      - influxdb
    networks:
      - SiteWiseEdgeNodeRedDemoNetwork
    restart: unless-stopped

volumes:
  influxdb-storage:
  grafana-storage:
  node_red_data:

networks:
  SiteWiseEdgeNodeRedDemoNetwork:
    external: true

configs:
  grafana_datasource:
    content: |
      apiVersion: 1
      datasources:
        - name: windfarm-demo
          type: influxdb
          access: proxy
          url: http://influxdb:8086
          jsonData:
            version: Flux
            organization: iot-sitewise-edge
            defaultBucket: WindFarmData
            tlsSkipVerify: true
          secureJsonData:
            token: ${INFLUXDB_TOKEN}
          editable: false

  grafana_preload_dashboard_config:
    content: |
      apiVersion: 1
      providers:
        - name: "Dashboard provider"
          orgId: 1
          type: file
          options: 
            path: /etc/grafana/provisioning/dashboards

  grafana_preload_dashboard:
    content: |
      {
        "annotations": {
          "list": [
            {
              "builtIn": 1,
              "datasource": {
                "type": "grafana",
                "uid": "-- Grafana --"
              },
              "enable": true,
              "hide": true,
              "iconColor": "rgba(0, 211, 255, 1)",
              "name": "Annotations & Alerts",
              "type": "dashboard"
            }
          ]
        },
        "editable": true,
        "fiscalYearStartMonth": 0,
        "graphTooltip": 0,
        "id": 1,
        "links": [],
        "panels": [
          {
            "datasource": {
              "type": "influxdb",
              "uid": "PEB0DCBF338B3CEB2"
            },
            "fieldConfig": {
              "defaults": {
                "color": {
                  "mode": "palette-classic"
                },
                "custom": {
                  "axisBorderShow": false,
                  "axisCenteredZero": false,
                  "axisColorMode": "text",
                  "axisLabel": "",
                  "axisPlacement": "auto",
                  "barAlignment": 0,
                  "barWidthFactor": 0.6,
                  "drawStyle": "line",
                  "fillOpacity": 0,
                  "gradientMode": "none",
                  "hideFrom": {
                    "legend": false,
                    "tooltip": false,
                    "viz": false
                  },
                  "insertNulls": false,
                  "lineInterpolation": "linear",
                  "lineWidth": 1,
                  "pointSize": 5,
                  "scaleDistribution": {
                    "type": "linear"
                  },
                  "showPoints": "auto",
                  "spanNulls": false,
                  "stacking": {
                    "group": "A",
                    "mode": "none"
                  },
                  "thresholdsStyle": {
                    "mode": "off"
                  }
                },
                "mappings": [],
                "thresholds": {
                  "mode": "absolute",
                  "steps": [
                    {
                      "color": "green"
                    },
                    {
                      "color": "red",
                      "value": 80
                    }
                  ]
                }
              },
              "overrides": []
            },
            "gridPos": {
              "h": 8,
              "w": 12,
              "x": 0,
              "y": 0
            },
            "id": 1,
            "options": {
              "legend": {
                "calcs": [],
                "displayMode": "list",
                "placement": "bottom",
                "showLegend": true
              },
              "tooltip": {
                "hideZeros": false,
                "mode": "single",
                "sort": "none"
              }
            },
            "pluginVersion": "11.6.0",
            "targets": [
              {
                "datasource": {
                  "type": "influxdb",
                  "uid": "PEB0DCBF338B3CEB2"
                },
                "query": "from(bucket: \"WindFarmData\")\n  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n  |> filter(fn: (r) => r[\"_measurement\"] == \"TurbineData\")\n  |> filter(fn: (r) => r[\"_field\"] == \"value\")\n  |> filter(fn: (r) => r[\"name\"] == \"/Renton/WindFarm/Turbine/WindSpeed\")\n  |> filter(fn: (r) => r[\"quality\"] == \"GOOD\")\n  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n  |> yield(name: \"mean\")",
                "refId": "A"
              }
            ],
            "title": "Wind Speed",
            "type": "timeseries"
          }
        ],
        "preload": false,
        "schemaVersion": 41,
        "tags": [],
        "templating": {
          "list": []
        },
        "time": {
          "from": "now-6h",
          "to": "now"
        },
        "timepicker": {},
        "timezone": "browser",
        "title": "Demo Dashboard",
        "uid": "eejtureqjo9a8c",
        "version": 2
      }

  nodered_flows:
    content: |
      [
        {
          "id": "95fce448fdd43b47",
          "type": "tab",
          "label": "Demo Flow",
          "disabled": false,
          "info": ""
        },
        {
          "id": "5f63740b66af3386",
          "type": "mqtt out",
          "z": "95fce448fdd43b47",
          "name": "Publish to MQTT broker",
          "topic": "/Renton/WindFarm/Turbine/WindSpeed",
          "qos": "1",
          "retain": "",
          "respTopic": "",
          "contentType": "",
          "userProps": "",
          "correl": "",
          "expiry": "",
          "broker": "5744207557fa19be",
          "x": 830,
          "y": 200,
          "wires": []
        },
        {
          "id": "8f2eb590d596679b",
          "type": "function",
          "z": "95fce448fdd43b47",
          "name": "Translate to SiteWise payload",
          "func": "let input = msg.payload;\nlet output = {};\n\noutput[\"propertyAlias\"] = input.name;\n\nlet propertyVal = {}\n\nlet timeInSeconds = Math.floor(input.timestamp / 1000);\nlet offsetInNanos = (input.timestamp % 1000) * 1000000;\n\npropertyVal[\"timestamp\"] = {\n    \"timeInSeconds\": timeInSeconds,\n    \"offsetInNanos\": offsetInNanos,\n};\n\npropertyVal[\"quality\"] = input.quality\n\nlet typeNameConverter = {\n    \"number\": (x) => Number.isInteger(x) ? \"integerValue\" : \"doubleValue\",\n    \"boolean\": (x) => \"booleanValue\",\n    \"string\": (x) => \"stringValue\", \n}\nlet typeName = typeNameConverter[typeof input.value](input.value)\npropertyVal[\"value\"] = {}\npropertyVal[\"value\"][typeName] = input.value;\n\noutput[\"propertyValues\"] = [propertyVal]\n\nreturn {\n    payload: JSON.stringify(output)\n};",
          "outputs": 1,
          "timeout": "",
          "noerr": 0,
          "initialize": "",
          "finalize": "",
          "libs": [],
          "x": 530,
          "y": 200,
          "wires": [
            [
              "5f63740b66af3386"
            ]
          ]
        },
        {
          "id": "4b78cbdea5e3258c",
          "type": "inject",
          "z": "95fce448fdd43b47",
          "name": "Turbine Simulator",
          "props": [
            {
              "p": "payload.timestamp",
              "v": "",
              "vt": "date"
            },
            {
              "p": "payload.quality",
              "v": "GOOD",
              "vt": "str"
            },
            {
              "p": "payload.value",
              "v": "$$random()",
              "vt": "jsonata"
            },
            {
              "p": "payload.name",
              "v": "/Renton/WindFarm/Turbine/WindSpeed",
              "vt": "str"
            }
          ],
          "repeat": "1",
          "crontab": "",
          "once": false,
          "onceDelay": "",
          "topic": "",
          "x": 270,
          "y": 200,
          "wires": [
            [
              "8f2eb590d596679b"
            ]
          ]
        },
        {
          "id": "b658bf337ea2e316",
          "type": "influxdb out",
          "z": "95fce448fdd43b47",
          "influxdb": "2f1c38495035d2e4",
          "name": "Store data in InfluxDB",
          "measurement": "TurbineData",
          "precision": "",
          "retentionPolicy": "",
          "database": "",
          "retentionPolicyV18Flux": "",
          "org": "iot-sitewise-edge",
          "bucket": "WindFarmData",
          "x": 840,
          "y": 340,
          "wires": []
        },
        {
          "id": "9432d39af35b202f",
          "type": "function",
          "z": "95fce448fdd43b47",
          "name": "Translate to InfluxDB payload",
          "func": "let data = msg.payload;\n\nlet timeInSeconds = data.propertyValues[0].timestamp.timeInSeconds;\nlet offsetInNanos = data.propertyValues[0].timestamp.offsetInNanos;\nlet timestampInMilliseconds = (timeInSeconds * 1000) + (offsetInNanos / 1000000);\n\nmsg.payload = [\n    {\n        \"timestamp(milliseconds_since_epoch)\": timestampInMilliseconds,\n        \"value\": data.propertyValues[0].value.doubleValue\n    },\n    {\n        \"name\": data.propertyAlias,\n        \"quality\": data.propertyValues[0].quality\n    }\n]\n\nreturn msg",
          "outputs": 1,
          "timeout": "",
          "noerr": 0,
          "initialize": "",
          "finalize": "",
          "libs": [],
          "x": 560,
          "y": 340,
          "wires": [
            [
              "b658bf337ea2e316"
            ]
          ]
        },
        {
          "id": "b689403d2c80816b",
          "type": "mqtt in",
          "z": "95fce448fdd43b47",
          "name": "Subscribe to MQTT broker",
          "topic": "/Renton/WindFarm/Turbine/WindSpeed",
          "qos": "1",
          "datatype": "auto-detect",
          "broker": "5744207557fa19be",
          "nl": false,
          "rap": true,
          "rh": 0,
          "inputs": 0,
          "x": 290,
          "y": 340,
          "wires": [
            [
              "9432d39af35b202f"
            ]
          ]
        },
        {
          "id": "4f59bed8e829fc35",
          "type": "comment",
          "z": "95fce448fdd43b47",
          "name": "Data Publish Flow",
          "info": "dfgh",
          "x": 270,
          "y": 160,
          "wires": []
        },
        {
          "id": "b218c7fc58c8b6e7",
          "type": "comment",
          "z": "95fce448fdd43b47",
          "name": "Data Retention flow",
          "info": "",
          "x": 270,
          "y": 300,
          "wires": []
        },
        {
          "id": "5744207557fa19be",
          "type": "mqtt-broker",
          "name": "emqx",
          "broker": "emqx",
          "port": "1883",
          "clientid": "",
          "autoConnect": true,
          "usetls": false,
          "protocolVersion": "5",
          "keepalive": 15,
          "cleansession": true,
          "autoUnsubscribe": true,
          "birthTopic": "",
          "birthQos": "0",
          "birthPayload": "",
          "birthMsg": {},
          "closeTopic": "",
          "closePayload": "",
          "closeMsg": {},
          "willTopic": "",
          "willQos": "0",
          "willPayload": "",
          "willMsg": {},
          "userProps": "",
          "sessionExpiry": ""
        },
        {
          "id": "2f1c38495035d2e4",
          "type": "influxdb",
          "hostname": "influxdb",
          "port": 8086,
          "protocol": "http",
          "database": "",
          "name": "InfluxDB",
          "usetls": false,
          "tls": "",
          "influxdbVersion": "2.0",
          "url": "http://influxdb:8086",
          "timeout": "",
          "rejectUnauthorized": false
        }
      ]

  nodered_flows_cred:
    content: |
      {
        "2f1c38495035d2e4": {
          "token": "${INFLUXDB_TOKEN}"
        }
      }

  nodered_settings:
    content: |
      module.exports = {
        flowFile: 'flows.json',
        credentialSecret: false,
        adminAuth: null,
        editorTheme: {
          projects: {
            enabled: false
          }
        }
      }
```

### Mettre à jour le déploiement d' SiteWise Edge
<a name="w2aac17c19c19c26c27b7c11"></a>

1. Accédez à la [AWS IoT console](https://console.aws.amazon.com/iot/)

1. Choisissez **Appareils Greengrass** dans le menu de navigation de gauche sous la section **Gérer**, puis Appareils **Core**.

1. Sélectionnez le périphérique principal connecté à votre SiteWise Edge Gateway.

1. Choisissez l'onglet **Déploiements**, puis sélectionnez la valeur de l'**ID de déploiement**.

1. Choisissez **Actions**, puis sélectionnez **Réviser**. 

1. Lisez le message contextuel, puis choisissez **Revise le déploiement**.

1. À **l'étape 2 - Sélection des composants**, sélectionnez les composants suivants, puis cliquez sur **Suivant**.
   + `aws.greengrass.clientdevices.mqtt.EMQX`
   + `aws.iot.SiteWiseEdgePublisher`

1. À **l'étape 3 - Configuration des composants**, sélectionnez la valeur du `aws.greengrass.clientdevices.mqtt.EMQX` composant et ajoutez la configuration réseau suivante :

   ```
   {
       "emqxConfig": {
           "authorization": {
               "no_match": "allow"
           },
           "listeners": {
               "tcp": {
                   "default": {
                       "enabled": true,
                       "enable_authn": false
                   }
               }
           }
       },
       "authMode": "bypass",
       "dockerOptions": "-p 127.0.0.1:1883:1883 --network=SiteWiseEdgeNodeRedDemoNetwork",
       "requiresPrivilege": "true"
   }
   ```

1. Choisissez **Suivant**.

1. À **l'étape 4 - Configurer les paramètres avancés**, choisissez **Next**.

1. Choisissez **Deploy**

### Lancez les services
<a name="linux-docker-launch"></a>

1. Démarrez les services à l'aide du fichier Docker Compose. Exécutez la commande suivante dans le répertoire contenant le `compose.yaml` fichier.

   ```
   docker compose up -d
   ```

1. Créez un tunnel SSH pour accéder aux services :

   ```
   ssh -i path_to_your_ssh_key -L 1880:127.0.0.1:1880 -L 3000:127.0.0.1:3000 -L 8086:127.0.0.1:8086 username@gateway_ip_address
   ```

Ce déploiement crée les services suivants dans `SiteWiseEdgeNodeRedDemoNetwork network` :

**InfluxDB v2 (port 8086)**  
Inclut une organisation (iot-sitewise-edge) préconfigurée, un bucket WindFarmData InfluxDB et des informations d'identification d'administrateur

**Node-rouge (port 1880)**  
Inclut des nœuds InfluxDB et des flux préconfigurés pour l'intégration AWS IoT SiteWise 

**Grafana (port 3000)**  
Comprend un utilisateur administrateur, une source de données InfluxDB et un tableau de bord de surveillance

### Accédez aux services
<a name="linux-docker-access-services"></a>

Après le déploiement, accédez aux services à l'aide des informations suivantes URLs et des informations d'identification :

**Note**  
Vous pouvez accéder à chaque service depuis votre hôte ou depuis la machine passerelle.


**Détails d'accès au service**  

| Service | URL | Informations d’identification | 
| --- | --- | --- | 
| Nœud rouge | [http://127.0.0.1:1880](http://127.0.0.1:1880) | Aucune information d'identification requise | 
| InfluxDB | [http://127.0.0.1:8086](http://127.0.0.1:8086) |  Nom d'utilisateur : admin Mot de passe : \$1INFLUXDB\$1PASSWORD  | 
| Grafana | [http://127.0.0.1:3000](http://127.0.0.1:3000) |  Nom d'utilisateur : admin Mot de passe : \$1GRAFANA\$1PASSWORD  | 

## Vérification du déploiement
<a name="linux-docker-verify-deployment"></a>

Pour garantir le succès de votre déploiement, effectuez les vérifications suivantes :

1. Pour Node-RED, vérifiez la présence de deux flux préchargés :
   + Flux de publication des données
   + Flux de conservation des données

1. Car AWS IoT SiteWise, dans la AWS IoT SiteWise console, confirmez la présence d'un flux de données avec l'alias`/Renton/WindFarm/Turbine/WindSpeed`.

1. Pour InfluxDB, utilisez l'explorateur de données pour vérifier le stockage des données dans la `TurbineData` mesure au sein du `WindFarmData` bucket.

1. Pour Grafana, consultez le tableau de bord pour confirmer l'affichage des données de séries chronologiques générées par Node-RED.