Skip to content

Commit 4316f52

Browse files
committed
Dockerfile preprocessing
1 parent 805196f commit 4316f52

22 files changed

Lines changed: 620 additions & 52 deletions

src/spec-common/cliHost.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import * as path from 'path';
77
import * as net from 'net';
88
import * as os from 'os';
99

10-
import { readLocalFile, writeLocalFile, mkdirpLocal, isLocalFile, renameLocal, readLocalDir, isLocalFolder } from '../spec-utils/pfs';
10+
import { readLocalFile, writeLocalFile, mkdirpLocal, isLocalFile, renameLocal, readLocalDir, isLocalFolder, unlinkLocal } from '../spec-utils/pfs';
1111
import { URI } from 'vscode-uri';
1212
import { ExecFunction, getLocalUsername, plainExec, plainPtyExec, PtyExecFunction } from './commonUtils';
1313
import { Abort, Duplex, Sink, Source, SourceCallback } from 'pull-stream';
@@ -32,6 +32,7 @@ export interface CLIHost {
3232
isFolder(filepath: string): Promise<boolean>;
3333
readFile(filepath: string): Promise<Buffer>;
3434
writeFile(filepath: string, content: Buffer): Promise<void>;
35+
deleteFile?(filepath: string): Promise<void>;
3536
rename(oldPath: string, newPath: string): Promise<void>;
3637
mkdirp(dirpath: string): Promise<void>;
3738
readDir(dirpath: string): Promise<string[]>;
@@ -76,6 +77,7 @@ function createLocalCLIHostFromExecFunctions(localCwd: string, exec: ExecFunctio
7677
isFolder: isLocalFolder,
7778
readFile: readLocalFile,
7879
writeFile: writeLocalFile,
80+
deleteFile: unlinkLocal,
7981
rename: renameLocal,
8082
mkdirp: async (dirpath) => {
8183
await mkdirpLocal(dirpath);

src/spec-node/dockerCompose.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { Mount, parseMount } from '../spec-configuration/containerFeaturesConfig
1919
import path from 'path';
2020
import { getDevcontainerMetadata, getImageBuildInfoFromDockerfile, getImageBuildInfoFromImage, getImageMetadataFromContainer, ImageBuildInfo, lifecycleCommandOriginMapFromMetadata, mergeConfiguration, MergedDevContainerConfig } from './imageMetadata';
2121
import { ensureDockerfileHasFinalStageName } from './dockerfileUtils';
22-
import { resolveDockerfileIncludesIfNeeded } from './dockerfilePreprocess';
22+
import { materializeResolvedDockerfileForBuild, resolveDockerfileIncludesIfNeeded } from './dockerfilePreprocess';
2323
import { randomUUID } from 'crypto';
2424

2525
const projectLabel = 'com.docker.compose.project';
@@ -165,15 +165,15 @@ export async function buildAndExtendDockerCompose(configWithRaw: SubstitutedConf
165165
let dockerfile: string | undefined;
166166
let imageBuildInfo: ImageBuildInfo;
167167
let preprocessedDockerfilePathForComposeBuild: string | undefined;
168+
let disposeMaterializedDockerfile = async () => { };
169+
let resolvedBuildDockerfile;
168170
const serviceInfo = getBuildInfoForService(composeService, cliHost.path, localComposeFiles);
169171
if (serviceInfo.build) {
170172
const { context, dockerfilePath, target } = serviceInfo.build;
171173
const resolvedDockerfilePath = cliHost.path.isAbsolute(dockerfilePath) ? dockerfilePath : path.resolve(context, dockerfilePath);
172174
const resolvedDockerfile = await resolveDockerfileIncludesIfNeeded(cliHost, resolvedDockerfilePath);
175+
resolvedBuildDockerfile = resolvedDockerfile;
173176
const originalDockerfile = resolvedDockerfile.effectiveDockerfileContent;
174-
if (resolvedDockerfile.preprocessed) {
175-
preprocessedDockerfilePathForComposeBuild = resolvedDockerfile.effectiveDockerfilePath;
176-
}
177177
dockerfile = originalDockerfile;
178178
if (target) {
179179
// Explictly set build target for the dev container build features on that
@@ -197,6 +197,11 @@ export async function buildAndExtendDockerCompose(configWithRaw: SubstitutedConf
197197
const supportsAdditionalBuildContexts = !params.isPodman && version && !isEarlierVersion(version, [2, 17, 0]);
198198
const optionalBuildKitParams = supportsAdditionalBuildContexts ? params : { ...params, buildKitVersion: undefined };
199199
const extendImageBuildInfo = await getExtendImageBuildInfo(optionalBuildKitParams, configWithRaw, baseName, imageBuildInfo, composeService.user, additionalFeatures, canAddLabelsToContainer);
200+
if (resolvedBuildDockerfile && !extendImageBuildInfo?.featureBuildInfo) {
201+
const materializedDockerfile = await materializeResolvedDockerfileForBuild(cliHost, resolvedBuildDockerfile);
202+
preprocessedDockerfilePathForComposeBuild = materializedDockerfile.dockerfilePath;
203+
disposeMaterializedDockerfile = materializedDockerfile.dispose;
204+
}
200205

201206
let overrideImageName: string | undefined;
202207
let buildOverrideContent = '';
@@ -274,7 +279,8 @@ ${cacheFromOverrideContent}
274279
args.push('-f', composeOverrideFile);
275280
}
276281

277-
if (!noBuild) {
282+
try {
283+
if (!noBuild) {
278284
args.push('build');
279285
if (noCache) {
280286
args.push('--no-cache');
@@ -304,6 +310,9 @@ ${cacheFromOverrideContent}
304310

305311
throw err instanceof ContainerError ? err : new ContainerError({ description: 'An error occurred building the Docker Compose images.', originalError: err, data: { fileWithError: localComposeFiles[0] } });
306312
}
313+
}
314+
} finally {
315+
await disposeMaterializedDockerfile();
307316
}
308317

309318
return {

0 commit comments

Comments
 (0)