Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions lib/docker-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
isFileNotFoundError,
parseDockerHost,
} from './util.js';
import type { SecureContextOptions } from 'tls';

export interface Credentials {
username: string;
Expand All @@ -40,12 +41,12 @@ export class DockerClient {
/**
* Create a DockerClient instance from a Docker host string
* @param dockerHost Docker host string (e.g., "unix:/var/run/docker.sock", "tcp://localhost:2376", or "ssh://user@host[:port][/path/to/docker.sock]")
* @param certPath Optional path to directory containing TLS certificates (ca.pem, cert.pem, key.pem) for TCP connections
* @param certificates Optional path to directory containing TLS certificates (ca.pem, cert.pem, key.pem) for TCP connections
* @returns Promise that resolves to a connected DockerClient instance
*/
static fromDockerHost(
dockerHost: string,
certPath?: string,
certificates?: string | SecureContextOptions,
): Promise<DockerClient> {
return new Promise((resolve, reject) => {
if (dockerHost.startsWith('unix:')) {
Expand All @@ -66,18 +67,26 @@ export class DockerClient {
}
} else if (dockerHost.startsWith('tcp:')) {
// TCP connection - use SocketAgent with TCP socket creation function
const defaultPort = certPath ? 2376 : 2375; // Default ports: 2376 for TLS, 2375 for plain
const defaultPort = certificates ? 2376 : 2375; // Default ports: 2376 for TLS, 2375 for plain
const { host, port } = parseDockerHost(dockerHost, defaultPort);

try {
let agent: SocketAgent;

if (certPath) {
// Use SocketAgent with TLS socket creation function
const tlsOptions = TLS.loadCertificates(certPath);
agent = new SocketAgent(() =>
tls.connect({ host, port, ...tlsOptions }),
);
if (certificates) {
if (typeof certificates === 'string') {
// Use SocketAgent with TLS socket creation function
const tlsOptions =
TLS.loadCertificates(certificates);
agent = new SocketAgent(() =>
tls.connect({ host, port, ...tlsOptions }),
);
} else {
// certificates is a SecureContextOptions type
agent = new SocketAgent(() =>
tls.connect({ host, port, ...certificates }),
);
}
} else {
// Use SocketAgent with plain TCP socket creation function
agent = new SocketAgent(() =>
Expand Down Expand Up @@ -345,7 +354,7 @@ export class DockerClient {
public async containerArchive(
id: string,
path: string,
out: NodeJS.WritableStream,
out: stream.Writable,
): Promise<void> {
return this.api.get<void>(
`/containers/${id}/archive`,
Expand Down Expand Up @@ -796,7 +805,7 @@ export class DockerClient {
public async putContainerArchive(
id: string,
path: string,
tar: NodeJS.ReadableStream,
tar: stream.Readable,
options?: {
noOverwriteDirNonDir?: string;
copyUIDGID?: string;
Expand Down
9 changes: 3 additions & 6 deletions lib/tls.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as fs from 'fs';
import * as path from 'path';
import { getErrorMessage } from './util.js';
import type { SecureContextOptions } from 'tls';

/**
* TLS certificate utilities for secure Docker connections
Expand All @@ -11,12 +12,8 @@ export class TLS {
* @param certPath Path to directory containing ca.pem, cert.pem, and key.pem files
* @returns TLS options object for HTTPS agent
*/
static loadCertificates(certPath: string): {
ca?: Buffer;
cert?: Buffer;
key?: Buffer;
} {
const tlsOptions: { ca?: Buffer; cert?: Buffer; key?: Buffer } = {};
static loadCertificates(certPath: string): SecureContextOptions {
const tlsOptions: SecureContextOptions = {};

try {
// Load CA certificate
Expand Down