@enjoys/context-engine 1.0.7 → 1.0.9

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.
@@ -4,533 +4,1282 @@
4
4
  {
5
5
  "label": "FROM",
6
6
  "kind": 14,
7
- "detail": "Set the base image",
8
- "documentation": { "value": "Initialize a new build stage and set the base image.\n\n```dockerfile\nFROM ubuntu:22.04\nFROM node:20-alpine\nFROM --platform=linux/amd64 golang:1.21\n```" },
9
- "insertText": "FROM ${1:image}:${2:tag}",
7
+ "detail": "Base image instruction",
8
+ "documentation": {
9
+ "value": "Set the base image for subsequent instructions. Every Dockerfile must start with FROM (except ARG before FROM)."
10
+ },
11
+ "insertText": "FROM",
12
+ "sortText": "00_from"
13
+ },
14
+ {
15
+ "label": "RUN",
16
+ "kind": 14,
17
+ "detail": "Execute command",
18
+ "documentation": {
19
+ "value": "Execute a command in a new layer on top of the current image and commit the result."
20
+ },
21
+ "insertText": "RUN",
22
+ "sortText": "00_run"
23
+ },
24
+ {
25
+ "label": "CMD",
26
+ "kind": 14,
27
+ "detail": "Default command",
28
+ "documentation": {
29
+ "value": "Provide defaults for an executing container. Only one CMD per Dockerfile; the last one wins."
30
+ },
31
+ "insertText": "CMD",
32
+ "sortText": "00_cmd"
33
+ },
34
+ {
35
+ "label": "LABEL",
36
+ "kind": 14,
37
+ "detail": "Metadata label",
38
+ "documentation": {
39
+ "value": "Add metadata key-value pairs to the image."
40
+ },
41
+ "insertText": "LABEL",
42
+ "sortText": "00_label"
43
+ },
44
+ {
45
+ "label": "MAINTAINER",
46
+ "kind": 14,
47
+ "detail": "Author (deprecated)",
48
+ "documentation": {
49
+ "value": "Set the Author field of the generated image. Deprecated in favor of LABEL."
50
+ },
51
+ "insertText": "MAINTAINER",
52
+ "sortText": "00_maintainer"
53
+ },
54
+ {
55
+ "label": "EXPOSE",
56
+ "kind": 14,
57
+ "detail": "Expose port",
58
+ "documentation": {
59
+ "value": "Inform Docker that the container listens on the specified network ports at runtime."
60
+ },
61
+ "insertText": "EXPOSE",
62
+ "sortText": "00_expose"
63
+ },
64
+ {
65
+ "label": "ENV",
66
+ "kind": 14,
67
+ "detail": "Environment variable",
68
+ "documentation": {
69
+ "value": "Set an environment variable that persists in the built image and running containers."
70
+ },
71
+ "insertText": "ENV",
72
+ "sortText": "00_env"
73
+ },
74
+ {
75
+ "label": "ADD",
76
+ "kind": 14,
77
+ "detail": "Add files",
78
+ "documentation": {
79
+ "value": "Copy files, directories, or remote URLs into the image filesystem. Automatically extracts tar archives."
80
+ },
81
+ "insertText": "ADD",
82
+ "sortText": "00_add"
83
+ },
84
+ {
85
+ "label": "COPY",
86
+ "kind": 14,
87
+ "detail": "Copy files",
88
+ "documentation": {
89
+ "value": "Copy files or directories from the build context into the image filesystem."
90
+ },
91
+ "insertText": "COPY",
92
+ "sortText": "00_copy"
93
+ },
94
+ {
95
+ "label": "ENTRYPOINT",
96
+ "kind": 14,
97
+ "detail": "Container entrypoint",
98
+ "documentation": {
99
+ "value": "Configure a container that will run as an executable."
100
+ },
101
+ "insertText": "ENTRYPOINT",
102
+ "sortText": "00_entrypoint"
103
+ },
104
+ {
105
+ "label": "VOLUME",
106
+ "kind": 14,
107
+ "detail": "Create mount point",
108
+ "documentation": {
109
+ "value": "Create a mount point with the specified name and mark it as holding externally mounted volumes."
110
+ },
111
+ "insertText": "VOLUME",
112
+ "sortText": "00_volume"
113
+ },
114
+ {
115
+ "label": "USER",
116
+ "kind": 14,
117
+ "detail": "Set user",
118
+ "documentation": {
119
+ "value": "Set the user name or UID (and optionally group) to use for RUN, CMD, and ENTRYPOINT instructions."
120
+ },
121
+ "insertText": "USER",
122
+ "sortText": "00_user"
123
+ },
124
+ {
125
+ "label": "WORKDIR",
126
+ "kind": 14,
127
+ "detail": "Set working directory",
128
+ "documentation": {
129
+ "value": "Set the working directory for RUN, CMD, ENTRYPOINT, COPY, and ADD instructions."
130
+ },
131
+ "insertText": "WORKDIR",
132
+ "sortText": "00_workdir"
133
+ },
134
+ {
135
+ "label": "ARG",
136
+ "kind": 14,
137
+ "detail": "Build argument",
138
+ "documentation": {
139
+ "value": "Define a build-time variable that users can pass with --build-arg."
140
+ },
141
+ "insertText": "ARG",
142
+ "sortText": "00_arg"
143
+ },
144
+ {
145
+ "label": "ONBUILD",
146
+ "kind": 14,
147
+ "detail": "Deferred instruction",
148
+ "documentation": {
149
+ "value": "Add a trigger instruction that executes when the image is used as a base for another build."
150
+ },
151
+ "insertText": "ONBUILD",
152
+ "sortText": "00_onbuild"
153
+ },
154
+ {
155
+ "label": "STOPSIGNAL",
156
+ "kind": 14,
157
+ "detail": "Stop signal",
158
+ "documentation": {
159
+ "value": "Set the system call signal that will be sent to the container to exit."
160
+ },
161
+ "insertText": "STOPSIGNAL",
162
+ "sortText": "00_stopsignal"
163
+ },
164
+ {
165
+ "label": "HEALTHCHECK",
166
+ "kind": 14,
167
+ "detail": "Health check",
168
+ "documentation": {
169
+ "value": "Tell Docker how to test a container to check that it is still working."
170
+ },
171
+ "insertText": "HEALTHCHECK",
172
+ "sortText": "00_healthcheck"
173
+ },
174
+ {
175
+ "label": "SHELL",
176
+ "kind": 14,
177
+ "detail": "Default shell",
178
+ "documentation": {
179
+ "value": "Override the default shell used for the shell form of commands."
180
+ },
181
+ "insertText": "SHELL",
182
+ "sortText": "00_shell"
183
+ },
184
+ {
185
+ "label": "FROM image",
186
+ "kind": 15,
187
+ "detail": "FROM with image",
188
+ "documentation": {
189
+ "value": "Basic FROM with image name."
190
+ },
191
+ "insertText": "FROM ${1:image}",
10
192
  "insertTextRules": 4,
11
- "sortText": "00_FROM"
193
+ "sortText": "01_from_basic"
12
194
  },
13
195
  {
14
- "label": "FROM ... AS (multi-stage)",
196
+ "label": "FROM image:tag",
15
197
  "kind": 15,
16
- "detail": "Multi-stage build base image",
17
- "documentation": { "value": "Set a base image with a named build stage for multi-stage builds.\n\n```dockerfile\nFROM node:20-alpine AS builder\nRUN npm ci && npm run build\n\nFROM nginx:alpine AS production\nCOPY --from=builder /app/dist /usr/share/nginx/html\n```" },
18
- "insertText": "FROM ${1:image}:${2:tag} AS ${3:stage_name}",
198
+ "detail": "FROM with tag",
199
+ "documentation": {
200
+ "value": "FROM with explicit image tag."
201
+ },
202
+ "insertText": "FROM ${1:image}:${2:tag}",
19
203
  "insertTextRules": 4,
20
- "sortText": "00_FROM_AS"
204
+ "sortText": "01_from_tag"
21
205
  },
22
206
  {
23
- "label": "FROM scratch",
207
+ "label": "FROM image AS stage",
24
208
  "kind": 15,
25
- "detail": "Start from an empty image",
26
- "documentation": { "value": "Use an empty base image. Commonly used for statically compiled binaries (Go, Rust).\n\n```dockerfile\nFROM scratch\nCOPY --from=builder /app/mybin /mybin\nENTRYPOINT [\"/mybin\"]\n```" },
27
- "insertText": "FROM scratch",
209
+ "detail": "FROM multi-stage",
210
+ "documentation": {
211
+ "value": "FROM with AS alias for multi-stage builds."
212
+ },
213
+ "insertText": "FROM ${1:image}:${2:tag} AS ${3:builder}",
28
214
  "insertTextRules": 4,
29
- "sortText": "00_FROM_scratch"
215
+ "sortText": "01_from_as"
30
216
  },
31
217
  {
32
218
  "label": "FROM --platform",
33
219
  "kind": 15,
34
- "detail": "Set base image with platform",
35
- "documentation": { "value": "Specify the target platform for the build stage.\n\n```dockerfile\nFROM --platform=linux/amd64 ubuntu:22.04\nFROM --platform=$BUILDPLATFORM golang:1.21 AS builder\n```" },
36
- "insertText": "FROM --platform=${1|linux/amd64,linux/arm64,$BUILDPLATFORM,$TARGETPLATFORM|} ${2:image}:${3:tag}",
220
+ "detail": "FROM with platform",
221
+ "documentation": {
222
+ "value": "FROM with explicit platform for cross-compilation."
223
+ },
224
+ "insertText": "FROM --platform=${1|linux/amd64,linux/arm64,linux/arm/v7,\\$BUILDPLATFORM,\\$TARGETPLATFORM|} ${2:image}:${3:tag}",
37
225
  "insertTextRules": 4,
38
- "sortText": "00_FROM_platform"
226
+ "sortText": "01_from_platform"
39
227
  },
40
228
  {
41
- "label": "RUN",
42
- "kind": 14,
43
- "detail": "Execute a command in the build",
44
- "documentation": { "value": "Execute a command in a new layer on top of the current image.\n\n```dockerfile\nRUN apt-get update && apt-get install -y curl\nRUN pip install --no-cache-dir -r requirements.txt\n```" },
229
+ "label": "FROM --platform AS",
230
+ "kind": 15,
231
+ "detail": "FROM platform + stage",
232
+ "documentation": {
233
+ "value": "FROM with platform and stage alias."
234
+ },
235
+ "insertText": "FROM --platform=${1|linux/amd64,linux/arm64,\\$BUILDPLATFORM,\\$TARGETPLATFORM|} ${2:image}:${3:tag} AS ${4:stage}",
236
+ "insertTextRules": 4,
237
+ "sortText": "01_from_platform_as"
238
+ },
239
+ {
240
+ "label": "FROM scratch",
241
+ "kind": 15,
242
+ "detail": "FROM scratch (empty)",
243
+ "documentation": {
244
+ "value": "Start from an empty image, used for statically linked binaries."
245
+ },
246
+ "insertText": "FROM scratch",
247
+ "insertTextRules": 4,
248
+ "sortText": "01_from_scratch"
249
+ },
250
+ {
251
+ "label": "RUN shell",
252
+ "kind": 15,
253
+ "detail": "RUN shell form",
254
+ "documentation": {
255
+ "value": "Execute command in shell form (/bin/sh -c)."
256
+ },
45
257
  "insertText": "RUN ${1:command}",
46
258
  "insertTextRules": 4,
47
- "sortText": "01_RUN"
259
+ "sortText": "02_run_shell"
48
260
  },
49
261
  {
50
- "label": "RUN (exec form)",
262
+ "label": "RUN exec",
51
263
  "kind": 15,
52
- "detail": "Execute a command in exec form",
53
- "documentation": { "value": "Execute a command using the exec form (JSON array). This avoids shell processing and is preferred when you don't need shell features.\n\n```dockerfile\nRUN [\"executable\", \"param1\", \"param2\"]\nRUN [\"apt-get\", \"install\", \"-y\", \"curl\"]\n```" },
54
- "insertText": "RUN [\"${1:executable}\", \"${2:param1}\"]",
264
+ "detail": "RUN exec form",
265
+ "documentation": {
266
+ "value": "Execute command in exec form (no shell processing)."
267
+ },
268
+ "insertText": "RUN [\"${1:executable}\", \"${2:arg1}\", \"${3:arg2}\"]",
55
269
  "insertTextRules": 4,
56
- "sortText": "01_RUN_exec"
270
+ "sortText": "02_run_exec"
57
271
  },
58
272
  {
59
- "label": "RUN --mount=type=cache",
273
+ "label": "RUN --mount=cache",
60
274
  "kind": 15,
61
275
  "detail": "RUN with cache mount",
62
- "documentation": { "value": "Mount a cache directory that persists across builds. Speeds up package manager installs.\n\n```dockerfile\nRUN --mount=type=cache,target=/var/cache/apt \\\n apt-get update && apt-get install -y curl\n\nRUN --mount=type=cache,target=/root/.cache/pip \\\n pip install -r requirements.txt\n```" },
63
- "insertText": "RUN --mount=type=cache,target=${1:/var/cache/apt} \\\n ${2:command}",
276
+ "documentation": {
277
+ "value": "Mount a persistent cache directory for package managers."
278
+ },
279
+ "insertText": "RUN --mount=type=cache,target=${1:/var/cache/apt} \\\n ${2:apt-get update && apt-get install -y package}",
64
280
  "insertTextRules": 4,
65
- "sortText": "01_RUN_cache"
281
+ "sortText": "02_run_mount_cache"
66
282
  },
67
283
  {
68
- "label": "RUN --mount=type=secret",
284
+ "label": "RUN --mount=bind",
285
+ "kind": 15,
286
+ "detail": "RUN with bind mount",
287
+ "documentation": {
288
+ "value": "Bind mount a directory from the build context."
289
+ },
290
+ "insertText": "RUN --mount=type=bind,source=${1:src},target=${2:/app/src} \\\n ${3:command}",
291
+ "insertTextRules": 4,
292
+ "sortText": "02_run_mount_bind"
293
+ },
294
+ {
295
+ "label": "RUN --mount=secret",
69
296
  "kind": 15,
70
297
  "detail": "RUN with secret mount",
71
- "documentation": { "value": "Mount a secret file that won't be stored in the final image.\n\n```dockerfile\nRUN --mount=type=secret,id=mysecret,target=/run/secrets/mysecret \\\n cat /run/secrets/mysecret\n\n# Build: docker build --secret id=mysecret,src=secret.txt .\n```" },
72
- "insertText": "RUN --mount=type=secret,id=${1:secret_id},target=${2:/run/secrets/$1} \\\n ${3:command}",
298
+ "documentation": {
299
+ "value": "Mount a secret file without persisting in the image layer."
300
+ },
301
+ "insertText": "RUN --mount=type=secret,id=${1:mysecret},target=${2:/run/secrets/mysecret} \\\n ${3:cat /run/secrets/mysecret}",
73
302
  "insertTextRules": 4,
74
- "sortText": "01_RUN_secret"
303
+ "sortText": "02_run_mount_secret"
75
304
  },
76
305
  {
77
- "label": "RUN --mount=type=ssh",
306
+ "label": "RUN --mount=ssh",
78
307
  "kind": 15,
79
- "detail": "RUN with SSH agent forwarding",
80
- "documentation": { "value": "Mount the SSH agent socket for accessing private repositories.\n\n```dockerfile\nRUN --mount=type=ssh \\\n git clone git@github.com:private/repo.git\n\n# Build: docker build --ssh default .\n```" },
308
+ "detail": "RUN with SSH mount",
309
+ "documentation": {
310
+ "value": "Forward SSH agent for private repo access during build."
311
+ },
81
312
  "insertText": "RUN --mount=type=ssh \\\n ${1:git clone git@github.com:user/repo.git}",
82
313
  "insertTextRules": 4,
83
- "sortText": "01_RUN_ssh"
314
+ "sortText": "02_run_mount_ssh"
84
315
  },
85
316
  {
86
- "label": "CMD",
87
- "kind": 14,
88
- "detail": "Default command for the container",
89
- "documentation": { "value": "Set the default command to run when the container starts. Only the last CMD takes effect.\n\n```dockerfile\nCMD [\"node\", \"server.js\"]\nCMD [\"python\", \"app.py\"]\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n```" },
90
- "insertText": "CMD [\"${1:executable}\", \"${2:param1}\"]",
317
+ "label": "RUN --mount=tmpfs",
318
+ "kind": 15,
319
+ "detail": "RUN with tmpfs mount",
320
+ "documentation": {
321
+ "value": "Mount a tmpfs for temporary scratch space."
322
+ },
323
+ "insertText": "RUN --mount=type=tmpfs,target=${1:/tmp} \\\n ${2:command}",
91
324
  "insertTextRules": 4,
92
- "sortText": "02_CMD"
325
+ "sortText": "02_run_mount_tmpfs"
93
326
  },
94
327
  {
95
- "label": "LABEL",
96
- "kind": 14,
97
- "detail": "Add metadata to an image",
98
- "documentation": { "value": "Add metadata as key-value pairs to an image.\n\n```dockerfile\nLABEL maintainer=\"user@example.com\"\nLABEL version=\"1.0\" description=\"My app\"\nLABEL org.opencontainers.image.source=\"https://github.com/user/repo\"\n```" },
99
- "insertText": "LABEL ${1:key}=\"${2:value}\"",
328
+ "label": "RUN heredoc",
329
+ "kind": 15,
330
+ "detail": "RUN with heredoc",
331
+ "documentation": {
332
+ "value": "Run multi-line script using heredoc syntax (BuildKit)."
333
+ },
334
+ "insertText": "RUN <<EOF\n${1:#!/bin/bash\nset -e\necho \"hello\"}\nEOF",
100
335
  "insertTextRules": 4,
101
- "sortText": "03_LABEL"
336
+ "sortText": "02_run_heredoc"
102
337
  },
103
338
  {
104
- "label": "MAINTAINER",
105
- "kind": 14,
106
- "detail": "Set the author (deprecated)",
107
- "documentation": { "value": "**Deprecated.** Use `LABEL maintainer=\"...\"` instead.\n\n```dockerfile\n# Deprecated:\nMAINTAINER user@example.com\n\n# Preferred:\nLABEL maintainer=\"user@example.com\"\n```" },
108
- "insertText": "MAINTAINER ${1:name}",
339
+ "label": "RUN apt-get install",
340
+ "kind": 15,
341
+ "detail": "RUN apt-get best practice",
342
+ "documentation": {
343
+ "value": "Best practice apt-get install: update + install + clean in one layer."
344
+ },
345
+ "insertText": "RUN apt-get update && apt-get install -y --no-install-recommends \\\n ${1:package1} \\\n ${2:package2} \\\n && rm -rf /var/lib/apt/lists/*",
109
346
  "insertTextRules": 4,
110
- "sortText": "04_MAINTAINER"
347
+ "sortText": "02_run_apt"
111
348
  },
112
349
  {
113
- "label": "EXPOSE",
114
- "kind": 14,
115
- "detail": "Declare container listen port",
116
- "documentation": { "value": "Inform Docker the container listens on the specified port(s) at runtime. This is documentation only — you still need `-p` to publish.\n\n```dockerfile\nEXPOSE 80\nEXPOSE 443\nEXPOSE 3000/tcp 3001/udp\n```" },
117
- "insertText": "EXPOSE ${1:port}",
350
+ "label": "RUN pip install",
351
+ "kind": 15,
352
+ "detail": "RUN pip install",
353
+ "documentation": {
354
+ "value": "Install Python packages with no cache for smaller images."
355
+ },
356
+ "insertText": "RUN pip install --no-cache-dir ${1:-r requirements.txt}",
118
357
  "insertTextRules": 4,
119
- "sortText": "05_EXPOSE"
358
+ "sortText": "02_run_pip"
120
359
  },
121
360
  {
122
- "label": "ENV",
123
- "kind": 14,
124
- "detail": "Set environment variable",
125
- "documentation": { "value": "Set an environment variable that persists in the running container.\n\n```dockerfile\nENV NODE_ENV=production\nENV APP_HOME=/app\nENV PATH=\"/app/bin:$PATH\"\n```" },
126
- "insertText": "ENV ${1:KEY}=${2:value}",
361
+ "label": "RUN npm ci",
362
+ "kind": 15,
363
+ "detail": "RUN npm ci",
364
+ "documentation": {
365
+ "value": "Install Node.js dependencies for reproducible builds."
366
+ },
367
+ "insertText": "RUN npm ci --only=production",
127
368
  "insertTextRules": 4,
128
- "sortText": "06_ENV"
369
+ "sortText": "02_run_npm_ci"
129
370
  },
130
371
  {
131
- "label": "ADD",
132
- "kind": 14,
133
- "detail": "Add files to the image",
134
- "documentation": { "value": "Copy files, directories, or remote URLs into the image. Supports auto-extraction of tar archives. Prefer COPY unless you need tar extraction or URLs.\n\n```dockerfile\nADD app.tar.gz /app/\nADD https://example.com/file.txt /data/\nADD --chown=1000:1000 files/ /app/\n```" },
135
- "insertText": "ADD ${1:src} ${2:dest}",
372
+ "label": "RUN apk add",
373
+ "kind": 15,
374
+ "detail": "RUN apk add (Alpine)",
375
+ "documentation": {
376
+ "value": "Install packages on Alpine Linux."
377
+ },
378
+ "insertText": "RUN apk add --no-cache \\\n ${1:package1} \\\n ${2:package2}",
136
379
  "insertTextRules": 4,
137
- "sortText": "07_ADD"
380
+ "sortText": "02_run_apk"
138
381
  },
139
382
  {
140
- "label": "COPY",
141
- "kind": 14,
142
- "detail": "Copy files into the image",
143
- "documentation": { "value": "Copy files or directories from the build context into the image.\n\n```dockerfile\nCOPY . /app/\nCOPY package.json package-lock.json ./\nCOPY --chown=node:node src/ /app/src/\n```" },
144
- "insertText": "COPY ${1:src} ${2:dest}",
383
+ "label": "RUN --network=none",
384
+ "kind": 15,
385
+ "detail": "RUN without network",
386
+ "documentation": {
387
+ "value": "Run command with network disabled for security."
388
+ },
389
+ "insertText": "RUN --network=none ${1:command}",
145
390
  "insertTextRules": 4,
146
- "sortText": "08_COPY"
391
+ "sortText": "02_run_network_none"
147
392
  },
148
393
  {
149
- "label": "COPY --from",
394
+ "label": "RUN --security=insecure",
150
395
  "kind": 15,
151
- "detail": "Copy files from another build stage",
152
- "documentation": { "value": "Copy files from a named build stage or external image.\n\n```dockerfile\nCOPY --from=builder /app/dist /usr/share/nginx/html\nCOPY --from=0 /app/bin /usr/local/bin/\nCOPY --from=alpine:latest /etc/alpine-release /\n```" },
153
- "insertText": "COPY --from=${1:stage} ${2:src} ${3:dest}",
396
+ "detail": "RUN insecure (privileged)",
397
+ "documentation": {
398
+ "value": "Run with elevated privileges (requires security.insecure entitlement)."
399
+ },
400
+ "insertText": "RUN --security=insecure ${1:command}",
154
401
  "insertTextRules": 4,
155
- "sortText": "08_COPY_from"
402
+ "sortText": "02_run_security"
403
+ },
404
+ {
405
+ "label": "RUN useradd",
406
+ "kind": 15,
407
+ "detail": "RUN create user",
408
+ "documentation": {
409
+ "value": "Create a non-root user for running the application."
410
+ },
411
+ "insertText": "RUN groupadd -r ${1:appuser} && useradd -r -g ${1:appuser} -d /home/${1:appuser} -s /sbin/nologin ${1:appuser}",
412
+ "insertTextRules": 4,
413
+ "sortText": "02_run_useradd"
414
+ },
415
+ {
416
+ "label": "RUN adduser Alpine",
417
+ "kind": 15,
418
+ "detail": "RUN create user (Alpine)",
419
+ "documentation": {
420
+ "value": "Create a non-root user on Alpine."
421
+ },
422
+ "insertText": "RUN addgroup -S ${1:appuser} && adduser -S ${1:appuser} -G ${1:appuser}",
423
+ "insertTextRules": 4,
424
+ "sortText": "02_run_adduser_alpine"
425
+ },
426
+ {
427
+ "label": "CMD exec form",
428
+ "kind": 15,
429
+ "detail": "CMD exec form",
430
+ "documentation": {
431
+ "value": "Set default command in exec form (preferred)."
432
+ },
433
+ "insertText": "CMD [\"${1:executable}\", \"${2:arg1}\"]",
434
+ "insertTextRules": 4,
435
+ "sortText": "03_cmd_exec"
436
+ },
437
+ {
438
+ "label": "CMD shell form",
439
+ "kind": 15,
440
+ "detail": "CMD shell form",
441
+ "documentation": {
442
+ "value": "Set default command in shell form."
443
+ },
444
+ "insertText": "CMD ${1:command arg1 arg2}",
445
+ "insertTextRules": 4,
446
+ "sortText": "03_cmd_shell"
447
+ },
448
+ {
449
+ "label": "CMD as ENTRYPOINT params",
450
+ "kind": 15,
451
+ "detail": "CMD default parameters",
452
+ "documentation": {
453
+ "value": "Provide default parameters to ENTRYPOINT."
454
+ },
455
+ "insertText": "CMD [\"${1:--help}\"]",
456
+ "insertTextRules": 4,
457
+ "sortText": "03_cmd_params"
458
+ },
459
+ {
460
+ "label": "ENTRYPOINT exec form",
461
+ "kind": 15,
462
+ "detail": "ENTRYPOINT exec form",
463
+ "documentation": {
464
+ "value": "Set entrypoint in exec form (preferred)."
465
+ },
466
+ "insertText": "ENTRYPOINT [\"${1:executable}\", \"${2:arg1}\"]",
467
+ "insertTextRules": 4,
468
+ "sortText": "04_entrypoint_exec"
469
+ },
470
+ {
471
+ "label": "ENTRYPOINT shell form",
472
+ "kind": 15,
473
+ "detail": "ENTRYPOINT shell form",
474
+ "documentation": {
475
+ "value": "Set entrypoint in shell form."
476
+ },
477
+ "insertText": "ENTRYPOINT ${1:command arg1}",
478
+ "insertTextRules": 4,
479
+ "sortText": "04_entrypoint_shell"
480
+ },
481
+ {
482
+ "label": "ENTRYPOINT with tini",
483
+ "kind": 15,
484
+ "detail": "ENTRYPOINT with tini",
485
+ "documentation": {
486
+ "value": "Use tini as PID 1 for proper signal handling."
487
+ },
488
+ "insertText": "ENTRYPOINT [\"tini\", \"--\", \"${1:executable}\"]",
489
+ "insertTextRules": 4,
490
+ "sortText": "04_entrypoint_tini"
491
+ },
492
+ {
493
+ "label": "ENTRYPOINT with dumb-init",
494
+ "kind": 15,
495
+ "detail": "ENTRYPOINT with dumb-init",
496
+ "documentation": {
497
+ "value": "Use dumb-init as PID 1 for signal forwarding."
498
+ },
499
+ "insertText": "ENTRYPOINT [\"dumb-init\", \"--\", \"${1:executable}\"]",
500
+ "insertTextRules": 4,
501
+ "sortText": "04_entrypoint_dumb_init"
502
+ },
503
+ {
504
+ "label": "COPY basic",
505
+ "kind": 15,
506
+ "detail": "COPY files",
507
+ "documentation": {
508
+ "value": "Copy files from build context into the image."
509
+ },
510
+ "insertText": "COPY ${1:src} ${2:dest}",
511
+ "insertTextRules": 4,
512
+ "sortText": "05_copy_basic"
156
513
  },
157
514
  {
158
515
  "label": "COPY --chown",
159
516
  "kind": 15,
160
- "detail": "Copy files with ownership",
161
- "documentation": { "value": "Copy files and set ownership in a single step.\n\n```dockerfile\nCOPY --chown=node:node . /app/\nCOPY --chown=1000:1000 config/ /etc/app/\n```" },
517
+ "detail": "COPY with chown",
518
+ "documentation": {
519
+ "value": "Copy files and set ownership."
520
+ },
162
521
  "insertText": "COPY --chown=${1:user}:${2:group} ${3:src} ${4:dest}",
163
522
  "insertTextRules": 4,
164
- "sortText": "08_COPY_chown"
523
+ "sortText": "05_copy_chown"
165
524
  },
166
525
  {
167
- "label": "ENTRYPOINT",
168
- "kind": 14,
169
- "detail": "Configure the container executable",
170
- "documentation": { "value": "Set the main executable for the container. CMD arguments are appended to ENTRYPOINT.\n\n```dockerfile\nENTRYPOINT [\"docker-entrypoint.sh\"]\nENTRYPOINT [\"python\", \"-m\", \"flask\"]\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]\n```" },
171
- "insertText": "ENTRYPOINT [\"${1:executable}\"]",
526
+ "label": "COPY --chmod",
527
+ "kind": 15,
528
+ "detail": "COPY with chmod",
529
+ "documentation": {
530
+ "value": "Copy files and set permissions (BuildKit)."
531
+ },
532
+ "insertText": "COPY --chmod=${1:755} ${2:src} ${3:dest}",
172
533
  "insertTextRules": 4,
173
- "sortText": "09_ENTRYPOINT"
534
+ "sortText": "05_copy_chmod"
174
535
  },
175
536
  {
176
- "label": "VOLUME",
177
- "kind": 14,
178
- "detail": "Create a mount point",
179
- "documentation": { "value": "Create a mount point for externally mounted volumes or other containers.\n\n```dockerfile\nVOLUME /data\nVOLUME [\"/var/log\", \"/data\"]\n```" },
537
+ "label": "COPY --from",
538
+ "kind": 15,
539
+ "detail": "COPY from stage",
540
+ "documentation": {
541
+ "value": "Copy files from a named build stage (multi-stage)."
542
+ },
543
+ "insertText": "COPY --from=${1:builder} ${2:/app/build} ${3:/usr/share/nginx/html}",
544
+ "insertTextRules": 4,
545
+ "sortText": "05_copy_from"
546
+ },
547
+ {
548
+ "label": "COPY --link",
549
+ "kind": 15,
550
+ "detail": "COPY with link",
551
+ "documentation": {
552
+ "value": "Copy files using link mode for better cache efficiency."
553
+ },
554
+ "insertText": "COPY --link ${1:src} ${2:dest}",
555
+ "insertTextRules": 4,
556
+ "sortText": "05_copy_link"
557
+ },
558
+ {
559
+ "label": "COPY package*.json",
560
+ "kind": 15,
561
+ "detail": "COPY package files first",
562
+ "documentation": {
563
+ "value": "Copy only package files first for better layer caching."
564
+ },
565
+ "insertText": "COPY package*.json ${1:./}\nRUN npm ci\nCOPY ${2:.} ${3:./}",
566
+ "insertTextRules": 4,
567
+ "sortText": "05_copy_package_cache"
568
+ },
569
+ {
570
+ "label": "ADD basic",
571
+ "kind": 15,
572
+ "detail": "ADD files",
573
+ "documentation": {
574
+ "value": "Add files from build context (or URL/tar) into the image."
575
+ },
576
+ "insertText": "ADD ${1:src} ${2:dest}",
577
+ "insertTextRules": 4,
578
+ "sortText": "06_add_basic"
579
+ },
580
+ {
581
+ "label": "ADD URL",
582
+ "kind": 15,
583
+ "detail": "ADD from URL",
584
+ "documentation": {
585
+ "value": "Download a file from a URL into the image."
586
+ },
587
+ "insertText": "ADD ${1:https://example.com/file.tar.gz} ${2:/tmp/}",
588
+ "insertTextRules": 4,
589
+ "sortText": "06_add_url"
590
+ },
591
+ {
592
+ "label": "ADD tar",
593
+ "kind": 15,
594
+ "detail": "ADD tar auto-extract",
595
+ "documentation": {
596
+ "value": "Add and auto-extract a tar archive."
597
+ },
598
+ "insertText": "ADD ${1:archive.tar.gz} ${2:/opt/}",
599
+ "insertTextRules": 4,
600
+ "sortText": "06_add_tar"
601
+ },
602
+ {
603
+ "label": "ADD --checksum",
604
+ "kind": 15,
605
+ "detail": "ADD with checksum",
606
+ "documentation": {
607
+ "value": "Add file with SHA256 checksum verification (BuildKit)."
608
+ },
609
+ "insertText": "ADD --checksum=sha256:${1:hash} ${2:https://example.com/file} ${3:/dest}",
610
+ "insertTextRules": 4,
611
+ "sortText": "06_add_checksum"
612
+ },
613
+ {
614
+ "label": "ENV single",
615
+ "kind": 15,
616
+ "detail": "ENV single variable",
617
+ "documentation": {
618
+ "value": "Set a single environment variable."
619
+ },
620
+ "insertText": "ENV ${1:KEY}=${2:value}",
621
+ "insertTextRules": 4,
622
+ "sortText": "07_env_single"
623
+ },
624
+ {
625
+ "label": "ENV multiple",
626
+ "kind": 15,
627
+ "detail": "ENV multiple variables",
628
+ "documentation": {
629
+ "value": "Set multiple environment variables."
630
+ },
631
+ "insertText": "ENV ${1:KEY1}=${2:value1} \\\n ${3:KEY2}=${4:value2}",
632
+ "insertTextRules": 4,
633
+ "sortText": "07_env_multiple"
634
+ },
635
+ {
636
+ "label": "ENV PATH",
637
+ "kind": 15,
638
+ "detail": "ENV prepend PATH",
639
+ "documentation": {
640
+ "value": "Prepend a directory to PATH."
641
+ },
642
+ "insertText": "ENV PATH=\"${1:/app/bin}:$$PATH\"",
643
+ "insertTextRules": 4,
644
+ "sortText": "07_env_path"
645
+ },
646
+ {
647
+ "label": "ENV NODE_ENV",
648
+ "kind": 15,
649
+ "detail": "ENV NODE_ENV production",
650
+ "documentation": {
651
+ "value": "Set Node.js production environment."
652
+ },
653
+ "insertText": "ENV NODE_ENV=production",
654
+ "insertTextRules": 4,
655
+ "sortText": "07_env_node"
656
+ },
657
+ {
658
+ "label": "ENV PYTHONDONTWRITEBYTECODE",
659
+ "kind": 15,
660
+ "detail": "ENV Python optimizations",
661
+ "documentation": {
662
+ "value": "Common Python env vars for Docker."
663
+ },
664
+ "insertText": "ENV PYTHONDONTWRITEBYTECODE=1 \\\n PYTHONUNBUFFERED=1",
665
+ "insertTextRules": 4,
666
+ "sortText": "07_env_python"
667
+ },
668
+ {
669
+ "label": "ARG basic",
670
+ "kind": 15,
671
+ "detail": "ARG variable",
672
+ "documentation": {
673
+ "value": "Define a build-time argument."
674
+ },
675
+ "insertText": "ARG ${1:NAME}",
676
+ "insertTextRules": 4,
677
+ "sortText": "08_arg_basic"
678
+ },
679
+ {
680
+ "label": "ARG with default",
681
+ "kind": 15,
682
+ "detail": "ARG with default value",
683
+ "documentation": {
684
+ "value": "Define a build arg with a default value."
685
+ },
686
+ "insertText": "ARG ${1:NAME}=${2:default}",
687
+ "insertTextRules": 4,
688
+ "sortText": "08_arg_default"
689
+ },
690
+ {
691
+ "label": "ARG before FROM",
692
+ "kind": 15,
693
+ "detail": "ARG before FROM",
694
+ "documentation": {
695
+ "value": "Define ARG before FROM for use in FROM instruction."
696
+ },
697
+ "insertText": "ARG ${1:VERSION}=${2:latest}\nFROM ${3:node}:${1:VERSION}",
698
+ "insertTextRules": 4,
699
+ "sortText": "08_arg_before_from"
700
+ },
701
+ {
702
+ "label": "EXPOSE port",
703
+ "kind": 15,
704
+ "detail": "EXPOSE single port",
705
+ "documentation": {
706
+ "value": "Expose a single port."
707
+ },
708
+ "insertText": "EXPOSE ${1:8080}",
709
+ "insertTextRules": 4,
710
+ "sortText": "09_expose_single"
711
+ },
712
+ {
713
+ "label": "EXPOSE multiple",
714
+ "kind": 15,
715
+ "detail": "EXPOSE multiple ports",
716
+ "documentation": {
717
+ "value": "Expose multiple ports."
718
+ },
719
+ "insertText": "EXPOSE ${1:80} ${2:443}",
720
+ "insertTextRules": 4,
721
+ "sortText": "09_expose_multiple"
722
+ },
723
+ {
724
+ "label": "EXPOSE UDP",
725
+ "kind": 15,
726
+ "detail": "EXPOSE UDP port",
727
+ "documentation": {
728
+ "value": "Expose a UDP port."
729
+ },
730
+ "insertText": "EXPOSE ${1:53}/udp",
731
+ "insertTextRules": 4,
732
+ "sortText": "09_expose_udp"
733
+ },
734
+ {
735
+ "label": "VOLUME path",
736
+ "kind": 15,
737
+ "detail": "VOLUME mount point",
738
+ "documentation": {
739
+ "value": "Create a mount point."
740
+ },
180
741
  "insertText": "VOLUME ${1:/data}",
181
742
  "insertTextRules": 4,
182
- "sortText": "10_VOLUME"
743
+ "sortText": "10_volume"
183
744
  },
184
745
  {
185
- "label": "USER",
186
- "kind": 14,
187
- "detail": "Set the user for subsequent instructions",
188
- "documentation": { "value": "Set the user (and optionally group) for RUN, CMD, and ENTRYPOINT instructions that follow.\n\n```dockerfile\nRUN groupadd -r appuser && useradd -r -g appuser appuser\nUSER appuser\nUSER 1000:1000\n```" },
189
- "insertText": "USER ${1:user}",
746
+ "label": "VOLUME JSON",
747
+ "kind": 15,
748
+ "detail": "VOLUME multiple",
749
+ "documentation": {
750
+ "value": "Create multiple mount points."
751
+ },
752
+ "insertText": "VOLUME [\"${1:/data}\", \"${2:/logs}\"]",
190
753
  "insertTextRules": 4,
191
- "sortText": "11_USER"
754
+ "sortText": "10_volume_json"
192
755
  },
193
756
  {
194
- "label": "WORKDIR",
195
- "kind": 14,
196
- "detail": "Set the working directory",
197
- "documentation": { "value": "Set the working directory for RUN, CMD, ENTRYPOINT, COPY, and ADD instructions that follow.\n\n```dockerfile\nWORKDIR /app\nWORKDIR /usr/src/app\n```" },
757
+ "label": "USER name",
758
+ "kind": 15,
759
+ "detail": "USER set user",
760
+ "documentation": {
761
+ "value": "Switch to a non-root user."
762
+ },
763
+ "insertText": "USER ${1:appuser}",
764
+ "insertTextRules": 4,
765
+ "sortText": "11_user"
766
+ },
767
+ {
768
+ "label": "USER uid:gid",
769
+ "kind": 15,
770
+ "detail": "USER with UID:GID",
771
+ "documentation": {
772
+ "value": "Switch to a specific UID:GID."
773
+ },
774
+ "insertText": "USER ${1:1001}:${2:1001}",
775
+ "insertTextRules": 4,
776
+ "sortText": "11_user_uid"
777
+ },
778
+ {
779
+ "label": "WORKDIR path",
780
+ "kind": 15,
781
+ "detail": "WORKDIR set directory",
782
+ "documentation": {
783
+ "value": "Set the working directory."
784
+ },
198
785
  "insertText": "WORKDIR ${1:/app}",
199
786
  "insertTextRules": 4,
200
- "sortText": "12_WORKDIR"
787
+ "sortText": "12_workdir"
201
788
  },
202
789
  {
203
- "label": "ARG",
204
- "kind": 14,
205
- "detail": "Define a build-time variable",
206
- "documentation": { "value": "Define a variable that users can pass at build time with `--build-arg`.\n\n```dockerfile\nARG NODE_VERSION=20\nARG APP_VERSION\nFROM node:${NODE_VERSION}-alpine\n```\n\nBuild: `docker build --build-arg NODE_VERSION=18 .`" },
207
- "insertText": "ARG ${1:name}=${2:default}",
790
+ "label": "LABEL single",
791
+ "kind": 15,
792
+ "detail": "LABEL single",
793
+ "documentation": {
794
+ "value": "Add a single metadata label."
795
+ },
796
+ "insertText": "LABEL ${1:key}=\"${2:value}\"",
208
797
  "insertTextRules": 4,
209
- "sortText": "13_ARG"
798
+ "sortText": "13_label_single"
210
799
  },
211
800
  {
212
- "label": "ONBUILD",
213
- "kind": 14,
214
- "detail": "Add trigger instruction for downstream builds",
215
- "documentation": { "value": "Add a trigger instruction that executes when the image is used as a base for another build.\n\n```dockerfile\nONBUILD COPY . /app/src\nONBUILD RUN npm install\n```" },
216
- "insertText": "ONBUILD ${1:INSTRUCTION}",
801
+ "label": "LABEL multiple",
802
+ "kind": 15,
803
+ "detail": "LABEL multiple",
804
+ "documentation": {
805
+ "value": "Add multiple metadata labels."
806
+ },
807
+ "insertText": "LABEL ${1:maintainer}=\"${2:name}\" \\\n ${3:version}=\"${4:1.0}\"",
808
+ "insertTextRules": 4,
809
+ "sortText": "13_label_multiple"
810
+ },
811
+ {
812
+ "label": "LABEL OCI",
813
+ "kind": 15,
814
+ "detail": "LABEL OCI annotations",
815
+ "documentation": {
816
+ "value": "OCI image spec annotation labels."
817
+ },
818
+ "insertText": "LABEL org.opencontainers.image.title=\"${1:title}\" \\\n org.opencontainers.image.description=\"${2:description}\" \\\n org.opencontainers.image.version=\"${3:1.0.0}\" \\\n org.opencontainers.image.authors=\"${4:author}\" \\\n org.opencontainers.image.source=\"${5:https://github.com/user/repo}\" \\\n org.opencontainers.image.licenses=\"${6:MIT}\"",
819
+ "insertTextRules": 4,
820
+ "sortText": "13_label_oci"
821
+ },
822
+ {
823
+ "label": "HEALTHCHECK CMD",
824
+ "kind": 15,
825
+ "detail": "HEALTHCHECK CMD",
826
+ "documentation": {
827
+ "value": "Health check with HTTP endpoint."
828
+ },
829
+ "insertText": "HEALTHCHECK --interval=${1:30s} --timeout=${2:10s} --start-period=${3:5s} --retries=${4:3} \\\n CMD ${5:curl -f http://localhost:${6:8080}/health || exit 1}",
830
+ "insertTextRules": 4,
831
+ "sortText": "14_healthcheck_cmd"
832
+ },
833
+ {
834
+ "label": "HEALTHCHECK wget",
835
+ "kind": 15,
836
+ "detail": "HEALTHCHECK with wget",
837
+ "documentation": {
838
+ "value": "Health check using wget (for alpine/minimal images)."
839
+ },
840
+ "insertText": "HEALTHCHECK --interval=${1:30s} --timeout=${2:10s} --retries=${3:3} \\\n CMD wget --quiet --tries=1 --spider http://localhost:${4:8080}/health || exit 1",
841
+ "insertTextRules": 4,
842
+ "sortText": "14_healthcheck_wget"
843
+ },
844
+ {
845
+ "label": "HEALTHCHECK NONE",
846
+ "kind": 15,
847
+ "detail": "HEALTHCHECK NONE",
848
+ "documentation": {
849
+ "value": "Disable health check inherited from base image."
850
+ },
851
+ "insertText": "HEALTHCHECK NONE",
852
+ "insertTextRules": 4,
853
+ "sortText": "14_healthcheck_none"
854
+ },
855
+ {
856
+ "label": "SHELL bash",
857
+ "kind": 15,
858
+ "detail": "SHELL set to bash",
859
+ "documentation": {
860
+ "value": "Set default shell to bash."
861
+ },
862
+ "insertText": "SHELL [\"/bin/bash\", \"-c\"]",
863
+ "insertTextRules": 4,
864
+ "sortText": "15_shell_bash"
865
+ },
866
+ {
867
+ "label": "SHELL powershell",
868
+ "kind": 15,
869
+ "detail": "SHELL set to PowerShell",
870
+ "documentation": {
871
+ "value": "Set default shell to PowerShell (Windows)."
872
+ },
873
+ "insertText": "SHELL [\"powershell\", \"-Command\"]",
217
874
  "insertTextRules": 4,
218
- "sortText": "14_ONBUILD"
875
+ "sortText": "15_shell_powershell"
219
876
  },
220
877
  {
221
878
  "label": "STOPSIGNAL",
222
- "kind": 14,
223
- "detail": "Set the system call signal for stopping the container",
224
- "documentation": { "value": "Set the signal that will be sent to the container to stop it.\n\n```dockerfile\nSTOPSIGNAL SIGTERM\nSTOPSIGNAL SIGQUIT\nSTOPSIGNAL 9\n```" },
225
- "insertText": "STOPSIGNAL ${1|SIGTERM,SIGQUIT,SIGKILL,SIGINT|}",
879
+ "kind": 15,
880
+ "detail": "STOPSIGNAL",
881
+ "documentation": {
882
+ "value": "Set stop signal."
883
+ },
884
+ "insertText": "STOPSIGNAL ${1|SIGTERM,SIGQUIT,SIGINT,SIGKILL|}",
226
885
  "insertTextRules": 4,
227
- "sortText": "15_STOPSIGNAL"
886
+ "sortText": "16_stopsignal"
228
887
  },
229
888
  {
230
- "label": "HEALTHCHECK",
231
- "kind": 14,
232
- "detail": "Define container health check",
233
- "documentation": { "value": "Tell Docker how to test the container to check that it is still working.\n\n```dockerfile\nHEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\\n CMD curl -f http://localhost:8080/health || exit 1\n\nHEALTHCHECK NONE\n```" },
234
- "insertText": "HEALTHCHECK --interval=${1:30s} --timeout=${2:10s} --start-period=${3:5s} --retries=${4:3} \\\n CMD ${5:curl -f http://localhost:8080/health || exit 1}",
889
+ "label": "ONBUILD",
890
+ "kind": 15,
891
+ "detail": "ONBUILD trigger",
892
+ "documentation": {
893
+ "value": "Add instruction to execute when image is used as base."
894
+ },
895
+ "insertText": "ONBUILD ${1:RUN echo \"triggered\"}",
235
896
  "insertTextRules": 4,
236
- "sortText": "16_HEALTHCHECK"
897
+ "sortText": "17_onbuild"
237
898
  },
238
899
  {
239
- "label": "SHELL",
240
- "kind": 14,
241
- "detail": "Override the default shell",
242
- "documentation": { "value": "Override the default shell used for the shell form of commands.\n\n```dockerfile\nSHELL [\"/bin/bash\", \"-c\"]\nSHELL [\"powershell\", \"-command\"]\n```" },
243
- "insertText": "SHELL [\"${1:/bin/bash}\", \"${2:-c}\"]",
900
+ "label": "# syntax=",
901
+ "kind": 15,
902
+ "detail": "syntax parser directive",
903
+ "documentation": {
904
+ "value": "Set BuildKit frontend syntax (must be first line)."
905
+ },
906
+ "insertText": "# syntax=docker/dockerfile:${1|1,1.4,1.5,1.6,1.7,labs|}",
244
907
  "insertTextRules": 4,
245
- "sortText": "17_SHELL"
908
+ "sortText": "00_syntax"
246
909
  },
247
910
  {
248
- "label": "FROM node",
249
- "kind": 27,
250
- "detail": "Node.js base image",
251
- "documentation": { "value": "Use the official Node.js image as the base.\n\n```dockerfile\nFROM node:20-alpine\nFROM node:18-slim\nFROM node:20-bookworm\n```\n\nVariants: `alpine` (minimal ~50MB), `slim` (Debian minimal), `bookworm`/`bullseye` (full Debian)." },
252
- "insertText": "FROM node:${1|20-alpine,20-slim,20-bookworm,18-alpine,18-slim,22-alpine|}",
911
+ "label": "# escape=",
912
+ "kind": 15,
913
+ "detail": "escape parser directive",
914
+ "documentation": {
915
+ "value": "Change the escape character (must be before any instruction)."
916
+ },
917
+ "insertText": "# escape=${1|\\\\,`|}",
253
918
  "insertTextRules": 4,
254
- "sortText": "20_node"
919
+ "sortText": "00_escape"
255
920
  },
256
921
  {
257
- "label": "FROM python",
258
- "kind": 27,
259
- "detail": "Python base image",
260
- "documentation": { "value": "Use the official Python image as the base.\n\n```dockerfile\nFROM python:3.12-slim\nFROM python:3.11-alpine\nFROM python:3.12-bookworm\n```\n\nVariants: `slim` (recommended for most apps), `alpine` (smallest), `bookworm` (full Debian)." },
261
- "insertText": "FROM python:${1|3.12-slim,3.12-alpine,3.12-bookworm,3.11-slim,3.11-alpine|}",
922
+ "label": "Dockerfile: Node.js multi-stage",
923
+ "kind": 15,
924
+ "detail": "Node.js multi-stage Dockerfile",
925
+ "documentation": {
926
+ "value": "Production-ready multi-stage Dockerfile for a Node.js application."
927
+ },
928
+ "insertText": "# syntax=docker/dockerfile:1\nFROM node:${1:20}-alpine AS deps\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci --only=production\n\nFROM node:${1:20}-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM node:${1:20}-alpine\nWORKDIR /app\nENV NODE_ENV=production\nRUN addgroup -S appuser && adduser -S appuser -G appuser\nCOPY --from=deps /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY package*.json ./\nUSER appuser\nEXPOSE ${2:3000}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD wget --quiet --tries=1 --spider http://localhost:${2:3000}/health || exit 1\nCMD [\"node\", \"dist/index.js\"]",
262
929
  "insertTextRules": 4,
263
- "sortText": "20_python"
930
+ "sortText": "20_tmpl_node"
264
931
  },
265
932
  {
266
- "label": "FROM golang",
267
- "kind": 27,
268
- "detail": "Go base image",
269
- "documentation": { "value": "Use the official Go image as the base.\n\n```dockerfile\nFROM golang:1.22-alpine\nFROM golang:1.22-bookworm\n```\n\nGo binaries are statically linked by default — ideal for multi-stage builds with `FROM scratch`." },
270
- "insertText": "FROM golang:${1|1.22-alpine,1.22-bookworm,1.21-alpine,1.21-bookworm|}",
933
+ "label": "Dockerfile: Python multi-stage",
934
+ "kind": 15,
935
+ "detail": "Python multi-stage Dockerfile",
936
+ "documentation": {
937
+ "value": "Production-ready multi-stage Dockerfile for a Python application."
938
+ },
939
+ "insertText": "# syntax=docker/dockerfile:1\nFROM python:${1:3.12}-slim AS builder\nWORKDIR /app\nENV PYTHONDONTWRITEBYTECODE=1 \\\n PYTHONUNBUFFERED=1\nCOPY requirements.txt .\nRUN pip install --no-cache-dir --prefix=/install -r requirements.txt\n\nFROM python:${1:3.12}-slim\nWORKDIR /app\nENV PYTHONDONTWRITEBYTECODE=1 \\\n PYTHONUNBUFFERED=1\nRUN groupadd -r appuser && useradd -r -g appuser appuser\nCOPY --from=builder /install /usr/local\nCOPY . .\nUSER appuser\nEXPOSE ${2:8000}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD python -c \"import urllib.request; urllib.request.urlopen('http://localhost:${2:8000}/health')\" || exit 1\nCMD [\"python\", \"-m\", \"${3:app}\"]",
271
940
  "insertTextRules": 4,
272
- "sortText": "20_golang"
941
+ "sortText": "20_tmpl_python"
273
942
  },
274
943
  {
275
- "label": "FROM rust",
276
- "kind": 27,
277
- "detail": "Rust base image",
278
- "documentation": { "value": "Use the official Rust image as the base.\n\n```dockerfile\nFROM rust:1.77-slim\nFROM rust:1.77-alpine\nFROM rust:1.77-bookworm\n```\n\nUse multi-stage builds to create minimal final images." },
279
- "insertText": "FROM rust:${1|1.77-slim,1.77-alpine,1.77-bookworm|}",
944
+ "label": "Dockerfile: Go multi-stage",
945
+ "kind": 15,
946
+ "detail": "Go multi-stage Dockerfile",
947
+ "documentation": {
948
+ "value": "Production-ready multi-stage Dockerfile for a Go application."
949
+ },
950
+ "insertText": "# syntax=docker/dockerfile:1\nFROM golang:${1:1.22}-alpine AS builder\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags=\"-s -w\" -o /app/server ./cmd/${2:server}\n\nFROM gcr.io/distroless/static-debian12\nCOPY --from=builder /app/server /server\nEXPOSE ${3:8080}\nUSER nonroot:nonroot\nENTRYPOINT [\"/server\"]",
280
951
  "insertTextRules": 4,
281
- "sortText": "20_rust"
952
+ "sortText": "20_tmpl_go"
282
953
  },
283
954
  {
284
- "label": "FROM ubuntu",
285
- "kind": 27,
286
- "detail": "Ubuntu base image",
287
- "documentation": { "value": "Use the official Ubuntu image as the base.\n\n```dockerfile\nFROM ubuntu:22.04\nFROM ubuntu:24.04\nFROM ubuntu:20.04\n```" },
288
- "insertText": "FROM ubuntu:${1|24.04,22.04,20.04|}",
955
+ "label": "Dockerfile: Java Maven multi-stage",
956
+ "kind": 15,
957
+ "detail": "Java/Maven multi-stage Dockerfile",
958
+ "documentation": {
959
+ "value": "Production-ready multi-stage Dockerfile for a Java application built with Maven."
960
+ },
961
+ "insertText": "# syntax=docker/dockerfile:1\nFROM maven:${1:3.9}-eclipse-temurin-${2:21} AS builder\nWORKDIR /app\nCOPY pom.xml .\nRUN mvn dependency:go-offline -B\nCOPY src ./src\nRUN mvn package -DskipTests -B\n\nFROM eclipse-temurin:${2:21}-jre-alpine\nWORKDIR /app\nRUN addgroup -S appuser && adduser -S appuser -G appuser\nCOPY --from=builder /app/target/*.jar app.jar\nUSER appuser\nEXPOSE ${3:8080}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD wget --quiet --tries=1 --spider http://localhost:${3:8080}/actuator/health || exit 1\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]",
289
962
  "insertTextRules": 4,
290
- "sortText": "20_ubuntu"
963
+ "sortText": "20_tmpl_java"
291
964
  },
292
965
  {
293
- "label": "FROM alpine",
294
- "kind": 27,
295
- "detail": "Alpine Linux base image",
296
- "documentation": { "value": "Use Alpine Linux (~5MB) for minimal images.\n\n```dockerfile\nFROM alpine:3.19\nFROM alpine:3.18\n```\n\nUses `musl` libc and `apk` package manager. May have compatibility issues with some C libraries." },
297
- "insertText": "FROM alpine:${1|3.19,3.18,3.17|}",
966
+ "label": "Dockerfile: Rust multi-stage",
967
+ "kind": 15,
968
+ "detail": "Rust multi-stage Dockerfile",
969
+ "documentation": {
970
+ "value": "Production-ready multi-stage Dockerfile for a Rust application."
971
+ },
972
+ "insertText": "# syntax=docker/dockerfile:1\nFROM rust:${1:1.77}-slim AS builder\nWORKDIR /app\nCOPY Cargo.toml Cargo.lock ./\nRUN mkdir src && echo \"fn main() {}\" > src/main.rs && cargo build --release && rm -rf src\nCOPY src ./src\nRUN cargo build --release\n\nFROM debian:${2:bookworm}-slim\nRUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \\\n && rm -rf /var/lib/apt/lists/*\nRUN groupadd -r appuser && useradd -r -g appuser appuser\nCOPY --from=builder /app/target/release/${3:myapp} /usr/local/bin/\nUSER appuser\nEXPOSE ${4:8080}\nENTRYPOINT [\"${3:myapp}\"]",
298
973
  "insertTextRules": 4,
299
- "sortText": "20_alpine"
974
+ "sortText": "20_tmpl_rust"
300
975
  },
301
976
  {
302
- "label": "FROM debian",
303
- "kind": 27,
304
- "detail": "Debian base image",
305
- "documentation": { "value": "Use the official Debian image as the base.\n\n```dockerfile\nFROM debian:bookworm-slim\nFROM debian:bullseye-slim\n```\n\n`-slim` variants are much smaller and sufficient for most applications." },
306
- "insertText": "FROM debian:${1|bookworm-slim,bullseye-slim,bookworm,bullseye|}",
977
+ "label": "Dockerfile: .NET multi-stage",
978
+ "kind": 15,
979
+ "detail": ".NET multi-stage Dockerfile",
980
+ "documentation": {
981
+ "value": "Production-ready multi-stage Dockerfile for a .NET application."
982
+ },
983
+ "insertText": "# syntax=docker/dockerfile:1\nFROM mcr.microsoft.com/dotnet/sdk:${1:8.0} AS builder\nWORKDIR /app\nCOPY *.csproj .\nRUN dotnet restore\nCOPY . .\nRUN dotnet publish -c Release -o /out --no-restore\n\nFROM mcr.microsoft.com/dotnet/aspnet:${1:8.0}\nWORKDIR /app\nRUN groupadd -r appuser && useradd -r -g appuser appuser\nCOPY --from=builder /out .\nUSER appuser\nEXPOSE ${2:8080}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD curl -f http://localhost:${2:8080}/health || exit 1\nENTRYPOINT [\"dotnet\", \"${3:MyApp}.dll\"]",
307
984
  "insertTextRules": 4,
308
- "sortText": "20_debian"
985
+ "sortText": "20_tmpl_dotnet"
309
986
  },
310
987
  {
311
- "label": "FROM nginx",
312
- "kind": 27,
313
- "detail": "Nginx web server base image",
314
- "documentation": { "value": "Use the official Nginx image.\n\n```dockerfile\nFROM nginx:alpine\nFROM nginx:1.25-alpine\n```\n\nDefault serves `/usr/share/nginx/html`. Config at `/etc/nginx/nginx.conf`." },
315
- "insertText": "FROM nginx:${1|alpine,1.25-alpine,1.25-bookworm,stable-alpine|}",
988
+ "label": "Dockerfile: Nginx static site",
989
+ "kind": 15,
990
+ "detail": "Nginx static site Dockerfile",
991
+ "documentation": {
992
+ "value": "Serve static files with Nginx using a multi-stage build."
993
+ },
994
+ "insertText": "# syntax=docker/dockerfile:1\nFROM node:${1:20}-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM nginx:${2:alpine}\nCOPY --from=builder /app/${3:dist} /usr/share/nginx/html\nCOPY ${4:nginx.conf} /etc/nginx/conf.d/default.conf\nEXPOSE 80\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD curl -f http://localhost/ || exit 1\nCMD [\"nginx\", \"-g\", \"daemon off;\"]",
316
995
  "insertTextRules": 4,
317
- "sortText": "20_nginx"
996
+ "sortText": "20_tmpl_nginx"
318
997
  },
319
998
  {
320
- "label": "FROM redis",
321
- "kind": 27,
322
- "detail": "Redis base image",
323
- "documentation": { "value": "Use the official Redis image.\n\n```dockerfile\nFROM redis:7-alpine\nFROM redis:7-bookworm\n```\n\nData directory: `/data`. Default port: 6379." },
324
- "insertText": "FROM redis:${1|7-alpine,7-bookworm,6-alpine|}",
999
+ "label": "Dockerfile: PHP-FPM",
1000
+ "kind": 15,
1001
+ "detail": "PHP-FPM Dockerfile",
1002
+ "documentation": {
1003
+ "value": "PHP-FPM application Dockerfile with Composer."
1004
+ },
1005
+ "insertText": "# syntax=docker/dockerfile:1\nFROM composer:${1:2} AS vendor\nWORKDIR /app\nCOPY composer.json composer.lock ./\nRUN composer install --no-dev --no-scripts --no-autoloader\nCOPY . .\nRUN composer dump-autoload --optimize\n\nFROM php:${2:8.3}-fpm-alpine\nWORKDIR /var/www/html\nRUN docker-php-ext-install pdo pdo_mysql opcache\nCOPY --from=vendor /app .\nRUN chown -R www-data:www-data /var/www/html\nUSER www-data\nEXPOSE 9000\nCMD [\"php-fpm\"]",
325
1006
  "insertTextRules": 4,
326
- "sortText": "20_redis"
1007
+ "sortText": "20_tmpl_php"
327
1008
  },
328
1009
  {
329
- "label": "FROM postgres",
330
- "kind": 27,
331
- "detail": "PostgreSQL base image",
332
- "documentation": { "value": "Use the official PostgreSQL image.\n\n```dockerfile\nFROM postgres:16-alpine\nFROM postgres:15-bookworm\n```\n\nSet `POSTGRES_PASSWORD`, `POSTGRES_USER`, `POSTGRES_DB` environment variables. Init scripts in `/docker-entrypoint-initdb.d/`." },
333
- "insertText": "FROM postgres:${1|16-alpine,16-bookworm,15-alpine,15-bookworm|}",
1010
+ "label": "Dockerfile: Ruby/Rails",
1011
+ "kind": 15,
1012
+ "detail": "Ruby/Rails Dockerfile",
1013
+ "documentation": {
1014
+ "value": "Production-ready Dockerfile for a Ruby on Rails application."
1015
+ },
1016
+ "insertText": "# syntax=docker/dockerfile:1\nFROM ruby:${1:3.3}-slim AS builder\nWORKDIR /app\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n build-essential libpq-dev \\\n && rm -rf /var/lib/apt/lists/*\nCOPY Gemfile Gemfile.lock ./\nRUN bundle config set --local deployment true \\\n && bundle config set --local without \"development test\" \\\n && bundle install\n\nFROM ruby:${1:3.3}-slim\nWORKDIR /app\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n libpq5 \\\n && rm -rf /var/lib/apt/lists/*\nRUN groupadd -r rails && useradd -r -g rails rails\nCOPY --from=builder /app/vendor/bundle ./vendor/bundle\nCOPY . .\nRUN bundle config set --local path vendor/bundle\nUSER rails\nEXPOSE ${2:3000}\nCMD [\"bundle\", \"exec\", \"rails\", \"server\", \"-b\", \"0.0.0.0\"]",
334
1017
  "insertTextRules": 4,
335
- "sortText": "20_postgres"
1018
+ "sortText": "20_tmpl_ruby"
336
1019
  },
337
1020
  {
338
- "label": "FROM mysql",
339
- "kind": 27,
340
- "detail": "MySQL base image",
341
- "documentation": { "value": "Use the official MySQL image.\n\n```dockerfile\nFROM mysql:8.0\nFROM mysql:8.3\n```\n\nSet `MYSQL_ROOT_PASSWORD`, `MYSQL_DATABASE`, `MYSQL_USER`, `MYSQL_PASSWORD`. Init scripts in `/docker-entrypoint-initdb.d/`." },
342
- "insertText": "FROM mysql:${1|8.3,8.0|}",
1021
+ "label": "Non-root user setup",
1022
+ "kind": 15,
1023
+ "detail": "Non-root user pattern",
1024
+ "documentation": {
1025
+ "value": "Best practice: create and switch to a non-root user."
1026
+ },
1027
+ "insertText": "RUN groupadd -r ${1:appuser} && useradd -r -g ${1:appuser} -d /home/${1:appuser} -s /sbin/nologin ${1:appuser} \\\n && mkdir -p /home/${1:appuser} && chown -R ${1:appuser}:${1:appuser} /home/${1:appuser}\nUSER ${1:appuser}",
343
1028
  "insertTextRules": 4,
344
- "sortText": "20_mysql"
1029
+ "sortText": "18_bp_nonroot"
345
1030
  },
346
1031
  {
347
- "label": "apt-get install pattern",
1032
+ "label": "apt-get best practice",
348
1033
  "kind": 15,
349
- "detail": "Best practice apt-get install with cleanup",
350
- "documentation": { "value": "Install packages with apt-get following Docker best practices: combine update+install, use `--no-install-recommends`, and clean up in a single RUN layer.\n\n```dockerfile\nRUN apt-get update && apt-get install -y --no-install-recommends \\\n curl \\\n ca-certificates \\\n && rm -rf /var/lib/apt/lists/*\n```" },
351
- "insertText": "RUN apt-get update && apt-get install -y --no-install-recommends \\\n ${1:package} \\\n && rm -rf /var/lib/apt/lists/*",
1034
+ "detail": "apt-get best practice layer",
1035
+ "documentation": {
1036
+ "value": "Install packages and clean up in a single layer."
1037
+ },
1038
+ "insertText": "RUN apt-get update \\\n && apt-get install -y --no-install-recommends \\\n ${1:curl} \\\n ${2:ca-certificates} \\\n && apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \\\n && rm -rf /var/lib/apt/lists/*",
352
1039
  "insertTextRules": 4,
353
- "sortText": "30_apt_install"
1040
+ "sortText": "18_bp_apt"
354
1041
  },
355
1042
  {
356
- "label": "pip install pattern",
1043
+ "label": "pip best practice",
357
1044
  "kind": 15,
358
- "detail": "Best practice pip install",
359
- "documentation": { "value": "Install Python packages with pip following best practices: use `--no-cache-dir` to keep image small.\n\n```dockerfile\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\n```" },
360
- "insertText": "COPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt",
1045
+ "detail": "pip install best practice",
1046
+ "documentation": {
1047
+ "value": "Install Python packages without cache."
1048
+ },
1049
+ "insertText": "COPY requirements.txt .\nRUN pip install --no-cache-dir --upgrade pip \\\n && pip install --no-cache-dir -r requirements.txt",
361
1050
  "insertTextRules": 4,
362
- "sortText": "30_pip_install"
1051
+ "sortText": "18_bp_pip"
363
1052
  },
364
1053
  {
365
- "label": "npm install pattern",
1054
+ "label": "npm ci pattern",
366
1055
  "kind": 15,
367
- "detail": "Best practice npm install with layer caching",
368
- "documentation": { "value": "Copy package files first to leverage Docker layer caching. Dependencies are only reinstalled when package files change.\n\n```dockerfile\nCOPY package.json package-lock.json ./\nRUN npm ci --only=production\nCOPY . .\n```" },
369
- "insertText": "COPY package.json package-lock.json ./\nRUN npm ci ${1:--only=production}\nCOPY . .",
1056
+ "detail": "npm ci production pattern",
1057
+ "documentation": {
1058
+ "value": "Install production Node.js dependencies."
1059
+ },
1060
+ "insertText": "COPY package.json package-lock.json ./\nRUN npm ci --only=production \\\n && npm cache clean --force",
370
1061
  "insertTextRules": 4,
371
- "sortText": "30_npm_install"
1062
+ "sortText": "18_bp_npm"
372
1063
  },
373
1064
  {
374
- "label": "COPY package.json first",
1065
+ "label": "Multi-stage build pattern",
375
1066
  "kind": 15,
376
- "detail": "Layer caching pattern for package managers",
377
- "documentation": { "value": "Copy dependency manifests before the rest of the code to leverage Docker's build cache. This way, dependencies are only reinstalled when the manifest changes.\n\n```dockerfile\n# Dependencies are cached unless package.json changes\nCOPY package.json package-lock.json ./\nRUN npm ci\n\n# Application code changes don't invalidate deps cache\nCOPY . .\n```" },
378
- "insertText": "# Install dependencies (cached unless manifest changes)\nCOPY ${1:package.json} ${2:package-lock.json} ./\nRUN ${3:npm ci}\n\n# Copy application source\nCOPY . .",
1067
+ "detail": "Multi-stage build skeleton",
1068
+ "documentation": {
1069
+ "value": "Basic multi-stage build skeleton."
1070
+ },
1071
+ "insertText": "FROM ${1:node:20-alpine} AS builder\nWORKDIR /app\nCOPY . .\nRUN ${2:npm ci && npm run build}\n\nFROM ${3:node:20-alpine}\nWORKDIR /app\nCOPY --from=builder /app/${4:dist} ./${4:dist}\nEXPOSE ${5:3000}\nCMD ${6:[\"node\", \"dist/index.js\"]}",
379
1072
  "insertTextRules": 4,
380
- "sortText": "30_copy_first"
1073
+ "sortText": "18_bp_multistage"
381
1074
  },
382
1075
  {
383
- "label": "ARG + ENV pattern",
1076
+ "label": "Distroless final stage",
384
1077
  "kind": 15,
385
- "detail": "Use ARG to set ENV at build time",
386
- "documentation": { "value": "Combine ARG and ENV to set environment variables that can be overridden at build time and persist at runtime.\n\n```dockerfile\nARG APP_VERSION=1.0.0\nENV APP_VERSION=${APP_VERSION}\n```\n\n`ARG` is only available during build. `ENV` persists in the running container." },
387
- "insertText": "ARG ${1:VAR_NAME}=${2:default_value}\nENV ${1:VAR_NAME}=${${1:VAR_NAME}}",
1078
+ "detail": "Distroless final stage",
1079
+ "documentation": {
1080
+ "value": "Use Google distroless as the final minimal image."
1081
+ },
1082
+ "insertText": "FROM gcr.io/distroless/${1|static-debian12,base-debian12,cc-debian12,java21-debian12,python3-debian12,nodejs22-debian12|}\nCOPY --from=builder ${2:/app/binary} ${3:/}\nUSER nonroot:nonroot\nENTRYPOINT [\"${4:/binary}\"]",
388
1083
  "insertTextRules": 4,
389
- "sortText": "31_arg_env"
1084
+ "sortText": "18_bp_distroless"
390
1085
  },
391
1086
  {
392
- "label": "HEALTHCHECK CMD",
1087
+ "label": "Signal handling (tini)",
393
1088
  "kind": 15,
394
- "detail": "Health check with all options",
395
- "documentation": { "value": "Configure a health check with interval, timeout, start period, and retries.\n\n```dockerfile\nHEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \\\n CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1\n```\n\nOptions:\n- `--interval=DURATION` (default 30s)\n- `--timeout=DURATION` (default 30s)\n- `--start-period=DURATION` (default 0s)\n- `--retries=N` (default 3)" },
396
- "insertText": "HEALTHCHECK --interval=${1:30s} --timeout=${2:10s} --start-period=${3:40s} --retries=${4:3} \\\n CMD ${5:wget --no-verbose --tries=1 --spider http://localhost:${6:8080}/health || exit 1}",
1089
+ "detail": "Signal handling with tini",
1090
+ "documentation": {
1091
+ "value": "Use tini init for proper PID 1 signal handling."
1092
+ },
1093
+ "insertText": "RUN apt-get update && apt-get install -y --no-install-recommends tini \\\n && rm -rf /var/lib/apt/lists/*\nENTRYPOINT [\"tini\", \"--\"]\nCMD [\"${1:node}\", \"${2:server.js}\"]",
397
1094
  "insertTextRules": 4,
398
- "sortText": "31_healthcheck"
1095
+ "sortText": "18_bp_tini"
399
1096
  },
400
1097
  {
401
- "label": "Multi-stage builder pattern",
1098
+ "label": "Build cache optimization",
402
1099
  "kind": 15,
403
- "detail": "Multi-stage build with builder stage",
404
- "documentation": { "value": "Use a multi-stage build to compile/build in one stage and copy artifacts to a minimal final image.\n\n```dockerfile\nFROM node:20-alpine AS builder\nWORKDIR /app\nCOPY . .\nRUN npm ci && npm run build\n\nFROM nginx:alpine\nCOPY --from=builder /app/dist /usr/share/nginx/html\nEXPOSE 80\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n```" },
405
- "insertText": "FROM ${1:node:20-alpine} AS builder\nWORKDIR /app\nCOPY . .\nRUN ${2:npm ci && npm run build}\n\nFROM ${3:nginx:alpine}\nCOPY --from=builder ${4:/app/dist} ${5:/usr/share/nginx/html}\nEXPOSE ${6:80}\nCMD [\"${7:nginx}\", \"${8:-g}\", \"${9:daemon off;}\"]",
1100
+ "detail": "Layer caching order",
1101
+ "documentation": {
1102
+ "value": "Copy dependency files before source for cache optimization."
1103
+ },
1104
+ "insertText": "# Copy dependency manifests first (changes less often)\nCOPY ${1:package.json} ${2:package-lock.json} ./\nRUN ${3:npm ci}\n\n# Copy source code (changes more often)\nCOPY . .\nRUN ${4:npm run build}",
406
1105
  "insertTextRules": 4,
407
- "sortText": "32_multistage_builder"
1106
+ "sortText": "18_bp_cache_order"
408
1107
  },
409
1108
  {
410
- "label": "Non-root user pattern",
1109
+ "label": "FROM alpine",
411
1110
  "kind": 15,
412
- "detail": "Create and switch to non-root user",
413
- "documentation": { "value": "Security best practice: run the final container as a non-root user.\n\n```dockerfile\nRUN addgroup --system appgroup && adduser --system --ingroup appgroup appuser\nUSER appuser\n```" },
414
- "insertText": "RUN addgroup --system ${1:appgroup} && adduser --system --ingroup ${1:appgroup} ${2:appuser}\nUSER ${2:appuser}",
1111
+ "detail": "Alpine Linux",
1112
+ "documentation": {
1113
+ "value": "Minimal 5MB Alpine Linux base image."
1114
+ },
1115
+ "insertText": "FROM alpine:${1:3.19}",
415
1116
  "insertTextRules": 4,
416
- "sortText": "33_nonroot_user"
1117
+ "sortText": "19_base_alpine"
417
1118
  },
418
1119
  {
419
- "label": "Dockerfile: Node.js app",
1120
+ "label": "FROM node:alpine",
420
1121
  "kind": 15,
421
- "detail": "Complete Dockerfile for a Node.js application",
422
- "documentation": { "value": "Production-ready Dockerfile for a Node.js application with multi-stage build, non-root user, and health check.\n\n```dockerfile\nFROM node:20-alpine AS builder\nWORKDIR /app\nCOPY package.json package-lock.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM node:20-alpine\nRUN addgroup -S app && adduser -S app -G app\nWORKDIR /app\nCOPY --from=builder --chown=app:app /app/dist ./dist\nCOPY --from=builder --chown=app:app /app/node_modules ./node_modules\nCOPY --from=builder --chown=app:app /app/package.json ./\nUSER app\nEXPOSE 3000\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD wget -qO- http://localhost:3000/health || exit 1\nCMD [\"node\", \"dist/index.js\"]\n```" },
423
- "insertText": "FROM node:${1:20-alpine} AS builder\nWORKDIR /app\nCOPY package.json package-lock.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\nFROM node:${1:20-alpine}\nRUN addgroup -S app && adduser -S app -G app\nWORKDIR /app\nCOPY --from=builder --chown=app:app /app/dist ./dist\nCOPY --from=builder --chown=app:app /app/node_modules ./node_modules\nCOPY --from=builder --chown=app:app /app/package.json ./\nUSER app\nEXPOSE ${2:3000}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD wget -qO- http://localhost:${2:3000}/health || exit 1\nCMD [\"node\", \"dist/index.js\"]",
1122
+ "detail": "Node.js Alpine",
1123
+ "documentation": {
1124
+ "value": "Node.js on Alpine Linux."
1125
+ },
1126
+ "insertText": "FROM node:${1:20}-alpine",
424
1127
  "insertTextRules": 4,
425
- "sortText": "40_full_node"
1128
+ "sortText": "19_base_node_alpine"
426
1129
  },
427
1130
  {
428
- "label": "Dockerfile: Python app",
1131
+ "label": "FROM node:slim",
429
1132
  "kind": 15,
430
- "detail": "Complete Dockerfile for a Python application",
431
- "documentation": { "value": "Production-ready Dockerfile for a Python application with virtual env, non-root user, and best practices.\n\n```dockerfile\nFROM python:3.12-slim AS builder\nWORKDIR /app\nRUN python -m venv /opt/venv\nENV PATH=\"/opt/venv/bin:$PATH\"\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\n\nFROM python:3.12-slim\nRUN useradd --create-home appuser\nWORKDIR /app\nCOPY --from=builder /opt/venv /opt/venv\nENV PATH=\"/opt/venv/bin:$PATH\"\nCOPY --chown=appuser:appuser . .\nUSER appuser\nEXPOSE 8000\nCMD [\"python\", \"-m\", \"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8000\"]\n```" },
432
- "insertText": "FROM python:${1:3.12-slim} AS builder\nWORKDIR /app\nRUN python -m venv /opt/venv\nENV PATH=\"/opt/venv/bin:$$PATH\"\nCOPY requirements.txt .\nRUN pip install --no-cache-dir -r requirements.txt\n\nFROM python:${1:3.12-slim}\nRUN useradd --create-home appuser\nWORKDIR /app\nCOPY --from=builder /opt/venv /opt/venv\nENV PATH=\"/opt/venv/bin:$$PATH\"\nCOPY --chown=appuser:appuser . .\nUSER appuser\nEXPOSE ${2:8000}\nCMD [\"python\", \"-m\", \"${3:uvicorn}\", \"${4:main:app}\", \"--host\", \"0.0.0.0\", \"--port\", \"${2:8000}\"]",
1133
+ "detail": "Node.js Slim",
1134
+ "documentation": {
1135
+ "value": "Node.js on Debian slim."
1136
+ },
1137
+ "insertText": "FROM node:${1:20}-slim",
433
1138
  "insertTextRules": 4,
434
- "sortText": "40_full_python"
1139
+ "sortText": "19_base_node_slim"
435
1140
  },
436
1141
  {
437
- "label": "Dockerfile: Go app",
1142
+ "label": "FROM python:slim",
438
1143
  "kind": 15,
439
- "detail": "Complete Dockerfile for a Go application",
440
- "documentation": { "value": "Production-ready multi-stage Dockerfile for a Go application using scratch as the final image.\n\n```dockerfile\nFROM golang:1.22-alpine AS builder\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags='-w -s' -o /app/server ./cmd/server\n\nFROM scratch\nCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/\nCOPY --from=builder /app/server /server\nEXPOSE 8080\nENTRYPOINT [\"/server\"]\n```" },
441
- "insertText": "FROM golang:${1:1.22-alpine} AS builder\nWORKDIR /app\nCOPY go.mod go.sum ./\nRUN go mod download\nCOPY . .\nRUN CGO_ENABLED=0 GOOS=linux go build -ldflags='-w -s' -o /app/${2:server} ./${3:cmd/server}\n\nFROM scratch\nCOPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/\nCOPY --from=builder /app/${2:server} /${2:server}\nEXPOSE ${4:8080}\nENTRYPOINT [\"/${2:server}\"]",
1144
+ "detail": "Python Slim",
1145
+ "documentation": {
1146
+ "value": "Python on Debian slim."
1147
+ },
1148
+ "insertText": "FROM python:${1:3.12}-slim",
442
1149
  "insertTextRules": 4,
443
- "sortText": "40_full_go"
1150
+ "sortText": "19_base_python_slim"
444
1151
  },
445
1152
  {
446
- "label": "Dockerfile: Multi-stage build",
1153
+ "label": "FROM python:alpine",
447
1154
  "kind": 15,
448
- "detail": "Generic multi-stage build template",
449
- "documentation": { "value": "A generic multi-stage build template. First stage builds, second stage runs.\n\n```dockerfile\n# Build stage\nFROM image:tag AS builder\nWORKDIR /app\nCOPY . .\nRUN make build\n\n# Production stage\nFROM image:tag\nWORKDIR /app\nCOPY --from=builder /app/output /app/\nEXPOSE 8080\nCMD [\"./app\"]\n```" },
450
- "insertText": "# Build stage\nFROM ${1:image}:${2:tag} AS builder\nWORKDIR /app\nCOPY . .\nRUN ${3:make build}\n\n# Production stage\nFROM ${4:image}:${5:tag}\nWORKDIR /app\nCOPY --from=builder /app/${6:output} /app/\nEXPOSE ${7:8080}\nCMD [\"${8:./app}\"]",
1155
+ "detail": "Python Alpine",
1156
+ "documentation": {
1157
+ "value": "Python on Alpine Linux."
1158
+ },
1159
+ "insertText": "FROM python:${1:3.12}-alpine",
451
1160
  "insertTextRules": 4,
452
- "sortText": "40_full_multistage"
1161
+ "sortText": "19_base_python_alpine"
453
1162
  },
454
1163
  {
455
- "label": "Dockerfile: Rust app",
1164
+ "label": "FROM golang:alpine",
456
1165
  "kind": 15,
457
- "detail": "Complete Dockerfile for a Rust application",
458
- "documentation": { "value": "Production-ready multi-stage Dockerfile for a Rust application.\n\n```dockerfile\nFROM rust:1.77-slim AS builder\nWORKDIR /app\nCOPY Cargo.toml Cargo.lock ./\nRUN mkdir src && echo 'fn main(){}' > src/main.rs && cargo build --release && rm -rf src\nCOPY src ./src\nRUN cargo build --release\n\nFROM debian:bookworm-slim\nRUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*\nCOPY --from=builder /app/target/release/myapp /usr/local/bin/myapp\nEXPOSE 8080\nCMD [\"myapp\"]\n```" },
459
- "insertText": "FROM rust:${1:1.77-slim} AS builder\nWORKDIR /app\nCOPY Cargo.toml Cargo.lock ./\nRUN mkdir src && echo 'fn main(){}' > src/main.rs && cargo build --release && rm -rf src\nCOPY src ./src\nRUN cargo build --release\n\nFROM debian:bookworm-slim\nRUN apt-get update && apt-get install -y --no-install-recommends ca-certificates && rm -rf /var/lib/apt/lists/*\nCOPY --from=builder /app/target/release/${2:myapp} /usr/local/bin/${2:myapp}\nEXPOSE ${3:8080}\nCMD [\"${2:myapp}\"]",
1166
+ "detail": "Go Alpine",
1167
+ "documentation": {
1168
+ "value": "Go on Alpine Linux."
1169
+ },
1170
+ "insertText": "FROM golang:${1:1.22}-alpine",
460
1171
  "insertTextRules": 4,
461
- "sortText": "40_full_rust"
1172
+ "sortText": "19_base_golang_alpine"
462
1173
  },
463
1174
  {
464
- "label": "Dockerfile: Nginx static site",
1175
+ "label": "FROM ubuntu",
465
1176
  "kind": 15,
466
- "detail": "Dockerfile for serving static files with Nginx",
467
- "documentation": { "value": "Serve a static website or SPA with Nginx.\n\n```dockerfile\nFROM nginx:alpine\nCOPY nginx.conf /etc/nginx/conf.d/default.conf\nCOPY dist/ /usr/share/nginx/html/\nEXPOSE 80\nHEALTHCHECK --interval=30s --timeout=5s CMD wget -qO- http://localhost/ || exit 1\nCMD [\"nginx\", \"-g\", \"daemon off;\"]\n```" },
468
- "insertText": "FROM nginx:alpine\nCOPY ${1:nginx.conf} /etc/nginx/conf.d/default.conf\nCOPY ${2:dist/} /usr/share/nginx/html/\nEXPOSE 80\nHEALTHCHECK --interval=30s --timeout=5s \\\n CMD wget -qO- http://localhost/ || exit 1\nCMD [\"nginx\", \"-g\", \"daemon off;\"]",
1177
+ "detail": "Ubuntu",
1178
+ "documentation": {
1179
+ "value": "Ubuntu base image."
1180
+ },
1181
+ "insertText": "FROM ubuntu:${1:24.04}",
469
1182
  "insertTextRules": 4,
470
- "sortText": "40_full_nginx"
1183
+ "sortText": "19_base_ubuntu"
471
1184
  },
472
1185
  {
473
- "label": "apk add pattern",
1186
+ "label": "FROM debian:slim",
474
1187
  "kind": 15,
475
- "detail": "Alpine package install with cleanup",
476
- "documentation": { "value": "Install packages on Alpine Linux with `--no-cache` to avoid caching the index.\n\n```dockerfile\nRUN apk add --no-cache \\\n curl \\\n ca-certificates \\\n tzdata\n```" },
477
- "insertText": "RUN apk add --no-cache \\\n ${1:package}",
1188
+ "detail": "Debian Slim",
1189
+ "documentation": {
1190
+ "value": "Minimal Debian base image."
1191
+ },
1192
+ "insertText": "FROM debian:${1:bookworm}-slim",
478
1193
  "insertTextRules": 4,
479
- "sortText": "30_apk_install"
1194
+ "sortText": "19_base_debian_slim"
480
1195
  },
481
1196
  {
482
- "label": "ENTRYPOINT + CMD pattern",
1197
+ "label": "FROM nginx:alpine",
483
1198
  "kind": 15,
484
- "detail": "ENTRYPOINT with CMD as default args",
485
- "documentation": { "value": "Use ENTRYPOINT for the executable and CMD for default arguments. Users can override CMD args at `docker run`.\n\n```dockerfile\nENTRYPOINT [\"python\", \"app.py\"]\nCMD [\"--port\", \"8000\"]\n\n# docker run myimage -> python app.py --port 8000\n# docker run myimage --port 9000 -> python app.py --port 9000\n```" },
486
- "insertText": "ENTRYPOINT [\"${1:executable}\"]\nCMD [\"${2:--default-arg}\", \"${3:value}\"]",
1199
+ "detail": "Nginx Alpine",
1200
+ "documentation": {
1201
+ "value": "Nginx on Alpine Linux."
1202
+ },
1203
+ "insertText": "FROM nginx:${1:alpine}",
487
1204
  "insertTextRules": 4,
488
- "sortText": "31_entrypoint_cmd"
1205
+ "sortText": "19_base_nginx_alpine"
489
1206
  },
490
1207
  {
491
- "label": ".dockerignore note",
1208
+ "label": "FROM distroless",
492
1209
  "kind": 15,
493
- "detail": "Reminder to create .dockerignore",
494
- "documentation": { "value": "Always create a `.dockerignore` file to exclude files from the build context, reducing build time and image size.\n\n```\n# .dockerignore\nnode_modules\n.git\n.env\n*.md\nDockerfile\n.dockerignore\ndist\ncoverage\n.nyc_output\n```" },
495
- "insertText": "# Remember to create a .dockerignore file:\n# node_modules\n# .git\n# .env\n# *.md\n# Dockerfile\n# .dockerignore",
1210
+ "detail": "Distroless static",
1211
+ "documentation": {
1212
+ "value": "Google distroless static image (no shell)."
1213
+ },
1214
+ "insertText": "FROM gcr.io/distroless/static-debian12",
496
1215
  "insertTextRules": 4,
497
- "sortText": "50_dockerignore"
1216
+ "sortText": "19_base_distroless"
498
1217
  },
499
1218
  {
500
- "label": "COPY --link",
1219
+ "label": "FROM scratch",
501
1220
  "kind": 15,
502
- "detail": "Copy with independent layer",
503
- "documentation": { "value": "Use `--link` to create an independent layer that doesn't depend on previous layers, enabling better cache reuse.\n\n```dockerfile\nCOPY --link package.json ./\nCOPY --link --from=builder /app/dist ./dist\n```\n\nAvailable since BuildKit. The layer is not invalidated by changes to prior layers." },
504
- "insertText": "COPY --link ${1:src} ${2:dest}",
1221
+ "detail": "Scratch (empty)",
1222
+ "documentation": {
1223
+ "value": "Empty base image for static binaries."
1224
+ },
1225
+ "insertText": "FROM scratch",
505
1226
  "insertTextRules": 4,
506
- "sortText": "08_COPY_link"
1227
+ "sortText": "19_base_scratch"
507
1228
  },
508
1229
  {
509
- "label": "RUN --network=none",
1230
+ "label": "COPY --parents",
510
1231
  "kind": 15,
511
- "detail": "RUN with no network access",
512
- "documentation": { "value": "Disable network access during a RUN step for security.\n\n```dockerfile\nRUN --network=none cat /etc/hostname\n```" },
513
- "insertText": "RUN --network=none ${1:command}",
1232
+ "detail": "Copy preserving directory structure",
1233
+ "documentation": {
1234
+ "value": "Copy files preserving parent directory structure (BuildKit).\n\n```dockerfile\nCOPY --parents src/app/config.json /app/\n# Creates /app/src/app/config.json\n```"
1235
+ },
1236
+ "insertText": "COPY --parents ${1:src/dir/} ${2:/dest/}",
1237
+ "insertTextRules": 4,
1238
+ "sortText": "02_copy_parents"
1239
+ },
1240
+ {
1241
+ "label": "ADD --keep-git-dir",
1242
+ "kind": 15,
1243
+ "detail": "Add Git repo keeping .git",
1244
+ "documentation": {
1245
+ "value": "Clone and keep the .git directory (BuildKit).\n\n```dockerfile\nADD --keep-git-dir=true https://github.com/user/repo.git /src\n```"
1246
+ },
1247
+ "insertText": "ADD --keep-git-dir=true ${1:https://github.com/user/repo.git} ${2:/src}",
1248
+ "insertTextRules": 4,
1249
+ "sortText": "02_add_gitdir"
1250
+ },
1251
+ {
1252
+ "label": ".dockerignore pattern",
1253
+ "kind": 15,
1254
+ "detail": ".dockerignore best practice",
1255
+ "documentation": {
1256
+ "value": "Recommended .dockerignore contents to reduce build context.\n\n```\n# .dockerignore\nnode_modules\n.git\n.env\n*.md\nDockerfile*\ndocker-compose*\n.dockerignore\n.vscode\n__pycache__\n*.pyc\n.tox\n.coverage\ndist\nbuild\n```"
1257
+ },
1258
+ "insertText": "# .dockerignore\nnode_modules\n.git\n.env\n*.md\nDockerfile*\ndocker-compose*\n.dockerignore\n${1:.vscode}",
514
1259
  "insertTextRules": 4,
515
- "sortText": "01_RUN_nonetwork"
1260
+ "sortText": "09_dockerignore"
516
1261
  },
517
1262
  {
518
- "label": "LABEL OCI metadata",
1263
+ "label": "COPY heredoc",
519
1264
  "kind": 15,
520
- "detail": "OCI standard image labels",
521
- "documentation": { "value": "Apply standardized OCI annotations to your image.\n\n```dockerfile\nLABEL org.opencontainers.image.title=\"My App\" \\\n org.opencontainers.image.description=\"Description\" \\\n org.opencontainers.image.version=\"1.0.0\" \\\n org.opencontainers.image.source=\"https://github.com/user/repo\" \\\n org.opencontainers.image.licenses=\"MIT\"\n```" },
522
- "insertText": "LABEL org.opencontainers.image.title=\"${1:App Name}\" \\\n org.opencontainers.image.description=\"${2:Description}\" \\\n org.opencontainers.image.version=\"${3:1.0.0}\" \\\n org.opencontainers.image.source=\"${4:https://github.com/user/repo}\" \\\n org.opencontainers.image.licenses=\"${5:MIT}\"",
1265
+ "detail": "Inline file creation with heredoc",
1266
+ "documentation": {
1267
+ "value": "Create files inline using heredoc syntax (BuildKit).\n\n```dockerfile\nCOPY <<EOF /app/config.json\n{\"key\": \"value\"}\nEOF\n```"
1268
+ },
1269
+ "insertText": "COPY <<EOF ${1:/app/config.json}\n${2:content}\nEOF",
523
1270
  "insertTextRules": 4,
524
- "sortText": "03_LABEL_oci"
1271
+ "sortText": "02_copy_heredoc"
525
1272
  },
526
1273
  {
527
- "label": "Dockerfile: Java Spring Boot app",
1274
+ "label": "RUN pipe pattern",
528
1275
  "kind": 15,
529
- "detail": "Dockerfile for Java Spring Boot using layered JARs",
530
- "documentation": { "value": "Multi-stage Dockerfile for a Spring Boot application with dependency layer caching.\n\n```dockerfile\nFROM eclipse-temurin:21-jdk-alpine AS builder\nWORKDIR /app\nCOPY . .\nRUN ./mvnw package -DskipTests\n\nFROM eclipse-temurin:21-jre-alpine\nWORKDIR /app\nCOPY --from=builder /app/target/*.jar app.jar\nRUN addgroup -S spring && adduser -S spring -G spring\nUSER spring\nEXPOSE 8080\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD wget -qO- http://localhost:8080/actuator/health || exit 1\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]\n```" },
531
- "insertText": "FROM eclipse-temurin:${1:21-jdk-alpine} AS builder\nWORKDIR /app\nCOPY . .\nRUN ./mvnw package -DskipTests\n\nFROM eclipse-temurin:${2:21-jre-alpine}\nWORKDIR /app\nCOPY --from=builder /app/target/*.jar app.jar\nRUN addgroup -S spring && adduser -S spring -G spring\nUSER spring\nEXPOSE ${3:8080}\nHEALTHCHECK --interval=30s --timeout=10s --retries=3 \\\n CMD wget -qO- http://localhost:${3:8080}/actuator/health || exit 1\nENTRYPOINT [\"java\", \"-jar\", \"app.jar\"]",
1276
+ "detail": "RUN with pipe and set -o pipefail",
1277
+ "documentation": {
1278
+ "value": "Use pipefail for reliable pipe error detection.\n\n```dockerfile\nRUN set -o pipefail && curl -fsSL https://example.com/install.sh | bash\n```"
1279
+ },
1280
+ "insertText": "RUN set -o pipefail && ${1:curl -fsSL https://example.com/install.sh} | ${2:bash}",
532
1281
  "insertTextRules": 4,
533
- "sortText": "40_full_java"
1282
+ "sortText": "01_run_pipe"
534
1283
  }
535
1284
  ]
536
- }
1285
+ }