Merge pull request #400 from iksaku/feat/docker-build-stage

feat(docker): Multi-stage Builds
This commit is contained in:
Mauricio Siu
2024-09-02 00:09:20 -06:00
committed by GitHub
8 changed files with 3593 additions and 1 deletions

View File

@@ -10,6 +10,7 @@ const baseApp: ApplicationNested = {
appName: "",
autoDeploy: true,
branch: null,
dockerBuildStage: "",
buildArgs: null,
buildPath: "/",
gitlabPathNamespace: "",

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,32 @@ 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

@@ -239,6 +239,13 @@
"when": 1725250322137,
"tag": "0033_white_hawkeye",
"breakpoints": true
},
{
"idx": 34,
"version": "6",
"when": 1725256397019,
"tag": "0034_aspiring_secret_warriors",
"breakpoints": true
}
]
}

View File

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

View File

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

View File

@@ -12,7 +12,8 @@ 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 +26,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);
}