MCPcopy Index your code
hub / github.com/devcontainers/cli / buildAndExtendImage

Function buildAndExtendImage

src/spec-node/singleContainer.ts:124–273  ·  view source on GitHub ↗
(buildParams: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig>, baseImageNames: string[], noCache: boolean, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>)

Source from the content-addressed store, hash-verified

122}
123
124async function buildAndExtendImage(buildParams: DockerResolverParameters, configWithRaw: SubstitutedConfig<DevContainerFromDockerfileConfig>, baseImageNames: string[], noCache: boolean, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>) {
125 const { cliHost, output } = buildParams.common;
126 const { config } = configWithRaw;
127 const dockerfileUri = getDockerfilePath(cliHost, config);
128 const dockerfilePath = await uriToWSLFsPath(dockerfileUri, cliHost);
129 if (!cliHost.isFile(dockerfilePath)) {
130 throw new ContainerError({ description: `Dockerfile (${dockerfilePath}) not found.` });
131 }
132
133 let dockerfile = (await cliHost.readFile(dockerfilePath)).toString();
134 const originalDockerfile = dockerfile;
135 let baseName = 'dev_container_auto_added_stage_label';
136 if (config.build?.target) {
137 // Explictly set build target for the dev container build features on that
138 baseName = config.build.target;
139 } else {
140 // Use the last stage in the Dockerfile
141 // Find the last line that starts with "FROM" (possibly preceeded by white-space)
142 const { lastStageName, modifiedDockerfile } = ensureDockerfileHasFinalStageName(dockerfile, baseName);
143 baseName = lastStageName;
144 if (modifiedDockerfile) {
145 dockerfile = modifiedDockerfile;
146 }
147 }
148
149 const imageBuildInfo = await getImageBuildInfoFromDockerfile(buildParams, originalDockerfile, config.build?.args || {}, config.build?.target, configWithRaw.substitute);
150 const extendImageBuildInfo = await getExtendImageBuildInfo(buildParams, configWithRaw, baseName, imageBuildInfo, undefined, additionalFeatures, false);
151
152 let finalDockerfilePath = dockerfilePath;
153 const additionalBuildArgs: string[] = [];
154 if (extendImageBuildInfo?.featureBuildInfo) {
155 const { featureBuildInfo } = extendImageBuildInfo;
156 // We add a '# syntax' line at the start, so strip out any existing line
157 const syntaxMatch = dockerfile.match(/^\s*#\s*syntax\s*=.*[\r\n]/g);
158 if (syntaxMatch) {
159 dockerfile = dockerfile.slice(syntaxMatch[0].length);
160 }
161 let finalDockerfileContent = `${featureBuildInfo.dockerfilePrefixContent}${dockerfile}\n${featureBuildInfo.dockerfileContent}`;
162 finalDockerfilePath = cliHost.path.join(featureBuildInfo?.dstFolder, 'Dockerfile-with-features');
163 await cliHost.writeFile(finalDockerfilePath, Buffer.from(finalDockerfileContent));
164
165 // track additional build args to include below
166 for (const buildContext in featureBuildInfo.buildKitContexts) {
167 additionalBuildArgs.push('--build-context', `${buildContext}=${featureBuildInfo.buildKitContexts[buildContext]}`);
168 }
169 for (const buildArg in featureBuildInfo.buildArgs) {
170 additionalBuildArgs.push('--build-arg', `${buildArg}=${featureBuildInfo.buildArgs[buildArg]}`);
171 }
172
173 for (const securityOpt of featureBuildInfo.securityOpts) {
174 additionalBuildArgs.push('--security-opt', securityOpt);
175 }
176 }
177
178 const args: string[] = [];
179 if (!buildParams.buildKitVersion &&
180 (buildParams.buildxPlatform || buildParams.buildxPush)) {
181 throw new ContainerError({ description: '--platform or --push require BuildKit enabled.', data: { fileWithError: dockerfilePath } });

Callers 1

buildNamedImageAndExtendFunction · 0.85

Calls 15

uriToWSLFsPathFunction · 0.90
getExtendImageBuildInfoFunction · 0.90
isBuildxCacheToInlineFunction · 0.90
logUMaskFunction · 0.90
getDockerContextPathFunction · 0.90
toPtyExecParametersFunction · 0.90
makeLogFunction · 0.90
dockerPtyCLIFunction · 0.90
toExecParametersFunction · 0.90
dockerCLIFunction · 0.90

Tested by

no test coverage detected