n8n-nodes-docker-api 0.1.0

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.
Files changed (40) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +278 -0
  3. package/dist/credentials/DockerApi.credentials.d.ts +7 -0
  4. package/dist/credentials/DockerApi.credentials.js +125 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.js +5 -0
  7. package/dist/nodes/Docker/Docker/docker.svg +25 -0
  8. package/dist/nodes/Docker/Docker.node.d.ts +5 -0
  9. package/dist/nodes/Docker/Docker.node.js +73 -0
  10. package/dist/nodes/Docker/actions/container/getLogs.operation.d.ts +3 -0
  11. package/dist/nodes/Docker/actions/container/getLogs.operation.js +82 -0
  12. package/dist/nodes/Docker/actions/container/list.operation.d.ts +3 -0
  13. package/dist/nodes/Docker/actions/container/list.operation.js +40 -0
  14. package/dist/nodes/Docker/actions/container/start.operation.d.ts +3 -0
  15. package/dist/nodes/Docker/actions/container/start.operation.js +21 -0
  16. package/dist/nodes/Docker/actions/container/stop.operation.d.ts +3 -0
  17. package/dist/nodes/Docker/actions/container/stop.operation.js +38 -0
  18. package/dist/nodes/Docker/actions/index.d.ts +3 -0
  19. package/dist/nodes/Docker/actions/index.js +25 -0
  20. package/dist/nodes/Docker/descriptions/container/getLogs.description.d.ts +2 -0
  21. package/dist/nodes/Docker/descriptions/container/getLogs.description.js +64 -0
  22. package/dist/nodes/Docker/descriptions/container/list.description.d.ts +2 -0
  23. package/dist/nodes/Docker/descriptions/container/list.description.js +66 -0
  24. package/dist/nodes/Docker/descriptions/container/start.description.d.ts +2 -0
  25. package/dist/nodes/Docker/descriptions/container/start.description.js +20 -0
  26. package/dist/nodes/Docker/descriptions/container/stop.description.d.ts +2 -0
  27. package/dist/nodes/Docker/descriptions/container/stop.description.js +46 -0
  28. package/dist/nodes/Docker/descriptions/index.d.ts +3 -0
  29. package/dist/nodes/Docker/descriptions/index.js +53 -0
  30. package/dist/nodes/Docker/helpers/accessGuard.d.ts +2 -0
  31. package/dist/nodes/Docker/helpers/accessGuard.js +13 -0
  32. package/dist/nodes/Docker/helpers/errorHandler.d.ts +1 -0
  33. package/dist/nodes/Docker/helpers/errorHandler.js +36 -0
  34. package/dist/nodes/Docker/helpers/normalizeContainer.d.ts +16 -0
  35. package/dist/nodes/Docker/helpers/normalizeContainer.js +71 -0
  36. package/dist/nodes/Docker/helpers/resolveContainer.d.ts +11 -0
  37. package/dist/nodes/Docker/helpers/resolveContainer.js +32 -0
  38. package/dist/utils/dockerClient.d.ts +3 -0
  39. package/dist/utils/dockerClient.js +31 -0
  40. package/package.json +69 -0
package/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright 2022 n8n
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,278 @@
1
+ ![n8n Docker Node](./assets/banner.png)
2
+
3
+ # ๐Ÿณ n8n-nodes-docker-api
4
+
5
+ ![npm](https://img.shields.io/npm/v/n8n-nodes-docker-api)
6
+ ![License](https://img.shields.io/npm/l/n8n-nodes-docker-api)
7
+
8
+ > Interact with Docker via direct API (no Portainer required) โ€” manage containers, stream logs, and automate infrastructure with ease.
9
+
10
+ ---
11
+
12
+ ## โœจ Why this node?
13
+
14
+ Managing Docker via raw HTTP calls in n8n is painful and error-prone.
15
+
16
+ This node gives you:
17
+
18
+ * ๐Ÿ” **Clean container listing** (normalized output)
19
+ * ๐Ÿ“œ **Readable logs** (stdout/stderr separated, no binary noise)
20
+ * โšก **Simple control** (start/stop containers safely)
21
+ * ๐Ÿ” **Built-in access control** (read-only vs full control)
22
+
23
+ ๐Ÿ‘‰ Turn Docker into a **first-class automation tool inside n8n**
24
+
25
+ ---
26
+
27
+ ## ๐Ÿš€ Quick Start
28
+
29
+ 1. Install the node:
30
+
31
+ ```bash
32
+ npm install n8n-nodes-docker-api
33
+ ```
34
+
35
+ 2. Add **Docker API credentials**
36
+ 3. Add the **Docker node** to your workflow
37
+ 4. Choose an operation and execute
38
+
39
+ โœ… No manual API calls needed
40
+
41
+ ---
42
+
43
+ ## ๐Ÿ“ฆ Installation
44
+
45
+ ### Community Nodes (Recommended)
46
+
47
+ 1. Go to **Settings โ†’ Community Nodes**
48
+ 2. Install: `n8n-nodes-docker-api`
49
+
50
+ ---
51
+
52
+ ### Manual Installation
53
+
54
+ ```bash
55
+ npm install n8n-nodes-docker-api
56
+ ```
57
+
58
+ ---
59
+
60
+ ## ๐Ÿงช Usage
61
+
62
+ ### Docker Node in n8n
63
+
64
+ ![Docker Node UI](./assets/node-ui.png)
65
+
66
+ 1. Add the **Docker node**
67
+ 2. Select an operation:
68
+
69
+ * List Containers
70
+ * Get Container Logs
71
+ * Start Container
72
+ * Stop Container
73
+ 3. Configure credentials
74
+ 4. Execute the node
75
+
76
+ ---
77
+
78
+ ### Example: List Containers
79
+
80
+ * Operation: `List Containers`
81
+ * Optional filters:
82
+
83
+ * Name
84
+ * Status
85
+ * Show all containers
86
+
87
+ ---
88
+
89
+ ## ๐Ÿ” Credentials
90
+
91
+ ### Credentials UI in n8n
92
+
93
+ ![Docker Credentials UI](./assets/credentials-ui.png)
94
+
95
+ ---
96
+
97
+ ### Connection Modes
98
+
99
+ #### ๐ŸŸข Unix Socket (Local)
100
+
101
+ * Default for local Docker setups
102
+ * Path: `/var/run/docker.sock`
103
+
104
+ ---
105
+
106
+ #### ๐ŸŒ TCP (Remote)
107
+
108
+ * Connect to remote Docker daemon
109
+ * Example:
110
+
111
+ * Host: `192.168.1.10`
112
+ * Port: `2375`
113
+
114
+ โš ๏ธ Requires Docker daemon configured with:
115
+
116
+ ```bash
117
+ -H tcp://0.0.0.0:2375
118
+ ```
119
+
120
+ ---
121
+
122
+ #### ๐Ÿ”’ TLS (Coming in v2)
123
+
124
+ * Secure remote connection using certificates
125
+
126
+ ---
127
+
128
+ ### Access Modes
129
+
130
+ #### ๐ŸŸก Read Only (Recommended)
131
+
132
+ * โœ… List containers
133
+ * โœ… Get logs
134
+ * โŒ Cannot start/stop containers
135
+
136
+ ---
137
+
138
+ #### ๐Ÿ”ด Full Control
139
+
140
+ * โœ… All operations enabled
141
+
142
+ ---
143
+
144
+ ## ๐Ÿ“‹ Supported Operations (v1)
145
+
146
+ | Operation | Description | Access |
147
+ | ------------------ | --------------------------------------- | ------------ |
148
+ | List Containers | Get containers with normalized output | Read Only |
149
+ | Get Container Logs | Logs with stream filtering & timestamps | Read Only |
150
+ | Start Container | Start stopped containers | Full Control |
151
+ | Stop Container | Stop running containers (with dry run) | Full Control |
152
+
153
+ ---
154
+
155
+ ## ๐Ÿ”ฅ Real Use Cases
156
+
157
+ ### โ™ป๏ธ Self-Healing Containers
158
+
159
+ Automatically restart crashed services:
160
+
161
+ ```
162
+ List Containers โ†’ IF (status != running) โ†’ Start Container
163
+ ```
164
+
165
+ ---
166
+
167
+ ### ๐Ÿšจ Log-Based Alerting
168
+
169
+ Detect errors and notify:
170
+
171
+ ```
172
+ Get Logs โ†’ Search "ERROR" โ†’ Send Slack alert
173
+ ```
174
+
175
+ ---
176
+
177
+ ### ๐Ÿ“Š Container Monitoring
178
+
179
+ Track system health:
180
+
181
+ ```
182
+ Schedule โ†’ List Containers โ†’ Aggregate โ†’ Report
183
+ ```
184
+
185
+ ---
186
+
187
+ ## ๐Ÿง  Output Examples
188
+
189
+ ### List Containers
190
+
191
+ ```json
192
+ {
193
+ "id": "3025272c7592...",
194
+ "shortId": "3025272c7592",
195
+ "name": "qdrant",
196
+ "image": "qdrant/qdrant",
197
+ "status": "running",
198
+ "createdAt": "2026-03-13T23:19:38.000Z"
199
+ }
200
+ ```
201
+
202
+ ---
203
+
204
+ ### Logs
205
+
206
+ ```json
207
+ {
208
+ "message": "Server started",
209
+ "stream": "stdout"
210
+ }
211
+ ```
212
+
213
+ ---
214
+
215
+ ## ๐Ÿ”’ Security
216
+
217
+ โš ๏ธ Docker access = **host-level control**
218
+
219
+ ### Best Practices
220
+
221
+ * Use **Read Only mode** unless needed
222
+ * Avoid exposing Docker over public TCP
223
+ * Use a proxy like:
224
+
225
+ * `tecnativa/docker-socket-proxy`
226
+ * Restrict network access
227
+
228
+ ---
229
+
230
+ ## ๐Ÿงช Testing
231
+
232
+ ```bash
233
+ npm test
234
+ ```
235
+
236
+ ---
237
+
238
+ ## ๐Ÿ—บ๏ธ Roadmap
239
+
240
+ ### v2
241
+
242
+ * Restart Container
243
+ * Remove Container
244
+ * Image operations (list/pull/remove)
245
+ * TLS support
246
+ * Container autocomplete
247
+
248
+ ### v3
249
+
250
+ * Run container (ephemeral jobs)
251
+ * Execute commands in container
252
+ * Container stats
253
+
254
+ ### v4
255
+
256
+ * Docker Trigger node (events)
257
+
258
+ ---
259
+
260
+ ## โญ Contributing
261
+
262
+ PRs and ideas are welcome โ€” especially for new operations and improvements.
263
+
264
+ ---
265
+
266
+ ## ๐Ÿ“„ License
267
+
268
+ MIT
269
+
270
+ ---
271
+
272
+ ## ๐Ÿ’ฌ Support
273
+
274
+ Open an issue on GitHub for:
275
+
276
+ * Bugs
277
+ * Feature requests
278
+ * Questions
@@ -0,0 +1,7 @@
1
+ import { ICredentialType, INodeProperties } from 'n8n-workflow';
2
+ export declare class DockerApi implements ICredentialType {
3
+ name: string;
4
+ displayName: string;
5
+ documentationUrl: string;
6
+ properties: INodeProperties[];
7
+ }
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DockerApi = void 0;
4
+ class DockerApi {
5
+ constructor() {
6
+ this.name = 'dockerApi';
7
+ this.displayName = 'Docker API';
8
+ this.documentationUrl = 'https://github.com/YOUR_USERNAME/n8n-nodes-docker';
9
+ this.properties = [
10
+ {
11
+ displayName: 'Connection Mode',
12
+ name: 'authMode',
13
+ type: 'options',
14
+ options: [
15
+ {
16
+ name: 'Unix Socket (Local)',
17
+ value: 'socket',
18
+ description: 'Connect to Docker via local Unix socket',
19
+ },
20
+ {
21
+ name: 'TCP (Remote)',
22
+ value: 'tcp',
23
+ description: 'Connect to a remote Docker daemon over TCP',
24
+ },
25
+ {
26
+ name: 'TLS (Secure Remote)',
27
+ value: 'tls',
28
+ description: 'Connect to a remote Docker daemon with TLS authentication',
29
+ },
30
+ ],
31
+ default: 'socket',
32
+ },
33
+ // --- Socket mode fields ---
34
+ {
35
+ displayName: 'Socket Path',
36
+ name: 'socketPath',
37
+ type: 'string',
38
+ default: '/var/run/docker.sock',
39
+ displayOptions: { show: { authMode: ['socket'] } },
40
+ description: 'Path to the Docker Unix socket',
41
+ },
42
+ // --- TCP mode fields ---
43
+ {
44
+ displayName: 'Host',
45
+ name: 'host',
46
+ type: 'string',
47
+ default: '',
48
+ placeholder: '192.168.1.100',
49
+ displayOptions: { show: { authMode: ['tcp', 'tls'] } },
50
+ description: 'IP address or hostname of the Docker host',
51
+ },
52
+ {
53
+ displayName: 'Port',
54
+ name: 'port',
55
+ type: 'number',
56
+ default: 2375,
57
+ displayOptions: { show: { authMode: ['tcp'] } },
58
+ description: 'Docker daemon TCP port (default: 2375)',
59
+ },
60
+ // --- TLS mode fields (v2 implementation, schema defined now) ---
61
+ {
62
+ displayName: 'TLS Port',
63
+ name: 'tlsPort',
64
+ type: 'number',
65
+ default: 2376,
66
+ displayOptions: { show: { authMode: ['tls'] } },
67
+ description: 'Docker daemon TLS port (default: 2376)',
68
+ },
69
+ {
70
+ displayName: 'CA Certificate',
71
+ name: 'ca',
72
+ type: 'string',
73
+ typeOptions: { rows: 4 },
74
+ default: '',
75
+ displayOptions: { show: { authMode: ['tls'] } },
76
+ description: 'TLS CA certificate (PEM format)',
77
+ },
78
+ {
79
+ displayName: 'Client Certificate',
80
+ name: 'cert',
81
+ type: 'string',
82
+ typeOptions: { rows: 4 },
83
+ default: '',
84
+ displayOptions: { show: { authMode: ['tls'] } },
85
+ description: 'TLS client certificate (PEM format)',
86
+ },
87
+ {
88
+ displayName: 'Client Key',
89
+ name: 'clientKey',
90
+ type: 'string',
91
+ typeOptions: { rows: 4, password: true },
92
+ default: '',
93
+ displayOptions: { show: { authMode: ['tls'] } },
94
+ description: 'TLS client private key (PEM format)',
95
+ },
96
+ // --- Access control ---
97
+ {
98
+ displayName: 'Access Mode',
99
+ name: 'accessMode',
100
+ type: 'options',
101
+ options: [
102
+ {
103
+ name: 'Read Only',
104
+ value: 'readonly',
105
+ description: 'Only list and inspect operations are allowed',
106
+ },
107
+ {
108
+ name: 'Full Control',
109
+ value: 'full',
110
+ description: 'All operations including start, stop, and remove are allowed',
111
+ },
112
+ ],
113
+ default: 'readonly',
114
+ description: 'Controls which operations this credential permits',
115
+ },
116
+ {
117
+ displayName: '',
118
+ name: 'securityNotice',
119
+ type: 'notice',
120
+ default: 'โš ๏ธ This credential connects to the Docker daemon. Full Control mode grants the ability to start, stop, and remove containers. Use Read Only mode unless write access is explicitly required.',
121
+ },
122
+ ];
123
+ }
124
+ }
125
+ exports.DockerApi = DockerApi;
@@ -0,0 +1,2 @@
1
+ import { Docker } from './nodes/Docker/Docker.node';
2
+ export declare const nodeTypes: (typeof Docker)[];
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.nodeTypes = void 0;
4
+ const Docker_node_1 = require("./nodes/Docker/Docker.node");
5
+ exports.nodeTypes = [Docker_node_1.Docker];
@@ -0,0 +1,25 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 340 268">
3
+ <!-- Generator: Adobe Illustrator 30.1.0, SVG Export Plug-In . SVG Version: 2.1.1 Build 136) -->
4
+ <defs>
5
+ <style>
6
+ .st0 {
7
+ fill: none;
8
+ }
9
+
10
+ .st1 {
11
+ fill: #2560ff;
12
+ }
13
+
14
+ .st2 {
15
+ clip-path: url(#clippath);
16
+ }
17
+ </style>
18
+ <clipPath id="clippath">
19
+ <rect class="st0" width="339.5" height="268"/>
20
+ </clipPath>
21
+ </defs>
22
+ <g class="st2">
23
+ <path class="st1" d="M334,110.1c-8.3-5.6-30.2-8-46.1-3.7-.9-15.8-9-29.2-24-40.8l-5.5-3.7-3.7,5.6c-7.2,11-10.3,25.7-9.2,39,.8,8.2,3.7,17.4,9.2,24.1-20.7,12-39.8,9.3-124.3,9.3H0c-.4,19.1,2.7,55.8,26,85.6,2.6,3.3,5.4,6.5,8.5,9.6,19,19,47.6,32.9,90.5,33,65.4,0,121.4-35.3,155.5-120.8,11.2.2,40.8,2,55.3-26,.4-.5,3.7-7.4,3.7-7.4l-5.5-3.7h0ZM85.2,92.7h-36.7v36.7h36.7v-36.7ZM132.6,92.7h-36.7v36.7h36.7v-36.7ZM179.9,92.7h-36.7v36.7h36.7v-36.7ZM227.3,92.7h-36.7v36.7h36.7v-36.7ZM37.8,92.7H1.1v36.7h36.7v-36.7ZM85.2,46.3h-36.7v36.7h36.7v-36.7ZM132.6,46.3h-36.7v36.7h36.7v-36.7ZM179.9,46.3h-36.7v36.7h36.7v-36.7ZM179.9,0h-36.7v36.7h36.7V0Z"/>
24
+ </g>
25
+ </svg>
@@ -0,0 +1,5 @@
1
+ import { IExecuteFunctions, INodeExecutionData, INodeType, INodeTypeDescription } from 'n8n-workflow';
2
+ export declare class Docker implements INodeType {
3
+ description: INodeTypeDescription;
4
+ execute(this: IExecuteFunctions): Promise<INodeExecutionData[][]>;
5
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Docker = void 0;
4
+ const n8n_workflow_1 = require("n8n-workflow");
5
+ const dockerClient_1 = require("../../utils/dockerClient");
6
+ const descriptions_1 = require("./descriptions");
7
+ const actions_1 = require("./actions");
8
+ const accessGuard_1 = require("./helpers/accessGuard");
9
+ class Docker {
10
+ constructor() {
11
+ this.description = {
12
+ displayName: 'Docker API',
13
+ name: 'docker',
14
+ icon: 'file:docker.svg',
15
+ group: ['transform'],
16
+ version: 1,
17
+ subtitle: '={{$parameter["operation"] + ": " + $parameter["resource"]}}',
18
+ description: 'Interact with Docker via direct API (no Portainer required)',
19
+ defaults: {
20
+ name: 'Docker API',
21
+ },
22
+ inputs: ['main'],
23
+ outputs: ['main'],
24
+ credentials: [
25
+ {
26
+ name: 'dockerApi',
27
+ required: true,
28
+ },
29
+ ],
30
+ properties: [
31
+ {
32
+ displayName: 'Resource',
33
+ name: 'resource',
34
+ type: 'options',
35
+ noDataExpression: true,
36
+ options: [
37
+ {
38
+ name: 'Container',
39
+ value: 'container',
40
+ },
41
+ ],
42
+ default: 'container',
43
+ },
44
+ ...descriptions_1.containerOperations,
45
+ ...descriptions_1.containerFields,
46
+ ],
47
+ };
48
+ }
49
+ async execute() {
50
+ const items = this.getInputData();
51
+ const credentials = await this.getCredentials('dockerApi');
52
+ const resource = this.getNodeParameter('resource', 0);
53
+ const operation = this.getNodeParameter('operation', 0);
54
+ (0, accessGuard_1.enforceAccessMode)(credentials, operation);
55
+ const docker = (0, dockerClient_1.createDockerClient)(credentials);
56
+ const returnData = [];
57
+ for (let i = 0; i < items.length; i++) {
58
+ try {
59
+ const result = await actions_1.executeContainerOperation.call(this, docker, operation, i);
60
+ returnData.push(...result);
61
+ }
62
+ catch (error) {
63
+ if (this.continueOnFail()) {
64
+ returnData.push({ json: { error: error.message }, pairedItem: i });
65
+ continue;
66
+ }
67
+ throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex: i });
68
+ }
69
+ }
70
+ return [returnData];
71
+ }
72
+ }
73
+ exports.Docker = Docker;
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { IExecuteFunctions } from 'n8n-workflow';
3
+ export declare function getContainerLogs(this: IExecuteFunctions, docker: Docker, itemIndex: number): Promise<any>;
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getContainerLogs = getContainerLogs;
4
+ const errorHandler_1 = require("../../helpers/errorHandler");
5
+ const resolveContainer_1 = require("../../helpers/resolveContainer");
6
+ /**
7
+ * Demultiplexes Docker log buffer format.
8
+ * Docker logs use an 8-byte header: [stream type (1 byte)][0,0,0,0][size (4 bytes)][payload]
9
+ * Stream type: 1 = stdout, 2 = stderr
10
+ */
11
+ function demuxDockerLogs(buffer) {
12
+ const logs = [];
13
+ let offset = 0;
14
+ while (offset < buffer.length) {
15
+ // Need at least 8 bytes for header
16
+ if (offset + 8 > buffer.length) {
17
+ break;
18
+ }
19
+ const streamType = buffer[offset];
20
+ // Bytes 1-4 are zeros
21
+ // Bytes 5-8 are the payload size (big-endian uint32)
22
+ const payloadSize = buffer.readUInt32BE(offset + 4);
23
+ // Validate we have enough data for the payload
24
+ if (offset + 8 + payloadSize > buffer.length) {
25
+ break;
26
+ }
27
+ const payload = buffer.slice(offset + 8, offset + 8 + payloadSize);
28
+ const message = payload.toString('utf8');
29
+ // Split message into lines and add each line separately
30
+ const lines = message.split('\n').filter((line) => line.length > 0);
31
+ for (const line of lines) {
32
+ logs.push({
33
+ message: line,
34
+ stream: streamType === 1 ? 'stdout' : 'stderr',
35
+ });
36
+ }
37
+ offset += 8 + payloadSize;
38
+ }
39
+ return logs;
40
+ }
41
+ async function getContainerLogs(docker, itemIndex) {
42
+ try {
43
+ const containerId = this.getNodeParameter('containerId', itemIndex);
44
+ const tail = this.getNodeParameter('tail', itemIndex, 100);
45
+ const timestamps = this.getNodeParameter('timestamps', itemIndex, false);
46
+ const stream = this.getNodeParameter('stream', itemIndex, 'both');
47
+ // Resolve name to ID first
48
+ const resolved = await (0, resolveContainer_1.resolveContainer)(docker, containerId);
49
+ const container = docker.getContainer(resolved.id);
50
+ const logOptions = {
51
+ stdout: stream === 'both' || stream === 'stdout',
52
+ stderr: stream === 'both' || stream === 'stderr',
53
+ tail: tail === 0 ? undefined : tail,
54
+ follow: false,
55
+ timestamps,
56
+ };
57
+ // Get logs as a Buffer (follow: false returns Buffer)
58
+ const logsBuffer = await container.logs(logOptions);
59
+ // Demultiplex the Docker log format
60
+ const allLogs = demuxDockerLogs(logsBuffer);
61
+ // Filter logs based on stream selection
62
+ let logs = allLogs;
63
+ if (stream === 'stdout') {
64
+ logs = allLogs.filter((log) => log.stream === 'stdout');
65
+ }
66
+ else if (stream === 'stderr') {
67
+ logs = allLogs.filter((log) => log.stream === 'stderr');
68
+ }
69
+ return {
70
+ containerId: resolved.id,
71
+ shortId: resolved.id.substring(0, 12),
72
+ containerName: resolved.name,
73
+ logs,
74
+ lineCount: logs.length,
75
+ stream,
76
+ retrievedAt: new Date().toISOString(),
77
+ };
78
+ }
79
+ catch (error) {
80
+ throw new Error((0, errorHandler_1.translateDockerError)(error));
81
+ }
82
+ }
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { IExecuteFunctions } from 'n8n-workflow';
3
+ export declare function listContainers(this: IExecuteFunctions, docker: Docker, itemIndex: number): Promise<any[]>;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listContainers = listContainers;
4
+ const errorHandler_1 = require("../../helpers/errorHandler");
5
+ const normalizeContainer_1 = require("../../helpers/normalizeContainer");
6
+ /**
7
+ * Maps user-friendly status values to Docker API values
8
+ */
9
+ const statusMap = {
10
+ stopped: 'exited',
11
+ };
12
+ async function listContainers(docker, itemIndex) {
13
+ try {
14
+ const showAll = this.getNodeParameter('showAll', itemIndex, false);
15
+ const filters = this.getNodeParameter('filters', itemIndex, {});
16
+ const includeLabels = this.getNodeParameter('includeLabels', itemIndex, true);
17
+ const listOptions = {
18
+ all: showAll,
19
+ filters: {},
20
+ };
21
+ // Build filters - map user-friendly values to Docker API values
22
+ if (filters.status && filters.status !== '') {
23
+ const dockerStatus = statusMap[filters.status.toLowerCase()] || filters.status;
24
+ listOptions.filters = {
25
+ status: [dockerStatus],
26
+ };
27
+ }
28
+ const containers = await docker.listContainers(listOptions);
29
+ // Normalize and filter by name if provided
30
+ let normalized = containers.map((c) => (0, normalizeContainer_1.normalizeContainerInfo)(c, includeLabels));
31
+ if (filters.name && filters.name !== '') {
32
+ const nameFilter = filters.name.toLowerCase();
33
+ normalized = normalized.filter((c) => c.name.toLowerCase().includes(nameFilter));
34
+ }
35
+ return normalized;
36
+ }
37
+ catch (error) {
38
+ throw new Error((0, errorHandler_1.translateDockerError)(error));
39
+ }
40
+ }
@@ -0,0 +1,3 @@
1
+ import Docker from 'dockerode';
2
+ import { IExecuteFunctions } from 'n8n-workflow';
3
+ export declare function startContainer(this: IExecuteFunctions, docker: Docker, itemIndex: number): Promise<any>;