Juergen Kunz 8f0514d10e
Some checks failed
Default (tags) / security (push) Successful in 30s
Default (tags) / test (push) Failing after 4m14s
Default (tags) / release (push) Has been skipped
Default (tags) / metadata (push) Has been skipped
v1.17.4
2026-02-07 12:59:31 +00:00
2026-02-07 12:59:31 +00:00
2026-02-07 12:59:31 +00:00
2017-10-13 17:50:31 +02:00
2026-02-07 12:59:31 +00:00

@git.zone/tsdocker

🐳 The ultimate Docker development toolkit for TypeScript projects — build, test, and ship multi-arch containerized applications with zero friction.

Issue Reporting and Security

For reporting bugs, issues, or security vulnerabilities, please visit community.foss.global/. This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a code.foss.global/ account to submit Pull Requests directly.

What is tsdocker?

tsdocker is a comprehensive Docker development and build tool that handles everything from testing npm packages in clean environments to building and pushing multi-architecture Docker images across multiple registries — all from a single CLI.

🎯 Key Capabilities

  • 🧪 Containerized Testing — Run your tests in pristine Docker environments
  • 🏗️ Smart Docker Builds — Automatically discover, sort, and build Dockerfiles by dependency
  • 🌍 True Multi-Architecture — Build for amd64 and arm64 simultaneously with Docker Buildx
  • 🚀 Multi-Registry Push — Ship to Docker Hub, GitLab, GitHub Container Registry, and more via OCI Distribution API
  • Parallel Builds — Level-based parallel builds with configurable concurrency
  • 🗄️ Persistent Local Registry — All images flow through a local OCI registry with persistent storage
  • 📦 Build Caching — Skip unchanged Dockerfiles with content-hash caching
  • 🔧 Zero Config Start — Works out of the box, scales with your needs

Installation

# Global installation (recommended for CLI usage)
npm install -g @git.zone/tsdocker

# Or project-local installation
pnpm install --save-dev @git.zone/tsdocker

Quick Start

🧪 Run Tests in Docker

The simplest use case — run your tests in a clean container:

tsdocker

This pulls your configured base image, mounts your project, and executes your test command in isolation.

🏗️ Build Docker Images

Got Dockerfile files? Build them all with automatic dependency ordering:

tsdocker build

tsdocker will:

  1. 🔍 Discover all Dockerfile* files in your project
  2. 📊 Analyze FROM dependencies between them
  3. 🔄 Sort them topologically
  4. 🏗️ Build each image in the correct order
  5. 📦 Push every image to a persistent local registry (.nogit/docker-registry/)

📤 Push to Registries

Ship your images to one or all configured registries:

# Push to all configured registries
tsdocker push

# Push to a specific registry
tsdocker push --registry=registry.gitlab.com

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.

CLI Commands

Command Description
tsdocker Run tests in a fresh Docker container (legacy mode)
tsdocker build Build all Dockerfiles with dependency ordering
tsdocker push Build + push images to configured registries
tsdocker pull <registry> Pull images from a specific registry
tsdocker test Build + run container test scripts (test_*.sh)
tsdocker login Authenticate with configured registries
tsdocker list Display discovered Dockerfiles and their dependencies
tsdocker clean Interactively clean Docker environment
tsdocker vscode Launch containerized VS Code in browser

Build Flags

Flag Description
--platform=linux/arm64 Override build platform for a single architecture
--timeout=600 Build timeout in seconds
--no-cache Force rebuild without Docker layer cache
--cached Skip unchanged Dockerfiles (content-hash based)
--verbose Stream raw docker build output
--parallel Enable level-based parallel builds (default concurrency: 4)
--parallel=8 Parallel builds with custom concurrency
--context=mycontext Use a specific Docker context

Clean Flags

Flag Description
--all Include all images and volumes (not just dangling)
-y Auto-confirm all prompts

Configuration

Configure tsdocker in your package.json or npmextra.json under the @git.zone/tsdocker key:

{
  "@git.zone/tsdocker": {
    "registries": ["registry.gitlab.com", "docker.io"],
    "registryRepoMap": {
      "registry.gitlab.com": "myorg/myproject"
    },
    "buildArgEnvMap": {
      "NODE_VERSION": "NODE_VERSION"
    },
    "platforms": ["linux/amd64", "linux/arm64"],
    "testDir": "./test"
  }
}

Configuration Options

Build & Push Options

Option Type Default Description
registries string[] [] Registry URLs to push to
registryRepoMap object {} Map registries to different repository paths
buildArgEnvMap object {} Map Docker build ARGs to environment variables
platforms string[] ["linux/amd64"] Target architectures for multi-arch builds
testDir string ./test Directory containing test scripts

Legacy Testing Options

These options configure the tsdocker default command (containerized test runner):

Option Type Default Description
baseImage string hosttoday/ht-docker-node:npmdocker Docker image for test environment
command string npmci npm test Command to run inside the container
dockerSock boolean false Mount Docker socket for DinD scenarios

Architecture: How tsdocker Works

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.

📐 Build Flow

┌─────────────────────────────────────────────────┐
│  tsdocker build                                 │
│                                                 │
│  1. Start local registry (localhost:5234)        │
│     └── Persistent volume: .nogit/docker-registry/
│                                                 │
│  2. For each Dockerfile (topological order):     │
│     ├── Multi-platform: buildx --push → registry │
│     └── Single-platform: docker build → registry │
│                                                 │
│  3. Stop local registry (data persists on disk)  │
└─────────────────────────────────────────────────┘

📤 Push Flow

┌──────────────────────────────────────────────────┐
│  tsdocker push                                   │
│                                                  │
│  1. Start local registry (loads persisted data)   │
│                                                  │
│  2. For each image × each remote registry:        │
│     └── OCI Distribution API copy:               │
│         ├── Fetch manifest (single or multi-arch) │
│         ├── Copy blobs (skip if already exist)    │
│         └── Push manifest with destination tag    │
│                                                  │
│  3. Stop local registry                          │
└──────────────────────────────────────────────────┘

🔑 Why a Local Registry?

Problem Solution
docker buildx --load fails for multi-arch images buildx --push to local registry works for any number of platforms
docker push only pushes single-platform manifests OCI API copy preserves full manifest lists (multi-arch)
Images lost between build and push phases Persistent storage at .nogit/docker-registry/ survives restarts
Redundant blob uploads on incremental pushes HEAD checks skip blobs that already exist on the remote

Registry Authentication

Environment Variables

# Pipe-delimited format (supports DOCKER_REGISTRY_1 through DOCKER_REGISTRY_10)
export DOCKER_REGISTRY_1="registry.gitlab.com|username|password"
export DOCKER_REGISTRY_2="docker.io|username|password"

# Individual registry format
export DOCKER_REGISTRY_URL="registry.gitlab.com"
export DOCKER_REGISTRY_USER="username"
export DOCKER_REGISTRY_PASSWORD="password"

Docker Config Fallback

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.

Login Command

tsdocker login

Authenticates with all configured registries using the provided environment variables.

Advanced Usage

🔀 Multi-Architecture Builds

Build for multiple platforms using Docker Buildx:

{
  "@git.zone/tsdocker": {
    "platforms": ["linux/amd64", "linux/arm64"]
  }
}

tsdocker automatically:

  • Sets up a Buildx builder with --driver-opt network=host (so buildx can reach the local registry)
  • Pushes multi-platform images to the local registry via buildx --push
  • Copies the full manifest list (including all platform variants) to remote registries on tsdocker push

Parallel Builds

Speed up builds by building independent images concurrently:

# Default concurrency (4 workers)
tsdocker build --parallel

# Custom concurrency
tsdocker build --parallel=8

# Works with caching too
tsdocker build --parallel --cached

tsdocker groups Dockerfiles into dependency levels using topological analysis. Images within the same level have no dependencies on each other and build in parallel. Each level completes before the next begins.

📦 Dockerfile Naming Conventions

tsdocker discovers files matching Dockerfile*:

File Name Version Tag
Dockerfile latest
Dockerfile_v1.0.0 v1.0.0
Dockerfile_alpine alpine
Dockerfile_##version## Uses package.json version

🔗 Dependency-Aware Builds

If you have multiple Dockerfiles that depend on each other:

# Dockerfile_base
FROM node:20-alpine
RUN npm install -g typescript

# Dockerfile_app
FROM myproject:base
COPY . .
RUN npm run build

tsdocker automatically detects that Dockerfile_app depends on Dockerfile_base, builds them in the correct order, and makes the base image available to dependent builds via the local registry (using --build-context for buildx).

🧪 Container Test Scripts

Create test scripts in your test directory:

# test/test_latest.sh
#!/bin/bash
node --version
npm --version
echo "Container tests passed!"

Run with:

tsdocker test

This builds all images, starts the local registry (so multi-arch images can be pulled), and runs each matching test script inside a container.

🔧 Build Args from Environment

Pass environment variables as Docker build arguments:

{
  "@git.zone/tsdocker": {
    "buildArgEnvMap": {
      "NPM_TOKEN": "NPM_TOKEN",
      "NODE_VERSION": "NODE_VERSION"
    }
  }
}
ARG NPM_TOKEN
ARG NODE_VERSION=20
FROM node:${NODE_VERSION}
RUN echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > ~/.npmrc

🗺️ Registry Repo Mapping

Use different repository names for different registries:

{
  "@git.zone/tsdocker": {
    "registries": ["registry.gitlab.com", "docker.io"],
    "registryRepoMap": {
      "registry.gitlab.com": "mygroup/myproject",
      "docker.io": "myuser/myproject"
    }
  }
}

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.

🐳 Docker-in-Docker Testing

Test Docker-related tools by mounting the Docker socket:

{
  "@git.zone/tsdocker": {
    "baseImage": "docker:latest",
    "command": "docker version && docker ps",
    "dockerSock": true
  }
}

📋 Listing Dockerfiles

Inspect your project's Dockerfiles and their relationships:

tsdocker list

Output:

Discovered Dockerfiles:
========================

1. /path/to/Dockerfile_base
   Tag: myproject:base
   Base Image: node:20-alpine
   Version: base

2. /path/to/Dockerfile_app
   Tag: myproject:app
   Base Image: myproject:base
   Version: app
   Depends on: myproject:base

Examples

Minimal Build & Push

{
  "@git.zone/tsdocker": {
    "registries": ["docker.io"],
    "platforms": ["linux/amd64"]
  }
}
tsdocker push

Full Production Setup

{
  "@git.zone/tsdocker": {
    "registries": ["registry.gitlab.com", "ghcr.io", "docker.io"],
    "registryRepoMap": {
      "registry.gitlab.com": "myorg/myapp",
      "ghcr.io": "myorg/myapp",
      "docker.io": "myuser/myapp"
    },
    "buildArgEnvMap": {
      "NPM_TOKEN": "NPM_TOKEN"
    },
    "platforms": ["linux/amd64", "linux/arm64"],
    "testDir": "./docker-tests"
  }
}

CI/CD Integration

GitLab CI:

build-and-push:
  stage: build
  script:
    - npm install -g @git.zone/tsdocker
    - tsdocker push
  variables:
    DOCKER_REGISTRY_1: "registry.gitlab.com|$CI_REGISTRY_USER|$CI_REGISTRY_PASSWORD"

GitHub Actions:

- name: Build and Push
  run: |
    npm install -g @git.zone/tsdocker
    tsdocker login
    tsdocker push
  env:
    DOCKER_REGISTRY_1: "ghcr.io|${{ github.actor }}|${{ secrets.GITHUB_TOKEN }}"

TypeScript API

tsdocker can also be used programmatically:

import { TsDockerManager } from '@git.zone/tsdocker/dist_ts/classes.tsdockermanager.js';
import type { ITsDockerConfig } from '@git.zone/tsdocker/dist_ts/interfaces/index.js';

const config: ITsDockerConfig = {
  baseImage: 'node:20',
  command: 'npm test',
  dockerSock: false,
  keyValueObject: {},
  registries: ['docker.io'],
  platforms: ['linux/amd64', 'linux/arm64'],
};

const manager = new TsDockerManager(config);
await manager.prepare();
await manager.build({ parallel: true });
await manager.push();

Requirements

  • Docker — Docker Engine 20+ or Docker Desktop
  • Node.js — Version 18 or higher (for native fetch and ESM support)
  • Docker Buildx — Required for multi-architecture builds (included in Docker Desktop)

Troubleshooting

"docker not found"

Ensure Docker is installed and in your PATH:

docker --version

Multi-arch build fails

Make sure Docker Buildx is available. tsdocker will set up the builder automatically, but you can verify:

docker buildx version

Registry authentication fails

Check your environment variables are set correctly:

echo $DOCKER_REGISTRY_1
tsdocker login

tsdocker also falls back to ~/.docker/config.json — ensure you've run docker login for your target registries.

Circular dependency detected

Review your Dockerfiles' FROM statements — you have images depending on each other in a loop.

Build context too large

Use a .dockerignore file to exclude node_modules, .git, .nogit, and other large directories:

node_modules
.git
.nogit
dist_ts

Migration from Legacy

Previously published as npmdocker, now @git.zone/tsdocker:

Old New
npmdocker command tsdocker command
"npmdocker" config key "@git.zone/tsdocker" config key
CommonJS ESM with .js imports

This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the LICENSE file.

Please note: The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

Trademarks

This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.

Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.

Company Information

Task Venture Capital GmbH Registered at District Court Bremen HRB 35230 HB, Germany

For any legal inquiries or further information, please contact us via email at hello@task.vc.

By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.

Description
No description provided
Readme 744 KiB
Languages
TypeScript 99.7%
Dockerfile 0.2%