@flowfuse/driver-docker 2.6.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release-publish.yml +2 -2
- package/CHANGELOG.md +12 -0
- package/README.md +5 -0
- package/docker.js +62 -3
- package/package.json +1 -1
|
@@ -11,8 +11,8 @@ jobs:
|
|
|
11
11
|
- uses: actions/checkout@v4
|
|
12
12
|
- uses: actions/setup-node@v4
|
|
13
13
|
with:
|
|
14
|
-
node-version:
|
|
14
|
+
node-version: 18
|
|
15
15
|
- run: npm ci --omit dev
|
|
16
|
-
- uses: JS-DevTools/npm-publish@
|
|
16
|
+
- uses: JS-DevTools/npm-publish@v3
|
|
17
17
|
with:
|
|
18
18
|
token: ${{ secrets.NPM_PUBLISH_TOKEN }}
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
#### 2.7.1: Release
|
|
2
|
+
|
|
3
|
+
- Fix logPassthrough (#106) @knolleary
|
|
4
|
+
|
|
5
|
+
#### 2.7.0: Release
|
|
6
|
+
|
|
7
|
+
- Persistent storage - Docker (#103) @hardillb
|
|
8
|
+
- Fix LOG_PASSTHROUGH (#104) @hardillb
|
|
9
|
+
- Fix network selection if more than one network labeled 'flowforge' (#102) @hardillb
|
|
10
|
+
- Update release-publish.yml to use NodeJS v18 (#101) @hardillb
|
|
11
|
+
- Bump JS-DevTools/npm-publish from 2 to 3 (#96) @app/dependabot
|
|
12
|
+
|
|
1
13
|
#### 2.6.0: Release
|
|
2
14
|
|
|
3
15
|
|
package/README.md
CHANGED
|
@@ -15,12 +15,17 @@ driver:
|
|
|
15
15
|
registry: containers.flowforge.com
|
|
16
16
|
privateCA: /full/path/to/chain.pem
|
|
17
17
|
logPassthrough: true
|
|
18
|
+
storage:
|
|
19
|
+
enabled: true
|
|
20
|
+
path: /opt/flowfuse/storage
|
|
18
21
|
```
|
|
19
22
|
|
|
20
23
|
- `registry` is the Docker Registry to load Stack Containers from (default: Docker Hub)
|
|
21
24
|
- `socket` is the path to the docker unix domain socket (default: /var/run/docker.sock)
|
|
22
25
|
- `privateCA`: is the fully qualified path to a pem file containing trusted CA cert chain (default: not set)
|
|
23
26
|
- `logPassthrough` Have Node-RED logs printed in JSON format to container stdout (default: false)
|
|
27
|
+
- `storage.enabled` enables mounting a directory into each Node-RED instance as persistence storage (default: false)
|
|
28
|
+
- `storage.path` is the fully qualified path to the root directory for the storage on the host (default: not set)
|
|
24
29
|
|
|
25
30
|
### Configuration via environment variables
|
|
26
31
|
|
package/docker.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const got = require('got')
|
|
2
2
|
const Docker = require('dockerode')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
const { chownSync, mkdirSync, rmSync } = require('fs')
|
|
3
5
|
|
|
4
6
|
const createContainer = async (project, domain) => {
|
|
5
|
-
const networks = await this._docker.listNetworks({ filters: { label: ['com.docker.compose.network=flowforge'] } })
|
|
6
7
|
const stack = project.ProjectStack.properties
|
|
7
8
|
const contOptions = {
|
|
8
9
|
Image: stack.container,
|
|
@@ -15,7 +16,7 @@ const createContainer = async (project, domain) => {
|
|
|
15
16
|
AttachStdout: false,
|
|
16
17
|
AttachStderr: false,
|
|
17
18
|
HostConfig: {
|
|
18
|
-
NetworkMode:
|
|
19
|
+
NetworkMode: this._network
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
|
|
@@ -85,7 +86,7 @@ const createContainer = async (project, domain) => {
|
|
|
85
86
|
contOptions.Env.push(`FORGE_NR_SECRET=${credentialSecret}`)
|
|
86
87
|
}
|
|
87
88
|
|
|
88
|
-
if (this.
|
|
89
|
+
if (this._app.config.driver.options?.logPassthrough) {
|
|
89
90
|
contOptions.Env.push('FORGE_LOG_PASSTHROUGH=true')
|
|
90
91
|
}
|
|
91
92
|
|
|
@@ -100,6 +101,25 @@ const createContainer = async (project, domain) => {
|
|
|
100
101
|
contOptions.Env.push('NODE_EXTRA_CA_CERTS=/usr/local/ssl-certs/chain.pem')
|
|
101
102
|
}
|
|
102
103
|
|
|
104
|
+
if (this._app.config.driver.options?.storage?.enabled || this._app.config.driver.options?.storage?.path) {
|
|
105
|
+
try {
|
|
106
|
+
const localPath = path.join('/opt/persistent-storage', project.id)
|
|
107
|
+
console.log(`Creating dir in container ${localPath}`)
|
|
108
|
+
mkdirSync(localPath)
|
|
109
|
+
chownSync(localPath, 1000, 1000)
|
|
110
|
+
} catch (err) {
|
|
111
|
+
this._app.log.info(`[docker] problem creating persistent storage for ${project.id}`)
|
|
112
|
+
}
|
|
113
|
+
const projectPath = path.join(this._app.config.driver.options?.storage?.path, project.id)
|
|
114
|
+
if (Array.isArray(contOptions.HostConfig?.Binds)) {
|
|
115
|
+
contOptions.HostConfig.Binds.push(`${projectPath}:/data/storage`)
|
|
116
|
+
} else {
|
|
117
|
+
contOptions.HostConfig.Binds = [
|
|
118
|
+
`${projectPath}:/data/storage`
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
103
123
|
const containerList = await this._docker.listImages()
|
|
104
124
|
let containerFound = false
|
|
105
125
|
let stackName = stack.container
|
|
@@ -180,6 +200,35 @@ module.exports = {
|
|
|
180
200
|
options.registry = app.config.driver.options?.registry || '' // use docker hub
|
|
181
201
|
}
|
|
182
202
|
|
|
203
|
+
const networks = await this._docker.listNetworks({ filters: { label: ['com.docker.compose.network=flowforge'] } })
|
|
204
|
+
if (networks.length > 1) {
|
|
205
|
+
const filteredNetworks = []
|
|
206
|
+
for (let j = 0; j < networks.length; j++) {
|
|
207
|
+
const details = await this._docker.getNetwork(networks[j].Id).inspect()
|
|
208
|
+
const containers = Object.keys(details.Containers)
|
|
209
|
+
for (let i = 0; i < containers.length; i++) {
|
|
210
|
+
// console.log(containers[i])
|
|
211
|
+
if (containers[i].startsWith(process.env.HOSTNAME)) {
|
|
212
|
+
filteredNetworks.push(networks[j])
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// console.log(JSON.stringify(filteredNetworks, null, 2))
|
|
217
|
+
if (filteredNetworks[0]) {
|
|
218
|
+
this._app.log.info(`[docker] using network ${filteredNetworks[0].Name}`)
|
|
219
|
+
this._network = filteredNetworks[0].Name
|
|
220
|
+
} else {
|
|
221
|
+
this._app.log.info('[docker] unable to find network')
|
|
222
|
+
process.exit(-9)
|
|
223
|
+
}
|
|
224
|
+
} else if (networks.length === 1) {
|
|
225
|
+
this._app.log.info(`[docker] using network ${networks[0].Name}`)
|
|
226
|
+
this._network = networks[0].Name
|
|
227
|
+
} else {
|
|
228
|
+
this._app.log.info('[docker] unable to find network')
|
|
229
|
+
process.exit(-9)
|
|
230
|
+
}
|
|
231
|
+
|
|
183
232
|
// Get a list of all projects - with the absolute minimum of fields returned
|
|
184
233
|
const projects = await app.db.models.Project.findAll({
|
|
185
234
|
attributes: [
|
|
@@ -314,6 +363,16 @@ module.exports = {
|
|
|
314
363
|
await container.remove()
|
|
315
364
|
} catch (err) {}
|
|
316
365
|
}
|
|
366
|
+
if (this._app.config.driver.options?.storage?.enabled) {
|
|
367
|
+
// need to be sure we have permission to delete the dir and it's contents?
|
|
368
|
+
try {
|
|
369
|
+
// This is better and assumes that directory is mounted on `/opt/storage`
|
|
370
|
+
const projectPersistentPath = path.join('/opt/persistent-storage', project.id)
|
|
371
|
+
rmSync(projectPersistentPath, { recursive: true, force: true })
|
|
372
|
+
} catch (err) {
|
|
373
|
+
this._app.log.error(`[docker] Project ${project.id} - error deleting persistent storage: ${err.stack}`)
|
|
374
|
+
}
|
|
375
|
+
}
|
|
317
376
|
delete this._projects[project.id]
|
|
318
377
|
},
|
|
319
378
|
/**
|