in app/lib/server/processors/DockerJobExecutor.ts [144:280]
private async runJobInContainer(
jobId: string,
jobData: any,
credentials: any
): Promise<{
output: string;
environment: Record<string, string>;
secrets: Record<string, string>;
}> {
console.log(`🐳 Creating Docker container for job ${jobId}`);
// Use credentials from request (required - no fallback)
const openaiKey = credentials?.openaiApiKey;
// (Optional) enforce openaiKey presence if needed:
// if (!openaiKey) {
// throw new Error(
// "OpenAI API key is required but not provided in credentials"
// );
// }
// Use user's Docker configuration
let imageRef = dockerConfig.image;
console.log(`🐳 Using Docker image: ${imageRef}`);
// REMOVE to handle private registry or custom namespace
// If the default image is "codex-universal-explore:dev"
if (imageRef === "codex-universal-explore:dev") {
imageRef = "docker.io/drbh/codex-universal-explore:dev";
}
// Check if image exists locally
try {
await this.docker.getImage(imageRef).inspect();
console.log(`✅ Docker image found: ${imageRef}`);
} catch (error) {
console.error(`❌ Docker image not found: ${imageRef}`);
try {
const pullStream = await this.docker.pull(imageRef);
await new Promise<void>((resolve, reject) => {
this.docker.modem.followProgress(
pullStream,
(err: Error) => {
if (err) return reject(err);
return resolve();
},
(event: any) => {
// (Optional) uncomment to see each pull progress event:
console.log(event.status, event.progress || "");
}
);
});
console.log(`✅ Successfully pulled image: ${imageRef}`);
} catch (pullErr) {
console.error(
`❌ Failed to pull image "${imageRef}": ${pullErr.message}`
);
throw new Error(
`Could not pull Docker image "${imageRef}". ` +
`If it’s on Docker Hub under namespace "drbh", make sure you’ve pushed ` +
`"${imageRef}". If it’s on a private registry, ensure you’re logged in and the name is correct.`
);
}
}
// Get repository URL from job data or fall back to server config
const repositoryUrl = jobData.repository?.url || REPO.URL;
const repositoryBranch = jobData.repository?.branch || REPO.BRANCH;
console.log(
`📂 Repository: ${repositoryUrl} (branch: ${repositoryBranch})`
);
console.log(
`📋 Environment variables: ${
Object.keys(dockerConfig.environment).length
} custom variables`
);
console.log(
`🔐 Secrets: ${Object.keys(dockerConfig.secrets).length} custom secrets`
);
// Merge base environment with user's custom environment variables
const baseEnvironment = {
JOB_ID: jobId,
REPO_URL: repositoryUrl,
REPO_BRANCH: repositoryBranch,
PROMPT: jobData.description,
...dockerConfig.environment, // User's custom env vars
};
const secrets = {
OPENAI_API_KEY: openaiKey,
...dockerConfig.secrets, // User's custom secrets
};
// Convert to array format for Docker
const environment = [
...Object.entries(baseEnvironment).map(
([key, value]) => `${key}=${value}`
),
...Object.entries(secrets).map(([key, value]) => `${key}=${value}`),
];
// Use the user's configured Docker image
const container = await this.docker.createContainer({
Image: imageRef,
Cmd: ["/opt/agents/codex"],
Env: environment,
WorkingDir: "/workspace",
Tty: false,
AttachStdout: true,
AttachStderr: true,
HostConfig: {
AutoRemove: true,
Memory: DOCKER.MEMORY_LIMIT,
CpuShares: DOCKER.CPU_SHARES,
},
});
console.log(`🚀 Starting container for job ${jobId}`);
// Start container
await container.start();
// Get container logs
const logs = await this.getContainerLogs(container, jobId);
console.log(
`📜 Container logs for job ${jobId} (${logs.length} characters)`
);
console.log(`📄 Container logs preview:`, logs.substring(0, 500));
return {
output: logs,
environment: baseEnvironment,
secrets: secrets,
};
}