@git.zone/tsdocker 1.17.2 โ 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_ts/00_commitinfo_data.js +2 -2
- package/dist_ts/classes.registrycopy.js +1 -1
- package/dist_ts/interfaces/index.d.ts +0 -7
- package/dist_ts/tsdocker.cli.js +62 -37
- package/dist_ts/tsdocker.config.d.ts +1 -4
- package/dist_ts/tsdocker.config.js +3 -22
- package/dist_ts/tsdocker.paths.d.ts +0 -1
- package/dist_ts/tsdocker.paths.js +1 -2
- package/dist_ts/tsdocker.plugins.d.ts +1 -5
- package/dist_ts/tsdocker.plugins.js +2 -6
- package/package.json +2 -14
- package/readme.hints.md +1 -10
- package/readme.md +163 -78
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.registrycopy.ts +1 -1
- package/ts/interfaces/index.ts +0 -8
- package/ts/tsdocker.cli.ts +62 -42
- package/ts/tsdocker.config.ts +4 -29
- package/ts/tsdocker.paths.ts +0 -1
- package/ts/tsdocker.plugins.ts +0 -8
- package/assets/Dockerfile +0 -6
- package/dist_ts/tsdocker.docker.d.ts +0 -2
- package/dist_ts/tsdocker.docker.js +0 -145
- package/dist_ts/tsdocker.snippets.d.ts +0 -5
- package/dist_ts/tsdocker.snippets.js +0 -26
- package/ts/tsdocker.docker.ts +0 -169
- package/ts/tsdocker.snippets.ts +0 -34
package/readme.md
CHANGED
|
@@ -12,13 +12,15 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
|
|
|
12
12
|
|
|
13
13
|
### ๐ฏ Key Capabilities
|
|
14
14
|
|
|
15
|
-
- ๐งช **Containerized Testing** โ Run your tests in pristine Docker environments
|
|
16
15
|
- ๐๏ธ **Smart Docker Builds** โ Automatically discover, sort, and build Dockerfiles by dependency
|
|
17
16
|
- ๐ **True Multi-Architecture** โ Build for `amd64` and `arm64` simultaneously with Docker Buildx
|
|
18
17
|
- ๐ **Multi-Registry Push** โ Ship to Docker Hub, GitLab, GitHub Container Registry, and more via OCI Distribution API
|
|
19
18
|
- โก **Parallel Builds** โ Level-based parallel builds with configurable concurrency
|
|
20
19
|
- ๐๏ธ **Persistent Local Registry** โ All images flow through a local OCI registry with persistent storage
|
|
21
20
|
- ๐ฆ **Build Caching** โ Skip unchanged Dockerfiles with content-hash caching
|
|
21
|
+
- ๐ฏ **Dockerfile Filtering** โ Build or push only specific Dockerfiles using glob patterns
|
|
22
|
+
- ๐ **Resilient Push** โ Automatic retry with exponential backoff, timeouts, and token refresh for rock-solid pushes
|
|
23
|
+
- ๐ญ **CI-Safe Isolation** โ Unique sessions per invocation prevent collisions in parallel CI pipelines
|
|
22
24
|
- ๐ง **Zero Config Start** โ Works out of the box, scales with your needs
|
|
23
25
|
|
|
24
26
|
## Installation
|
|
@@ -33,16 +35,6 @@ pnpm install --save-dev @git.zone/tsdocker
|
|
|
33
35
|
|
|
34
36
|
## Quick Start
|
|
35
37
|
|
|
36
|
-
### ๐งช Run Tests in Docker
|
|
37
|
-
|
|
38
|
-
The simplest use case โ run your tests in a clean container:
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
tsdocker
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
This pulls your configured base image, mounts your project, and executes your test command in isolation.
|
|
45
|
-
|
|
46
38
|
### ๐๏ธ Build Docker Images
|
|
47
39
|
|
|
48
40
|
Got `Dockerfile` files? Build them all with automatic dependency ordering:
|
|
@@ -68,15 +60,33 @@ tsdocker push
|
|
|
68
60
|
|
|
69
61
|
# Push to a specific registry
|
|
70
62
|
tsdocker push --registry=registry.gitlab.com
|
|
63
|
+
|
|
64
|
+
# Push without rebuilding (use existing images in local registry)
|
|
65
|
+
tsdocker push --no-build
|
|
71
66
|
```
|
|
72
67
|
|
|
73
|
-
Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images directly from the local registry to remote registries. This means multi-arch manifest lists are preserved end-to-end โ no more single-platform-only pushes.
|
|
68
|
+
Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images directly from the local registry to remote registries. This means multi-arch manifest lists are preserved end-to-end โ no more single-platform-only pushes. Every request is protected with **automatic retry** (up to 6 attempts with exponential backoff) and **5-minute timeouts**, so transient network issues don't kill your push mid-transfer.
|
|
69
|
+
|
|
70
|
+
### ๐ฏ Build Only Specific Dockerfiles
|
|
71
|
+
|
|
72
|
+
Target specific Dockerfiles by name pattern โ dependencies are resolved automatically:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Build only the base image
|
|
76
|
+
tsdocker build Dockerfile_base
|
|
77
|
+
|
|
78
|
+
# Build anything matching a glob pattern
|
|
79
|
+
tsdocker build Dockerfile_app*
|
|
80
|
+
|
|
81
|
+
# Push specific images only (skip build phase)
|
|
82
|
+
tsdocker push --no-build Dockerfile_api Dockerfile_web
|
|
83
|
+
```
|
|
74
84
|
|
|
75
85
|
## CLI Commands
|
|
76
86
|
|
|
77
87
|
| Command | Description |
|
|
78
88
|
|---------|-------------|
|
|
79
|
-
| `tsdocker` |
|
|
89
|
+
| `tsdocker` | Show usage / man page |
|
|
80
90
|
| `tsdocker build` | Build all Dockerfiles with dependency ordering |
|
|
81
91
|
| `tsdocker push` | Build + push images to configured registries |
|
|
82
92
|
| `tsdocker pull <registry>` | Pull images from a specific registry |
|
|
@@ -84,12 +94,12 @@ Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images
|
|
|
84
94
|
| `tsdocker login` | Authenticate with configured registries |
|
|
85
95
|
| `tsdocker list` | Display discovered Dockerfiles and their dependencies |
|
|
86
96
|
| `tsdocker clean` | Interactively clean Docker environment |
|
|
87
|
-
| `tsdocker vscode` | Launch containerized VS Code in browser |
|
|
88
97
|
|
|
89
98
|
### Build Flags
|
|
90
99
|
|
|
91
100
|
| Flag | Description |
|
|
92
101
|
|------|-------------|
|
|
102
|
+
| `<patterns>` | Positional Dockerfile name patterns (e.g. `Dockerfile_base`, `Dockerfile_app*`) |
|
|
93
103
|
| `--platform=linux/arm64` | Override build platform for a single architecture |
|
|
94
104
|
| `--timeout=600` | Build timeout in seconds |
|
|
95
105
|
| `--no-cache` | Force rebuild without Docker layer cache |
|
|
@@ -99,6 +109,14 @@ Under the hood, `tsdocker push` uses the **OCI Distribution API** to copy images
|
|
|
99
109
|
| `--parallel=8` | Parallel builds with custom concurrency |
|
|
100
110
|
| `--context=mycontext` | Use a specific Docker context |
|
|
101
111
|
|
|
112
|
+
### Push Flags
|
|
113
|
+
|
|
114
|
+
| Flag | Description |
|
|
115
|
+
|------|-------------|
|
|
116
|
+
| `<patterns>` | Positional Dockerfile name patterns to select which images to push |
|
|
117
|
+
| `--registry=<url>` | Push to a single specific registry instead of all configured |
|
|
118
|
+
| `--no-build` | Skip the build phase; only push existing images from local registry |
|
|
119
|
+
|
|
102
120
|
### Clean Flags
|
|
103
121
|
|
|
104
122
|
| Flag | Description |
|
|
@@ -138,16 +156,6 @@ Configure tsdocker in your `package.json` or `npmextra.json` under the `@git.zon
|
|
|
138
156
|
| `platforms` | `string[]` | `["linux/amd64"]` | Target architectures for multi-arch builds |
|
|
139
157
|
| `testDir` | `string` | `./test` | Directory containing test scripts |
|
|
140
158
|
|
|
141
|
-
#### Legacy Testing Options
|
|
142
|
-
|
|
143
|
-
These options configure the `tsdocker` default command (containerized test runner):
|
|
144
|
-
|
|
145
|
-
| Option | Type | Default | Description |
|
|
146
|
-
|--------|------|---------|-------------|
|
|
147
|
-
| `baseImage` | `string` | `hosttoday/ht-docker-node:npmdocker` | Docker image for test environment |
|
|
148
|
-
| `command` | `string` | `npmci npm test` | Command to run inside the container |
|
|
149
|
-
| `dockerSock` | `boolean` | `false` | Mount Docker socket for DinD scenarios |
|
|
150
|
-
|
|
151
159
|
## Architecture: How tsdocker Works
|
|
152
160
|
|
|
153
161
|
tsdocker uses a **local OCI registry** as the canonical store for all built images. This design solves fundamental problems with Docker's local daemon, which cannot hold multi-architecture manifest lists.
|
|
@@ -155,36 +163,37 @@ tsdocker uses a **local OCI registry** as the canonical store for all built imag
|
|
|
155
163
|
### ๐ Build Flow
|
|
156
164
|
|
|
157
165
|
```
|
|
158
|
-
|
|
159
|
-
โ tsdocker build
|
|
160
|
-
โ
|
|
161
|
-
โ 1. Start local registry (localhost
|
|
162
|
-
โ โโโ Persistent volume: .nogit/docker-registry/
|
|
163
|
-
โ
|
|
164
|
-
โ 2. For each Dockerfile (topological order):
|
|
165
|
-
โ โโโ Multi-platform: buildx --push โ registry
|
|
166
|
-
โ โโโ Single-platform: docker build โ registry
|
|
167
|
-
โ
|
|
168
|
-
โ 3. Stop local registry (data persists on disk)
|
|
169
|
-
|
|
166
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
167
|
+
โ tsdocker build โ
|
|
168
|
+
โ โ
|
|
169
|
+
โ 1. Start local registry (localhost:<dynamic-port>) โ
|
|
170
|
+
โ โโโ Persistent volume: .nogit/docker-registry/ โ
|
|
171
|
+
โ โ
|
|
172
|
+
โ 2. For each Dockerfile (topological order): โ
|
|
173
|
+
โ โโโ Multi-platform: buildx --push โ registry โ
|
|
174
|
+
โ โโโ Single-platform: docker build โ registry โ
|
|
175
|
+
โ โ
|
|
176
|
+
โ 3. Stop local registry (data persists on disk) โ
|
|
177
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
170
178
|
```
|
|
171
179
|
|
|
172
180
|
### ๐ค Push Flow
|
|
173
181
|
|
|
174
182
|
```
|
|
175
|
-
|
|
176
|
-
โ tsdocker push
|
|
177
|
-
โ
|
|
178
|
-
โ 1. Start local registry (loads persisted data)
|
|
179
|
-
โ
|
|
180
|
-
โ 2. For each image ร each remote registry:
|
|
181
|
-
โ โโโ OCI Distribution API copy:
|
|
182
|
-
โ โโโ Fetch manifest (single or multi-arch)
|
|
183
|
-
โ โโโ Copy blobs (skip if already exist)
|
|
184
|
-
โ
|
|
185
|
-
โ
|
|
186
|
-
โ
|
|
187
|
-
|
|
183
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
184
|
+
โ tsdocker push โ
|
|
185
|
+
โ โ
|
|
186
|
+
โ 1. Start local registry (loads persisted data) โ
|
|
187
|
+
โ โ
|
|
188
|
+
โ 2. For each image ร each remote registry: โ
|
|
189
|
+
โ โโโ OCI Distribution API copy (with retry): โ
|
|
190
|
+
โ โโโ Fetch manifest (single or multi-arch) โ
|
|
191
|
+
โ โโโ Copy blobs (skip if already exist) โ
|
|
192
|
+
โ โโโ Retry up to 6ร with exponential backoff โ
|
|
193
|
+
โ โโโ Push manifest with destination tag โ
|
|
194
|
+
โ โ
|
|
195
|
+
โ 3. Stop local registry โ
|
|
196
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
188
197
|
```
|
|
189
198
|
|
|
190
199
|
### ๐ Why a Local Registry?
|
|
@@ -196,6 +205,49 @@ tsdocker uses a **local OCI registry** as the canonical store for all built imag
|
|
|
196
205
|
| Images lost between build and push phases | Persistent storage at `.nogit/docker-registry/` survives restarts |
|
|
197
206
|
| Redundant blob uploads on incremental pushes | HEAD checks skip blobs that already exist on the remote |
|
|
198
207
|
|
|
208
|
+
### ๐ Resilient Push
|
|
209
|
+
|
|
210
|
+
The OCI Distribution API client wraps every HTTP request with:
|
|
211
|
+
|
|
212
|
+
- **Timeouts** โ 5-minute timeout for blob operations, 30-second timeout for auth/metadata calls via `AbortSignal.timeout()`
|
|
213
|
+
- **Automatic Retry** โ Up to 6 attempts with exponential backoff (1s โ 2s โ 4s โ 8s โ 16s โ 32s)
|
|
214
|
+
- **Smart Retry Logic** โ Retries on network errors (`ECONNRESET`, `fetch failed`) and 5xx server errors; does NOT retry 4xx client errors
|
|
215
|
+
- **Token Refresh** โ On 401 responses, the cached auth token is cleared so the next retry re-authenticates automatically
|
|
216
|
+
|
|
217
|
+
This means transient issues like stale connection pools, brief network blips, or token expiry during long multi-arch pushes (56+ blob operations) are handled gracefully instead of killing the entire transfer.
|
|
218
|
+
|
|
219
|
+
### ๐ญ CI-Safe Session Isolation
|
|
220
|
+
|
|
221
|
+
Every tsdocker invocation gets its own **session** with unique:
|
|
222
|
+
|
|
223
|
+
- **Session ID** โ Random 8-char hex (override with `TSDOCKER_SESSION_ID`)
|
|
224
|
+
- **Registry port** โ Dynamically allocated (override with `TSDOCKER_REGISTRY_PORT`)
|
|
225
|
+
- **Registry container** โ Named `tsdocker-registry-<sessionId>`
|
|
226
|
+
- **Builder suffix** โ In CI, the buildx builder gets a `-<sessionId>` suffix to prevent collisions
|
|
227
|
+
|
|
228
|
+
This prevents resource conflicts when multiple CI jobs run tsdocker in parallel. Auto-detected CI systems:
|
|
229
|
+
|
|
230
|
+
| Environment Variable | CI System |
|
|
231
|
+
|---------------------|-----------|
|
|
232
|
+
| `GITEA_ACTIONS` | Gitea Actions |
|
|
233
|
+
| `GITHUB_ACTIONS` | GitHub Actions |
|
|
234
|
+
| `GITLAB_CI` | GitLab CI |
|
|
235
|
+
| `CI` | Generic CI |
|
|
236
|
+
|
|
237
|
+
In local dev, no suffix is added โ keeping a persistent builder for faster rebuilds.
|
|
238
|
+
|
|
239
|
+
### ๐ Docker Context & Topology Detection
|
|
240
|
+
|
|
241
|
+
tsdocker automatically detects your Docker environment topology:
|
|
242
|
+
|
|
243
|
+
| Topology | Detection | Meaning |
|
|
244
|
+
|----------|-----------|---------|
|
|
245
|
+
| `local` | Default | Standard Docker installation on the host |
|
|
246
|
+
| `socket-mount` | `/.dockerenv` exists | Running inside a container with Docker socket mounted |
|
|
247
|
+
| `dind` | `DOCKER_HOST` starts with `tcp://` | Docker-in-Docker setup |
|
|
248
|
+
|
|
249
|
+
Context-aware builder names (`tsdocker-builder-<context>`) prevent conflicts across Docker contexts. Rootless Docker configurations trigger appropriate warnings.
|
|
250
|
+
|
|
199
251
|
## Registry Authentication
|
|
200
252
|
|
|
201
253
|
### Environment Variables
|
|
@@ -213,7 +265,7 @@ export DOCKER_REGISTRY_PASSWORD="password"
|
|
|
213
265
|
|
|
214
266
|
### Docker Config Fallback
|
|
215
267
|
|
|
216
|
-
When pushing, tsdocker will also read credentials from `~/.docker/config.json` if no explicit credentials are provided via environment variables. This means `docker login` credentials work automatically.
|
|
268
|
+
When pushing, tsdocker will also read credentials from `~/.docker/config.json` if no explicit credentials are provided via environment variables. This means `docker login` credentials work automatically. Docker Hub special cases (`docker.io`, `index.docker.io`, `registry-1.docker.io`) are all recognized.
|
|
217
269
|
|
|
218
270
|
### Login Command
|
|
219
271
|
|
|
@@ -270,6 +322,26 @@ tsdocker discovers files matching `Dockerfile*`:
|
|
|
270
322
|
| `Dockerfile_alpine` | `alpine` |
|
|
271
323
|
| `Dockerfile_##version##` | Uses `package.json` version |
|
|
272
324
|
|
|
325
|
+
### ๐ฏ Dockerfile Filtering
|
|
326
|
+
|
|
327
|
+
Build or push only the Dockerfiles you need. Positional arguments are matched against Dockerfile basenames as glob patterns:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Build a single Dockerfile
|
|
331
|
+
tsdocker build Dockerfile_base
|
|
332
|
+
|
|
333
|
+
# Glob patterns with * and ? wildcards
|
|
334
|
+
tsdocker build Dockerfile_app*
|
|
335
|
+
|
|
336
|
+
# Multiple patterns
|
|
337
|
+
tsdocker build Dockerfile_base Dockerfile_web
|
|
338
|
+
|
|
339
|
+
# Push specific images without rebuilding
|
|
340
|
+
tsdocker push --no-build Dockerfile_api
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
When filtering for `build`, **dependencies are auto-resolved**: if `Dockerfile_app` depends on `Dockerfile_base`, specifying only `Dockerfile_app` will automatically include `Dockerfile_base` in the build order.
|
|
344
|
+
|
|
273
345
|
### ๐ Dependency-Aware Builds
|
|
274
346
|
|
|
275
347
|
If you have multiple Dockerfiles that depend on each other:
|
|
@@ -347,20 +419,6 @@ Use different repository names for different registries:
|
|
|
347
419
|
|
|
348
420
|
When pushing, tsdocker maps the local repo name to the registry-specific path. For example, a locally built `myproject:latest` becomes `registry.gitlab.com/mygroup/myproject:latest` and `docker.io/myuser/myproject:latest`.
|
|
349
421
|
|
|
350
|
-
### ๐ณ Docker-in-Docker Testing
|
|
351
|
-
|
|
352
|
-
Test Docker-related tools by mounting the Docker socket:
|
|
353
|
-
|
|
354
|
-
```json
|
|
355
|
-
{
|
|
356
|
-
"@git.zone/tsdocker": {
|
|
357
|
-
"baseImage": "docker:latest",
|
|
358
|
-
"command": "docker version && docker ps",
|
|
359
|
-
"dockerSock": true
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
422
|
### ๐ Listing Dockerfiles
|
|
365
423
|
|
|
366
424
|
Inspect your project's Dockerfiles and their relationships:
|
|
@@ -449,6 +507,19 @@ build-and-push:
|
|
|
449
507
|
DOCKER_REGISTRY_1: "ghcr.io|${{ github.actor }}|${{ secrets.GITHUB_TOKEN }}"
|
|
450
508
|
```
|
|
451
509
|
|
|
510
|
+
**Gitea Actions:**
|
|
511
|
+
|
|
512
|
+
```yaml
|
|
513
|
+
- name: Build and Push
|
|
514
|
+
run: |
|
|
515
|
+
npm install -g @git.zone/tsdocker
|
|
516
|
+
tsdocker push
|
|
517
|
+
env:
|
|
518
|
+
DOCKER_REGISTRY_1: "gitea.example.com|${{ secrets.REGISTRY_USER }}|${{ secrets.REGISTRY_PASSWORD }}"
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
tsdocker auto-detects all three CI systems and enables session isolation automatically โ no extra configuration needed.
|
|
522
|
+
|
|
452
523
|
## TypeScript API
|
|
453
524
|
|
|
454
525
|
tsdocker can also be used programmatically:
|
|
@@ -458,10 +529,6 @@ import { TsDockerManager } from '@git.zone/tsdocker/dist_ts/classes.tsdockermana
|
|
|
458
529
|
import type { ITsDockerConfig } from '@git.zone/tsdocker/dist_ts/interfaces/index.js';
|
|
459
530
|
|
|
460
531
|
const config: ITsDockerConfig = {
|
|
461
|
-
baseImage: 'node:20',
|
|
462
|
-
command: 'npm test',
|
|
463
|
-
dockerSock: false,
|
|
464
|
-
keyValueObject: {},
|
|
465
532
|
registries: ['docker.io'],
|
|
466
533
|
platforms: ['linux/amd64', 'linux/arm64'],
|
|
467
534
|
};
|
|
@@ -472,6 +539,25 @@ await manager.build({ parallel: true });
|
|
|
472
539
|
await manager.push();
|
|
473
540
|
```
|
|
474
541
|
|
|
542
|
+
## Environment Variables
|
|
543
|
+
|
|
544
|
+
### CI & Session Control
|
|
545
|
+
|
|
546
|
+
| Variable | Description |
|
|
547
|
+
|----------|-------------|
|
|
548
|
+
| `TSDOCKER_SESSION_ID` | Override the auto-generated session ID (default: random 8-char hex) |
|
|
549
|
+
| `TSDOCKER_REGISTRY_PORT` | Override the dynamically allocated local registry port |
|
|
550
|
+
| `CI` | Generic CI detection (also `GITHUB_ACTIONS`, `GITLAB_CI`, `GITEA_ACTIONS`) |
|
|
551
|
+
|
|
552
|
+
### Registry Credentials
|
|
553
|
+
|
|
554
|
+
| Variable | Description |
|
|
555
|
+
|----------|-------------|
|
|
556
|
+
| `DOCKER_REGISTRY_1` through `DOCKER_REGISTRY_10` | Pipe-delimited: `registry\|username\|password` |
|
|
557
|
+
| `DOCKER_REGISTRY_URL` | Registry URL for single-registry setup |
|
|
558
|
+
| `DOCKER_REGISTRY_USER` | Username for single-registry setup |
|
|
559
|
+
| `DOCKER_REGISTRY_PASSWORD` | Password for single-registry setup |
|
|
560
|
+
|
|
475
561
|
## Requirements
|
|
476
562
|
|
|
477
563
|
- **Docker** โ Docker Engine 20+ or Docker Desktop
|
|
@@ -507,6 +593,15 @@ tsdocker login
|
|
|
507
593
|
|
|
508
594
|
tsdocker also falls back to `~/.docker/config.json` โ ensure you've run `docker login` for your target registries.
|
|
509
595
|
|
|
596
|
+
### Push fails with "fetch failed"
|
|
597
|
+
|
|
598
|
+
tsdocker automatically retries failed requests up to 6 times with exponential backoff. If pushes still fail:
|
|
599
|
+
|
|
600
|
+
- Check network connectivity to the target registry
|
|
601
|
+
- Verify your credentials haven't expired
|
|
602
|
+
- Look for retry log messages (`fetch failed (attempt X/6)`) to diagnose the pattern
|
|
603
|
+
- Large layers may need longer timeouts โ the default 5-minute timeout per request should cover most cases
|
|
604
|
+
|
|
510
605
|
### Circular dependency detected
|
|
511
606
|
|
|
512
607
|
Review your Dockerfiles' `FROM` statements โ you have images depending on each other in a loop.
|
|
@@ -522,16 +617,6 @@ node_modules
|
|
|
522
617
|
dist_ts
|
|
523
618
|
```
|
|
524
619
|
|
|
525
|
-
## Migration from Legacy
|
|
526
|
-
|
|
527
|
-
Previously published as `npmdocker`, now `@git.zone/tsdocker`:
|
|
528
|
-
|
|
529
|
-
| Old | New |
|
|
530
|
-
|-----|-----|
|
|
531
|
-
| `npmdocker` command | `tsdocker` command |
|
|
532
|
-
| `"npmdocker"` config key | `"@git.zone/tsdocker"` config key |
|
|
533
|
-
| CommonJS | ESM with `.js` imports |
|
|
534
|
-
|
|
535
620
|
## License and Legal Information
|
|
536
621
|
|
|
537
622
|
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -29,7 +29,7 @@ export class RegistryCopy {
|
|
|
29
29
|
url: string,
|
|
30
30
|
options: RequestInit & { duplex?: string },
|
|
31
31
|
timeoutMs: number = 300_000,
|
|
32
|
-
maxRetries: number =
|
|
32
|
+
maxRetries: number = 6,
|
|
33
33
|
): Promise<Response> {
|
|
34
34
|
const method = (options.method || 'GET').toUpperCase();
|
|
35
35
|
let lastError: Error | null = null;
|
package/ts/interfaces/index.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Configuration interface for tsdocker
|
|
3
|
-
* Extends legacy config with new Docker build capabilities
|
|
4
3
|
*/
|
|
5
4
|
export interface ITsDockerConfig {
|
|
6
|
-
// Legacy (backward compatible)
|
|
7
|
-
baseImage: string;
|
|
8
|
-
command: string;
|
|
9
|
-
dockerSock: boolean;
|
|
10
|
-
keyValueObject: { [key: string]: any };
|
|
11
|
-
|
|
12
|
-
// New Docker build config
|
|
13
5
|
registries?: string[];
|
|
14
6
|
registryRepoMap?: { [registry: string]: string };
|
|
15
7
|
buildArgEnvMap?: { [dockerArg: string]: string };
|
package/ts/tsdocker.cli.ts
CHANGED
|
@@ -3,7 +3,6 @@ import * as paths from './tsdocker.paths.js';
|
|
|
3
3
|
|
|
4
4
|
// modules
|
|
5
5
|
import * as ConfigModule from './tsdocker.config.js';
|
|
6
|
-
import * as DockerModule from './tsdocker.docker.js';
|
|
7
6
|
|
|
8
7
|
import { logger, ora } from './tsdocker.logging.js';
|
|
9
8
|
import { TsDockerManager } from './classes.tsdockermanager.js';
|
|
@@ -14,16 +13,69 @@ import { commitinfo } from './00_commitinfo_data.js';
|
|
|
14
13
|
const tsdockerCli = new plugins.smartcli.Smartcli();
|
|
15
14
|
tsdockerCli.addVersion(commitinfo.version);
|
|
16
15
|
|
|
16
|
+
const printManPage = () => {
|
|
17
|
+
const manPage = `
|
|
18
|
+
TSDOCKER(1) User Commands TSDOCKER(1)
|
|
19
|
+
|
|
20
|
+
NAME
|
|
21
|
+
tsdocker - build, test, and push Docker images
|
|
22
|
+
|
|
23
|
+
VERSION
|
|
24
|
+
${commitinfo.version}
|
|
25
|
+
|
|
26
|
+
SYNOPSIS
|
|
27
|
+
tsdocker <command> [options]
|
|
28
|
+
|
|
29
|
+
COMMANDS
|
|
30
|
+
build [patterns...] [flags] Build Dockerfiles in dependency order
|
|
31
|
+
push [patterns...] [flags] Build and push images to registries
|
|
32
|
+
pull <registry-url> Pull images from a registry
|
|
33
|
+
test [flags] Build and run container test scripts
|
|
34
|
+
login Authenticate with configured registries
|
|
35
|
+
list List discovered Dockerfiles
|
|
36
|
+
clean [-y] [--all] Interactive Docker resource cleanup
|
|
37
|
+
|
|
38
|
+
BUILD / PUSH OPTIONS
|
|
39
|
+
--platform=<p> Target platform (e.g. linux/arm64)
|
|
40
|
+
--timeout=<s> Build timeout in seconds
|
|
41
|
+
--no-cache Rebuild without Docker layer cache
|
|
42
|
+
--cached Skip builds when Dockerfile is unchanged
|
|
43
|
+
--verbose Stream raw docker build output
|
|
44
|
+
--parallel[=<n>] Parallel builds (optional concurrency limit)
|
|
45
|
+
--context=<name> Docker context to use
|
|
46
|
+
|
|
47
|
+
PUSH-ONLY OPTIONS
|
|
48
|
+
--registry=<url> Push to a specific registry
|
|
49
|
+
--no-build Push already-built images (skip build step)
|
|
50
|
+
|
|
51
|
+
CLEAN OPTIONS
|
|
52
|
+
-y Auto-confirm all prompts
|
|
53
|
+
--all Include all images and volumes (not just dangling)
|
|
54
|
+
|
|
55
|
+
CONFIGURATION
|
|
56
|
+
Configure via npmextra.json under the "@git.zone/tsdocker" key:
|
|
57
|
+
|
|
58
|
+
registries Array of registry URLs to push to
|
|
59
|
+
registryRepoMap Map of registry URL to repo path overrides
|
|
60
|
+
buildArgEnvMap Map of Docker build-arg names to env var names
|
|
61
|
+
platforms Array of target platforms (default: ["linux/amd64"])
|
|
62
|
+
push Boolean, auto-push after build
|
|
63
|
+
testDir Directory containing test_*.sh scripts
|
|
64
|
+
|
|
65
|
+
EXAMPLES
|
|
66
|
+
tsdocker build
|
|
67
|
+
tsdocker build Dockerfile_app --platform=linux/arm64
|
|
68
|
+
tsdocker push --registry=ghcr.io
|
|
69
|
+
tsdocker test --verbose
|
|
70
|
+
tsdocker clean -y --all
|
|
71
|
+
`;
|
|
72
|
+
console.log(manPage);
|
|
73
|
+
};
|
|
74
|
+
|
|
17
75
|
export let run = () => {
|
|
18
|
-
// Default command:
|
|
19
|
-
tsdockerCli.standardCommand().subscribe(async
|
|
20
|
-
|
|
21
|
-
if (configArg.exitCode === 0) {
|
|
22
|
-
logger.log('success', 'container ended all right!');
|
|
23
|
-
} else {
|
|
24
|
-
logger.log('error', `container ended with error! Exit Code is ${configArg.exitCode}`);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
76
|
+
// Default command: print man page
|
|
77
|
+
tsdockerCli.standardCommand().subscribe(async () => {
|
|
78
|
+
printManPage();
|
|
27
79
|
});
|
|
28
80
|
|
|
29
81
|
/**
|
|
@@ -228,24 +280,6 @@ export let run = () => {
|
|
|
228
280
|
}
|
|
229
281
|
});
|
|
230
282
|
|
|
231
|
-
/**
|
|
232
|
-
* this command is executed inside docker and meant for use from outside docker
|
|
233
|
-
*/
|
|
234
|
-
tsdockerCli.addCommand('runinside').subscribe(async argvArg => {
|
|
235
|
-
logger.log('ok', 'Allright. We are now in Docker!');
|
|
236
|
-
ora.text('now trying to run your specified command');
|
|
237
|
-
const configArg = await ConfigModule.run();
|
|
238
|
-
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
239
|
-
executor: 'bash'
|
|
240
|
-
});
|
|
241
|
-
ora.stop();
|
|
242
|
-
await smartshellInstance.exec(configArg.command).then(response => {
|
|
243
|
-
if (response.exitCode !== 0) {
|
|
244
|
-
process.exit(1);
|
|
245
|
-
}
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
283
|
tsdockerCli.addCommand('clean').subscribe(async argvArg => {
|
|
250
284
|
try {
|
|
251
285
|
const autoYes = !!argvArg.y;
|
|
@@ -443,19 +477,5 @@ export let run = () => {
|
|
|
443
477
|
}
|
|
444
478
|
});
|
|
445
479
|
|
|
446
|
-
tsdockerCli.addCommand('vscode').subscribe(async argvArg => {
|
|
447
|
-
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
448
|
-
executor: 'bash'
|
|
449
|
-
});
|
|
450
|
-
logger.log('ok', `Starting vscode in cwd ${paths.cwd}`);
|
|
451
|
-
await smartshellInstance.execAndWaitForLine(
|
|
452
|
-
`docker run -p 127.0.0.1:8443:8443 -v "${
|
|
453
|
-
paths.cwd
|
|
454
|
-
}:/home/coder/project" registry.gitlab.com/hosttoday/ht-docker-vscode --allow-http --no-auth`,
|
|
455
|
-
/Connected to shared process/
|
|
456
|
-
);
|
|
457
|
-
await plugins.smartopen.openUrl('testing-vscode.git.zone:8443');
|
|
458
|
-
});
|
|
459
|
-
|
|
460
480
|
tsdockerCli.startParse();
|
|
461
481
|
};
|
package/ts/tsdocker.config.ts
CHANGED
|
@@ -1,34 +1,10 @@
|
|
|
1
1
|
import * as plugins from './tsdocker.plugins.js';
|
|
2
2
|
import * as paths from './tsdocker.paths.js';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
3
|
import type { ITsDockerConfig } from './interfaces/index.js';
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
export type IConfig = ITsDockerConfig & {
|
|
8
|
-
exitCode?: number;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
const getQenvKeyValueObject = async () => {
|
|
12
|
-
let qenvKeyValueObjectArray: { [key: string]: string | number };
|
|
13
|
-
if (fs.existsSync(plugins.path.join(paths.cwd, 'qenv.yml'))) {
|
|
14
|
-
qenvKeyValueObjectArray = new plugins.qenv.Qenv(paths.cwd, '.nogit/').keyValueObject;
|
|
15
|
-
} else {
|
|
16
|
-
qenvKeyValueObjectArray = {};
|
|
17
|
-
}
|
|
18
|
-
return qenvKeyValueObjectArray;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const buildConfig = async (qenvKeyValueObjectArg: { [key: string]: string | number }) => {
|
|
5
|
+
const buildConfig = async (): Promise<ITsDockerConfig> => {
|
|
22
6
|
const npmextra = new plugins.npmextra.Npmextra(paths.cwd);
|
|
23
|
-
const config = npmextra.dataFor<
|
|
24
|
-
// Legacy options (backward compatible)
|
|
25
|
-
baseImage: 'hosttoday/ht-docker-node:npmdocker',
|
|
26
|
-
init: 'rm -rf node_nodules/ && yarn install',
|
|
27
|
-
command: 'npmci npm test',
|
|
28
|
-
dockerSock: false,
|
|
29
|
-
keyValueObject: qenvKeyValueObjectArg,
|
|
30
|
-
|
|
31
|
-
// New Docker build options
|
|
7
|
+
const config = npmextra.dataFor<ITsDockerConfig>('@git.zone/tsdocker', {
|
|
32
8
|
registries: [],
|
|
33
9
|
registryRepoMap: {},
|
|
34
10
|
buildArgEnvMap: {},
|
|
@@ -39,7 +15,6 @@ const buildConfig = async (qenvKeyValueObjectArg: { [key: string]: string | numb
|
|
|
39
15
|
return config;
|
|
40
16
|
};
|
|
41
17
|
|
|
42
|
-
export let run = async (): Promise<
|
|
43
|
-
|
|
44
|
-
return config;
|
|
18
|
+
export let run = async (): Promise<ITsDockerConfig> => {
|
|
19
|
+
return buildConfig();
|
|
45
20
|
};
|
package/ts/tsdocker.paths.ts
CHANGED
|
@@ -11,4 +11,3 @@ export let cwd = process.cwd();
|
|
|
11
11
|
export let packageBase = plugins.path.join(__dirname, '../');
|
|
12
12
|
export let assets = plugins.path.join(packageBase, 'assets/');
|
|
13
13
|
fs.mkdirSync(assets, { recursive: true });
|
|
14
|
-
export let npmdockerFile = plugins.path.join(cwd, 'npmdocker');
|
package/ts/tsdocker.plugins.ts
CHANGED
|
@@ -3,17 +3,13 @@ import * as lik from '@push.rocks/lik';
|
|
|
3
3
|
import * as npmextra from '@push.rocks/npmextra';
|
|
4
4
|
import * as path from 'path';
|
|
5
5
|
import * as projectinfo from '@push.rocks/projectinfo';
|
|
6
|
-
import * as smartpromise from '@push.rocks/smartpromise';
|
|
7
|
-
import * as qenv from '@push.rocks/qenv';
|
|
8
6
|
import * as smartcli from '@push.rocks/smartcli';
|
|
9
7
|
import { SmartFs, SmartFsProviderNode } from '@push.rocks/smartfs';
|
|
10
8
|
import * as smartlog from '@push.rocks/smartlog';
|
|
11
9
|
import * as smartlogDestinationLocal from '@push.rocks/smartlog-destination-local';
|
|
12
10
|
import * as smartlogSouceOra from '@push.rocks/smartlog-source-ora';
|
|
13
|
-
import * as smartopen from '@push.rocks/smartopen';
|
|
14
11
|
import * as smartinteract from '@push.rocks/smartinteract';
|
|
15
12
|
import * as smartshell from '@push.rocks/smartshell';
|
|
16
|
-
import * as smartstring from '@push.rocks/smartstring';
|
|
17
13
|
|
|
18
14
|
// Create smartfs instance
|
|
19
15
|
export const smartfs = new SmartFs(new SmartFsProviderNode());
|
|
@@ -23,14 +19,10 @@ export {
|
|
|
23
19
|
npmextra,
|
|
24
20
|
path,
|
|
25
21
|
projectinfo,
|
|
26
|
-
smartpromise,
|
|
27
|
-
qenv,
|
|
28
22
|
smartcli,
|
|
29
23
|
smartinteract,
|
|
30
24
|
smartlog,
|
|
31
25
|
smartlogDestinationLocal,
|
|
32
26
|
smartlogSouceOra,
|
|
33
|
-
smartopen,
|
|
34
27
|
smartshell,
|
|
35
|
-
smartstring
|
|
36
28
|
};
|
package/assets/Dockerfile
DELETED