feat(docker): Multi-stage Builds

This commit is contained in:
Jorge González 2024-09-01 00:31:28 -06:00
parent 28d8fa9834
commit de72652297
No known key found for this signature in database
GPG Key ID: 194A4F5E8E749651
7 changed files with 3125 additions and 1 deletions

View File

@ -37,6 +37,7 @@ const mySchema = z.discriminatedUnion("buildType", [
})
.min(1, "Dockerfile required"),
dockerContextPath: z.string().nullable().default(""),
dockerBuildStage: z.string().nullable().default(""),
}),
z.object({
buildType: z.literal("heroku_buildpacks"),
@ -86,6 +87,7 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
...(data.buildType && {
dockerfile: data.dockerfile || "",
dockerContextPath: data.dockerContextPath || "",
dockerBuildStage: data.dockerBuildStage || "",
}),
});
} else {
@ -106,6 +108,8 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
dockerfile: data.buildType === "dockerfile" ? data.dockerfile : null,
dockerContextPath:
data.buildType === "dockerfile" ? data.dockerContextPath : null,
dockerBuildStage:
data.buildType === "dockerfile" ? data.dockerBuildStage : null,
})
.then(async () => {
toast.success("Build type saved");
@ -241,6 +245,34 @@ export const ShowBuildChooseForm = ({ applicationId }: Props) => {
);
}}
/>
<FormField
control={form.control}
name="dockerBuildStage"
render={({ field }) => {
return (
<FormItem>
<div className="space-y-0.5">
<FormLabel>Docker Build Stage</FormLabel>
<FormDescription>
Allows you to target a specific stage in a Multi-stage
Dockerfile. If empty, Docker defaults to build
the last defined stage.
</FormDescription>
</div>
<FormControl>
<Input
placeholder={
"E.g. production"
}
{...field}
value={field.value ?? ""}
/>
</FormControl>
</FormItem>
)
}}
/>
</>
)}

View File

@ -0,0 +1 @@
ALTER TABLE "application" ADD COLUMN "dockerBuildStage" text;

File diff suppressed because it is too large Load Diff

View File

@ -232,6 +232,13 @@
"when": 1723705257806,
"tag": "0032_flashy_shadow_king",
"breakpoints": true
},
{
"idx": 33,
"version": "6",
"when": 1725167062595,
"tag": "0033_new_mandrill",
"breakpoints": true
}
]
}

View File

@ -193,6 +193,7 @@ export const applicationRouter = createTRPCRouter({
dockerfile: input.dockerfile,
publishDirectory: input.publishDirectory,
dockerContextPath: input.dockerContextPath,
dockerBuildStage: input.dockerBuildStage,
});
return true;

View File

@ -142,6 +142,7 @@ export const applications = pgTable("application", {
),
dockerfile: text("dockerfile"),
dockerContextPath: text("dockerContextPath"),
dockerBuildStage: text("dockerBuildStage"),
// Drop
dropBuildPath: text("dropBuildPath"),
// Docker swarm json
@ -358,6 +359,7 @@ export const apiSaveBuildType = createSchema
buildType: true,
dockerfile: true,
dockerContextPath: true,
dockerBuildStage: true,
})
.required()
.merge(createSchema.pick({ publishDirectory: true }));

View File

@ -12,7 +12,7 @@ export const buildCustomDocker = async (
application: ApplicationNested,
writeStream: WriteStream,
) => {
const { appName, env, publishDirectory, buildArgs } = application;
const { appName, env, publishDirectory, buildArgs, dockerBuildStage } = application;
const dockerFilePath = getBuildAppDirectory(application);
try {
const image = `${appName}`;
@ -25,6 +25,10 @@ export const buildCustomDocker = async (
const commandArgs = ["build", "-t", image, "-f", dockerFilePath, "."];
if (!!dockerBuildStage) {
commandArgs.push("--target", dockerBuildStage);
}
for (const arg of args) {
commandArgs.push("--build-arg", arg);
}