From bd25ad7bd317fceb5f5c42611b47ad23f195a5ca Mon Sep 17 00:00:00 2001 From: MunsMan Date: Wed, 1 Mar 2023 17:58:34 +0000 Subject: [PATCH 1/6] adding 'static' port forwarding support - agilgur5 modification: rebased with `main` --- src/spec-node/containerNetwork.ts | 24 ++++++++++++++++++++++++ src/spec-node/singleContainer.ts | 7 +++---- 2 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/spec-node/containerNetwork.ts diff --git a/src/spec-node/containerNetwork.ts b/src/spec-node/containerNetwork.ts new file mode 100644 index 000000000..6d1173dff --- /dev/null +++ b/src/spec-node/containerNetwork.ts @@ -0,0 +1,24 @@ +import { DevContainerConfig, DevContainerFromDockerfileConfig, DevContainerFromImageConfig } from '../spec-configuration/configuration'; + +function getStaticPorts (ports: number | string | (number | string)[] | undefined): string[]{ + ports = ports ?? []; + ports = typeof ports === 'number' || typeof ports === 'string'? [ports] : ports; + return ports.map((port) => typeof port === 'number'? `127.0.0.1:${port}:${port}`: port); +} + +function appPorts (config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[]{ + return getStaticPorts(config.appPort); +} + +function hasAppPorts(obj: unknown):obj is (DevContainerFromDockerfileConfig | DevContainerFromImageConfig) { + return (obj as DevContainerFromDockerfileConfig | DevContainerFromImageConfig).appPort !== undefined; +} +export function applyStaticPorts (config: DevContainerConfig): string[] { + let staticPorts: string[] = []; + staticPorts = staticPorts.concat(...getStaticPorts(config.forwardPorts)); + if(hasAppPorts(config)){ + staticPorts = staticPorts.concat(...appPorts(config)); + } + return ([]).concat(...staticPorts.map((port) => ['-p', port])); +} + diff --git a/src/spec-node/singleContainer.ts b/src/spec-node/singleContainer.ts index 6a8bfa3af..64ffe37b5 100644 --- a/src/spec-node/singleContainer.ts +++ b/src/spec-node/singleContainer.ts @@ -13,6 +13,7 @@ import { LogLevel, Log, makeLog } from '../spec-utils/log'; import { extendImage, getExtendImageBuildInfo, updateRemoteUserUID } from './containerFeatures'; import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageMetadataFromContainer, ImageMetadataEntry, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata'; import { ensureDockerfileHasFinalStageName, generateMountCommand } from './dockerfileUtils'; +import { applyStaticPorts } from './containerNetwork'; export const hostFolderLabel = 'devcontainer.local_folder'; // used to label containers created from a workspace/folder export const configFileLabel = 'devcontainer.config_file'; @@ -196,7 +197,7 @@ async function buildAndExtendImage(buildParams: DockerResolverParameters, config if (buildParams.buildxPush) { args.push('--push'); } else { - if (buildParams.buildxOutput) { + if (buildParams.buildxOutput) { args.push('--output', buildParams.buildxOutput); } else { args.push('--load'); // (short for --output=docker, i.e. load into normal 'docker images' collection) @@ -348,9 +349,7 @@ export async function spawnDevContainer(params: DockerResolverParameters, config const { common } = params; common.progress(ResolverProgress.StartingContainer); - const appPort = config.appPort; - const exposedPorts = typeof appPort === 'number' || typeof appPort === 'string' ? [appPort] : appPort || []; - const exposed = ([]).concat(...exposedPorts.map(port => ['-p', typeof port === 'number' ? `127.0.0.1:${port}:${port}` : port])); + const exposed = applyStaticPorts(config); const cwdMount = workspaceMount ? ['--mount', workspaceMount] : []; From 99afaec0ae60aaf3c73f573a7602822eae044b25 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Mon, 15 Jul 2024 23:24:09 -0400 Subject: [PATCH 2/6] rename file to `ports.ts` - it doesn't cover all networking at this time Signed-off-by: Anton Gilgur --- src/spec-node/{containerNetwork.ts => ports.ts} | 0 src/spec-node/singleContainer.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/spec-node/{containerNetwork.ts => ports.ts} (100%) diff --git a/src/spec-node/containerNetwork.ts b/src/spec-node/ports.ts similarity index 100% rename from src/spec-node/containerNetwork.ts rename to src/spec-node/ports.ts diff --git a/src/spec-node/singleContainer.ts b/src/spec-node/singleContainer.ts index 64ffe37b5..7ff1120f0 100644 --- a/src/spec-node/singleContainer.ts +++ b/src/spec-node/singleContainer.ts @@ -13,7 +13,7 @@ import { LogLevel, Log, makeLog } from '../spec-utils/log'; import { extendImage, getExtendImageBuildInfo, updateRemoteUserUID } from './containerFeatures'; import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageMetadataFromContainer, ImageMetadataEntry, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata'; import { ensureDockerfileHasFinalStageName, generateMountCommand } from './dockerfileUtils'; -import { applyStaticPorts } from './containerNetwork'; +import { applyStaticPorts } from './ports'; export const hostFolderLabel = 'devcontainer.local_folder'; // used to label containers created from a workspace/folder export const configFileLabel = 'devcontainer.config_file'; From 04fd20043fb4a29649d48b80a35317790fd95ef9 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Mon, 15 Jul 2024 23:36:13 -0400 Subject: [PATCH 3/6] simplify and fix naming and style Signed-off-by: Anton Gilgur --- src/spec-node/ports.ts | 23 ++++++----------------- src/spec-node/singleContainer.ts | 4 ++-- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/src/spec-node/ports.ts b/src/spec-node/ports.ts index 6d1173dff..d1496e25b 100644 --- a/src/spec-node/ports.ts +++ b/src/spec-node/ports.ts @@ -1,24 +1,13 @@ -import { DevContainerConfig, DevContainerFromDockerfileConfig, DevContainerFromImageConfig } from '../spec-configuration/configuration'; +import { DevContainerFromDockerfileConfig, DevContainerFromImageConfig } from '../spec-configuration/configuration'; -function getStaticPorts (ports: number | string | (number | string)[] | undefined): string[]{ +function normalizePorts(ports: number | string | (number | string)[] | undefined): string[]{ ports = ports ?? []; ports = typeof ports === 'number' || typeof ports === 'string'? [ports] : ports; - return ports.map((port) => typeof port === 'number'? `127.0.0.1:${port}:${port}`: port); + return ports.map((port) => typeof port === 'number' ? `127.0.0.1:${port}:${port}`: port); } -function appPorts (config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[]{ - return getStaticPorts(config.appPort); -} - -function hasAppPorts(obj: unknown):obj is (DevContainerFromDockerfileConfig | DevContainerFromImageConfig) { - return (obj as DevContainerFromDockerfileConfig | DevContainerFromImageConfig).appPort !== undefined; -} -export function applyStaticPorts (config: DevContainerConfig): string[] { - let staticPorts: string[] = []; - staticPorts = staticPorts.concat(...getStaticPorts(config.forwardPorts)); - if(hasAppPorts(config)){ - staticPorts = staticPorts.concat(...appPorts(config)); - } - return ([]).concat(...staticPorts.map((port) => ['-p', port])); +export function getStaticPorts(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[] { + const staticPorts = normalizePorts(config.forwardPorts).concat(normalizePorts(config.appPort)); + return staticPorts.flatMap((port) => ['-p', port]); } diff --git a/src/spec-node/singleContainer.ts b/src/spec-node/singleContainer.ts index 7ff1120f0..1e33a476d 100644 --- a/src/spec-node/singleContainer.ts +++ b/src/spec-node/singleContainer.ts @@ -13,7 +13,7 @@ import { LogLevel, Log, makeLog } from '../spec-utils/log'; import { extendImage, getExtendImageBuildInfo, updateRemoteUserUID } from './containerFeatures'; import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageMetadataFromContainer, ImageMetadataEntry, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata'; import { ensureDockerfileHasFinalStageName, generateMountCommand } from './dockerfileUtils'; -import { applyStaticPorts } from './ports'; +import { getStaticPorts } from './ports'; export const hostFolderLabel = 'devcontainer.local_folder'; // used to label containers created from a workspace/folder export const configFileLabel = 'devcontainer.config_file'; @@ -349,7 +349,7 @@ export async function spawnDevContainer(params: DockerResolverParameters, config const { common } = params; common.progress(ResolverProgress.StartingContainer); - const exposed = applyStaticPorts(config); + const exposed = getStaticPorts(config); const cwdMount = workspaceMount ? ['--mount', workspaceMount] : []; From 63f6f36afc21490829542eaaa9c22ba366a64b43 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Mon, 15 Jul 2024 23:40:00 -0400 Subject: [PATCH 4/6] remove second trailing newline Signed-off-by: Anton Gilgur --- src/spec-node/ports.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/spec-node/ports.ts b/src/spec-node/ports.ts index d1496e25b..bdc1d061e 100644 --- a/src/spec-node/ports.ts +++ b/src/spec-node/ports.ts @@ -10,4 +10,3 @@ export function getStaticPorts(config: DevContainerFromDockerfileConfig | DevCon const staticPorts = normalizePorts(config.forwardPorts).concat(normalizePorts(config.appPort)); return staticPorts.flatMap((port) => ['-p', port]); } - From 5356a4dd20e38fa3f65d5efddc95384ccb465a75 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Mon, 15 Jul 2024 23:44:05 -0400 Subject: [PATCH 5/6] more style fixes and naming Signed-off-by: Anton Gilgur --- src/spec-node/ports.ts | 6 +++--- src/spec-node/singleContainer.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/spec-node/ports.ts b/src/spec-node/ports.ts index bdc1d061e..f6b6defca 100644 --- a/src/spec-node/ports.ts +++ b/src/spec-node/ports.ts @@ -1,12 +1,12 @@ import { DevContainerFromDockerfileConfig, DevContainerFromImageConfig } from '../spec-configuration/configuration'; -function normalizePorts(ports: number | string | (number | string)[] | undefined): string[]{ +function normalizePorts(ports: number | string | (number | string)[] | undefined): string[] { ports = ports ?? []; - ports = typeof ports === 'number' || typeof ports === 'string'? [ports] : ports; + ports = typeof ports === 'number' || typeof ports === 'string' ? [ports] : ports; return ports.map((port) => typeof port === 'number' ? `127.0.0.1:${port}:${port}`: port); } -export function getStaticPorts(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[] { +export function getStaticPortsArgs(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[] { const staticPorts = normalizePorts(config.forwardPorts).concat(normalizePorts(config.appPort)); return staticPorts.flatMap((port) => ['-p', port]); } diff --git a/src/spec-node/singleContainer.ts b/src/spec-node/singleContainer.ts index 1e33a476d..51f875399 100644 --- a/src/spec-node/singleContainer.ts +++ b/src/spec-node/singleContainer.ts @@ -13,7 +13,7 @@ import { LogLevel, Log, makeLog } from '../spec-utils/log'; import { extendImage, getExtendImageBuildInfo, updateRemoteUserUID } from './containerFeatures'; import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageMetadataFromContainer, ImageMetadataEntry, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata'; import { ensureDockerfileHasFinalStageName, generateMountCommand } from './dockerfileUtils'; -import { getStaticPorts } from './ports'; +import { getStaticPortsArgs } from './ports'; export const hostFolderLabel = 'devcontainer.local_folder'; // used to label containers created from a workspace/folder export const configFileLabel = 'devcontainer.config_file'; @@ -349,7 +349,7 @@ export async function spawnDevContainer(params: DockerResolverParameters, config const { common } = params; common.progress(ResolverProgress.StartingContainer); - const exposed = getStaticPorts(config); + const exposed = getStaticPortsArgs(config); const cwdMount = workspaceMount ? ['--mount', workspaceMount] : []; From a8b9491fb2e8296e589f5438bbee2a5ca63a9647 Mon Sep 17 00:00:00 2001 From: Anton Gilgur Date: Mon, 15 Jul 2024 23:53:13 -0400 Subject: [PATCH 6/6] more cleanly separate out getting ports from converting them into flags Signed-off-by: Anton Gilgur --- src/spec-node/ports.ts | 5 ++--- src/spec-node/singleContainer.ts | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/spec-node/ports.ts b/src/spec-node/ports.ts index f6b6defca..3cc0f2470 100644 --- a/src/spec-node/ports.ts +++ b/src/spec-node/ports.ts @@ -6,7 +6,6 @@ function normalizePorts(ports: number | string | (number | string)[] | undefined return ports.map((port) => typeof port === 'number' ? `127.0.0.1:${port}:${port}`: port); } -export function getStaticPortsArgs(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[] { - const staticPorts = normalizePorts(config.forwardPorts).concat(normalizePorts(config.appPort)); - return staticPorts.flatMap((port) => ['-p', port]); +export function getStaticPorts(config: DevContainerFromDockerfileConfig | DevContainerFromImageConfig): string[] { + return normalizePorts(config.forwardPorts).concat(normalizePorts(config.appPort)); } diff --git a/src/spec-node/singleContainer.ts b/src/spec-node/singleContainer.ts index 51f875399..a63ba1237 100644 --- a/src/spec-node/singleContainer.ts +++ b/src/spec-node/singleContainer.ts @@ -13,7 +13,7 @@ import { LogLevel, Log, makeLog } from '../spec-utils/log'; import { extendImage, getExtendImageBuildInfo, updateRemoteUserUID } from './containerFeatures'; import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageMetadataFromContainer, ImageMetadataEntry, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata'; import { ensureDockerfileHasFinalStageName, generateMountCommand } from './dockerfileUtils'; -import { getStaticPortsArgs } from './ports'; +import { getStaticPorts } from './ports'; export const hostFolderLabel = 'devcontainer.local_folder'; // used to label containers created from a workspace/folder export const configFileLabel = 'devcontainer.config_file'; @@ -349,7 +349,8 @@ export async function spawnDevContainer(params: DockerResolverParameters, config const { common } = params; common.progress(ResolverProgress.StartingContainer); - const exposed = getStaticPortsArgs(config); + const exposedPorts = getStaticPorts(config); + const exposed = exposedPorts.flatMap((port) => ['-p', port]); const cwdMount = workspaceMount ? ['--mount', workspaceMount] : [];