Build Configuration Step Deep Dive
Overview
The Configuration Step is the 3rd step in the Build Creation Wizard. It's where users configure the specific settings for their chosen build method. This step uses a tab-based interface with 4 tabs that organize different configuration aspects.
Key Principle
The Build Method tab is NOT a validation tab - it's the final tab that holds method-specific required fields. Each build method has unique requirements:
- Kaniko: Requires full Dockerfile content + build context
- Buildx: Requires base image + instructions (plus advanced options)
- Container: Requires base image + instructions
- Paketo: Requires builder selection
- Packer: Requires Packer template JSON
Wizard Flow Recap
Step 1: Build Method Selection
↓ (Choose Kaniko, Buildx, Container, Paketo, or Packer)
↓
Step 2: Tool Selection
↓ (Select SBOM, scanning tools, registry, secrets manager)
↓
Step 3: Configuration ← YOU ARE HERE
├─ Tab 1: Basic (Base Image, Instructions, Tags)
├─ Tab 2: Environment (Environment variables)
├─ Tab 3: Advanced (Method-specific advanced options)
└─ Tab 4: Build Method (Method-specific required config)
↓
Step 4: Validation & Submit
The 4 Configuration Tabs Explained
Tab 1: Basic
Purpose: Collect common build configuration needed across most build methods
Fields:
-
Base Image (for non-Kaniko builds)
- Type: Text input
- Example:
ubuntu:20.04,node:18-alpine,python:3.9-slim - Description: The starting container image for your build
- Required for: Container, Buildx
- Not used for: Kaniko (Kaniko requires Dockerfile content instead), Paketo, Packer
-
Build Instructions (for non-Kaniko builds)
- Type: Textarea (one instruction per line)
- Example:
RUN apt-get update && apt-get install -y build-essential COPY . /app WORKDIR /app RUN npm install && npm run build - Description: Dockerfile RUN, COPY, WORKDIR, EXPOSE, CMD, etc. instructions
- Stored as: Array of strings (split by newline)
- Required for: Container, Buildx
- Not used for: Kaniko
-
Tags
- Type: Text input (comma-separated)
- Example:
latest, v1.0.0, production - Description: Image tags to apply after build
- Stored as: Array of strings (split by comma, trimmed)
- Required for: All build methods
- Used when: Pushing image to registry
Use Cases:
- Quick/standard container builds using Docker
- Setting up basic build instructions
- Adding image tags for versioning
Validation:
IF buildMethod != 'kaniko' AND !baseImage
→ ERROR: "Base image is required"
IF buildMethod != 'kaniko' AND !instructions.length
→ ERROR: "At least one build instruction is required"
Tab 2: Environment
Purpose: Define environment variables that will be available during the build process
Features:
- Dynamic key-value editor: Add/remove environment variable pairs
- Add button:
+ Add Environment Variable - Remove button:
✕per variable
Structure:
environment: {
'NPM_ENV': 'production',
'NODE_VERSION': '18',
'BUILD_DATE': '2026-02-01',
'CACHE_DIR': '/tmp/cache'
}
Common Use Cases:
NPM_ENV=production- Node.js environment flagBUILD_FLAGS=-O3- Compiler optimization flagsREGISTRY_URL=myregistry.com- Registry endpointPYTHON_VERSION=3.9- Language version specificationCI_BUILD_ID=123456- Build metadata
Implementation Details:
- Stored as key-value object in
buildConfig.environment - UI allows inline editing of key AND value
- Empty strings are filtered on update
- Applied to the build process via build-time environment
Applies To: All build methods
When Used:
- Build-time configuration that doesn't need Dockerfile modification
- Passing secrets/credentials (though secrets manager is preferred)
- Compiler flags, language versions, feature flags
Tab 3: Advanced
Purpose: Build-method-specific advanced configuration options
For Container Builds:
Fields:
- Dockerfile Path: Default "Dockerfile"
- Build Context: Default "." (current directory)
- Target Stage: Optional (for multi-stage builds)
Example:
# Multi-stage Dockerfile
FROM node:18 AS builder
RUN npm install && npm run build
FROM node:18-slim
COPY --from=builder /app/dist /app
In this case: Target Stage = builder selects which stage to use as output
For Buildx Builds:
Fields:
- Target Platforms: e.g., "linux/amd64, linux/arm64, linux/arm/v7"
- Enable Build Cache: Checkbox
- Cache Repository: e.g., "myregistry.com/myapp/cache"
Example:
Platforms: linux/amd64, linux/arm64
Enable Cache: ✓
Cache Repo: gcr.io/my-project/build-cache
For All Build Methods:
Fields:
- Cache Repository: Generic caching configuration
Why This Tab?
- Advanced options are method-specific and not commonly needed
- Separates "I just want to build" (Basic) from "I need advanced control" (Advanced)
- Keeps the UI clean and progressive disclosure
Common Scenarios:
- Multi-stage Docker builds with specific target stages
- Cross-platform builds (e.g., supporting ARM + AMD64)
- Cache optimization for large builds
- Custom Dockerfile locations (non-standard paths)
Tab 4: Build Method
Purpose: Method-specific REQUIRED configuration that cannot be collected in other tabs
This tab contains the unique, essential configuration for each build method:
For Kaniko:
REQUIRED Fields:
1. Dockerfile * (Textarea - full Dockerfile content)
- Placeholder: Complete Dockerfile example
- Size: 8 rows
- Validation: Cannot be empty
2. Build Context * (Text input)
- Example: "."
- Description: The directory with build files
- Validation: Cannot be empty
3. Registry Repository * (Text input)
- Example: "123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app"
- Description: Target image repository used by the Kaniko executor
- Validation: Cannot be empty
Why Kaniko is different:
- Kaniko requires the complete Dockerfile content as a string (not base image + instructions)
- This is because Kaniko is Google's tool that reads an entire Dockerfile and builds without Docker daemon
- It needs the exact Dockerfile to execute
Kaniko Validation Errors:
IF !dockerfile:
→ "Dockerfile content is required for Kaniko builds"
IF !buildContext:
→ "Build context is required for Kaniko builds"
IF !registryRepo:
→ "Registry repository is required for Kaniko builds"
For Buildx:
- Uses Base Image + Instructions from Basic tab
- Target Platforms from Advanced tab
- No additional fields in Build Method tab
For Container:
- Uses Base Image + Instructions from Basic tab
- Dockerfile Path + Target Stage from Advanced tab
- No additional fields in Build Method tab
For Paketo:
Fields:
- Buildpack Builder (Dropdown)
Options:
- paketobuildpacks/builder:base
- paketobuildpacks/builder:full
- paketobuildpacks/builder:tiny
Validation:
IF !builder:
→ "Buildpack builder selection is required for Paketo builds"
For Packer:
Fields:
- Packer Template (Textarea - HCL/JSON)
Size: 8 rows
Validation: Cannot be empty
Example:
{
"builders": [
{
"type": "amazon-ebs",
"region": "us-east-1",
"source_ami": "ami-12345678"
}
],
"provisioners": [...]
}
Validation:
IF !packerTemplate:
→ "Packer template is required for Packer builds"
Information Box at top of tab:
[Build Method Specific Config]
[{buildMethod.toUpperCase()} Build Configuration]
[Description of what this build method does]
Data Flow: How Configuration is Used
Three Important Distinctions:
-
Frontend Local State (WizardState)
- Stores user input as they fill out the form
- Uses camelCase naming (JavaScript convention)
- Contains both UI fields AND build config
-
API Payload Sent to Backend (CreateBuildRequest)
- Snake_case naming (Go backend convention)
- Flattens/merges config data into BuildManifest
- Includes only what the backend needs
-
Backend Domain Model (BuildManifest + BuildConfig)
- Go structs with full type safety
- Validates and stores all configuration
- Handles different build methods with appropriate fields
The WizardState Object (Frontend Local State):
wizardState = {
// From Step 1
currentStep: number
buildName: string
buildDescription: string
buildMethod: 'kaniko' | 'buildx' | 'container' | 'paketo' | 'packer'
selectedProject: Project
// From Step 2
selectedTools: {
sbom?: SBOMTool // 'syft' | 'grype' | 'trivy'
scan?: ScanTool // 'trivy' | 'clair' | 'grype' | 'snyk'
registry?: RegistryType // 's3' | 'harbor' | 'quay' | 'artifactory'
secrets?: SecretManagerType // 'vault' | 'aws_secretsmanager' | 'azure_keyvault'
}
// From Step 3 Configuration
buildConfig: {
// Basic tab (all methods)
baseImage?: string // e.g., "ubuntu:20.04"
instructions?: string[] // Array of RUN, COPY, etc. commands
tags?: string[] // ["latest", "v1.0.0"]
// Environment tab (all methods)
environment?: Record<string, string> // {"NPM_ENV": "production"}
// Advanced tab (method-specific)
dockerfile?: string // Path or content depending on context
buildContext?: string // "." or "./src"
target?: string // Multi-stage target stage
platforms?: string[] // ["linux/amd64", "linux/arm64"]
cache?: boolean
cacheRepo?: string // "myregistry.com/cache"
// Build Method tab (method-specific)
dockerfile?: string // FULL Dockerfile content for Kaniko
buildContext?: string // Build context for Kaniko
paketoConfig?: {
builder: string // "paketobuildpacks/builder:base"
}
packerTemplate?: string // Full Packer HCL/JSON template
}
}
The API Payload: CreateBuildRequest
When the user submits the build creation wizard (Step 4), the frontend transforms WizardState into a CreateBuildRequest and sends it to the backend API.
Frontend Transformation (buildService.ts):
// What the wizard collects
const buildConfig: BuildConfig = {
buildType: wizardState.buildMethod, // 'kaniko', 'buildx', etc.
sbomTool: wizardState.selectedTools.sbom!,
scanTool: wizardState.selectedTools.scan!,
registryType: wizardState.selectedTools.registry!,
secretManagerType: wizardState.selectedTools.secrets!,
...wizardState.buildConfig // Spread all the configuration fields
}
// Transform to API payload
const buildRequest = {
tenantId: selectedTenantId, // Step 1: Current tenant
projectId: wizardState.selectedProject.id, // Step 1: Selected project
manifest: {
name: wizardState.buildName, // Build name from Step 1
description: wizardState.buildDescription,
type: wizardState.buildMethod, // 'kaniko', 'buildx', etc.
baseImage: '', // Will be set by buildConfig
instructions: [], // Will be set by buildConfig
environment: {}, // Will be set by buildConfig
tags: [], // Will be set by buildConfig
metadata: {},
buildConfig // All the configuration!
}
}
// Send to API
await buildService.createBuild(buildRequest)
The buildService transforms to snake_case:
async createBuild(buildData: CreateBuildRequest): Promise<Build> {
const transformedData = {
tenant_id: buildData.tenantId, // camelCase → snake_case
project_id: buildData.projectId,
manifest: buildData.manifest
}
const response = await api.post('/builds', transformedData)
return response.data.data
}
API Endpoint: POST /api/v1/builds
Payload Structure (JSON sent to backend):
{
"tenant_id": "702ea47b-22ec-439c-87b3-69f5c7e4c334",
"project_id": "81234567-890a-bcde-f012-345678901234",
"manifest": {
"name": "My Node App Build",
"description": "Building Node.js application",
"type": "kaniko",
"base_image": "",
"instructions": [],
"environment": {
"NPM_ENV": "production",
"NODE_VERSION": "18"
},
"tags": ["latest", "v1.0.0"],
"metadata": {},
"build_config": {
"build_type": "kaniko",
"sbom_tool": "syft",
"scan_tool": "trivy",
"registry_type": "harbor",
"secret_manager_type": "vault",
"dockerfile": "FROM node:18-alpine\nRUN npm install\nCMD [\"npm\", \"start\"]",
"build_context": ".",
"build_args": {},
"cache": false,
"cache_repo": ""
}
}
}
Backend Processing: BuildManifest + BuildConfig
Once the API receives the payload, the backend parses it into Go structs:
CreateBuildRequest (Handler Layer):
type CreateBuildRequest struct {
TenantID string `json:"tenant_id" validate:"required,uuid"`
ProjectID string `json:"project_id" validate:"required,uuid"`
Manifest build.BuildManifest `json:"manifest" validate:"required"`
}
BuildManifest (Domain Layer):
type BuildManifest struct {
Name string `json:"name"`
Type BuildType `json:"type"` // "kaniko", "buildx", etc.
BaseImage string `json:"base_image"`
Instructions []string `json:"instructions"`
Environment map[string]string `json:"environment"` // From Environment tab!
Tags []string `json:"tags"` // From Basic tab!
Metadata map[string]interface{} `json:"metadata"`
BuildConfig *BuildConfig `json:"build_config"` // All 3 tabs + methods
}
BuildConfig (Domain Layer):
type BuildConfig struct {
// Mandatory for all builds
BuildType BuildType // From wizard step selection
SBOMTool SBOMTool // From Tool Selection step
ScanTool ScanTool // From Tool Selection step
RegistryType RegistryType // From Tool Selection step
SecretManagerType SecretManagerType // From Tool Selection step
// For Kaniko & Buildx (Dockerfile-based)
Dockerfile string // FULL Dockerfile content from Build Method tab
BuildContext string // "." or custom path from Build Method tab
BuildArgs map[string]string // Build arguments
Target string // Multi-stage target from Advanced tab
Cache bool // Enable cache from Advanced tab
CacheRepo string // Cache repo from Advanced tab
// For Buildx only
Platforms []string // Target platforms from Advanced tab
CacheTo string // Cache export location
CacheFrom []string // Cache import locations
Secrets map[string]string // Build secrets
// For Paketo (Buildpacks)
PaketoConfig *PaketoConfig // Builder + buildpacks from Build Method tab
// PaketoConfig struct:
// {
// Builder: "paketobuildpacks/builder:base" // From Build Method tab
// Buildpacks: []string{}
// Env: map[string]string // From Environment tab
// BuildArgs: map[string]string
// }
// For Packer (VM images)
PackerTemplate string // Full HCL/JSON from Build Method tab
Builders []PackerBuilder // Parsed from template
Provisioners []VMProvisioner // Parsed from template
PostProcessors []VMPostProcessor // Parsed from template
// Common
Variables map[string]interface{} // Build variables
}
Validation Flow
When does validation happen?
Approach: Method-Specific Validation at Bottom of Step
Validation messages appear at the bottom of the Configuration Step and are shown in real-time as user fills fields:
// Kaniko validation
IF buildMethod === 'kaniko' && !dockerfile
→ Show red error: "Dockerfile content is required for Kaniko builds"
IF buildMethod === 'kaniko' && !buildContext
→ Show red error: "Build context is required for Kaniko builds"
// Container/Buildx validation
IF buildMethod !== 'kaniko' && !baseImage
→ Show red error: "Base image is required"
IF buildMethod !== 'kaniko' && !instructions.length
→ Show red error: "At least one build instruction is required"
// Paketo validation
IF buildMethod === 'paketo' && !paketoConfig?.builder
→ Show red error: "Buildpack builder selection is required"
// Packer validation
IF buildMethod === 'packer' && !packerTemplate
→ Show red error: "Packer template is required"
Next Step Button State:
- Enabled: When all required fields for current build method are filled
- Disabled: When validation messages are present
Why This Tab Structure?
Problem Being Solved:
Building container images has many, many options:
- Base image
- Build instructions
- Environment variables
- Caching strategy
- Multi-platform support
- Multi-stage targeting
- Build-method-specific fields
Solution: Progressive Disclosure
Tab 1 (Basic)
- Essential for most builds
- Getting started experience
Tab 2 (Environment)
- Common but optional
- Grouped together by category
Tab 3 (Advanced)
- For power users
- Method-specific optimizations
- Not needed for simple builds
Tab 4 (Build Method)
- Method-specific REQUIRED fields
- Validation only for these ensures correct setup
- Clear separation of concerns
Alternative Approaches NOT Used:
❌ Single long form: Would be overwhelming ❌ Conditional fields: Would be confusing (too many if-then display rules) ✅ Tabs: Clear organization, progressive disclosure, scalable
Common Scenarios & Tab Usage
Scenario 1: Simple Node.js app with Buildx
Step 1: Select Buildx
↓
Step 2: Select tools (SBOM, scanning, etc.)
↓
Step 3: Configuration
├─ Basic Tab:
│ - Base Image: node:18-alpine
│ - Instructions: RUN npm install, RUN npm run build, COPY . /app
│ - Tags: latest, v1.0.0
├─ Environment Tab:
│ - NODE_ENV=production
│ - NPM_REGISTRY=https://registry.npmjs.org
├─ Advanced Tab:
│ - Platforms: linux/amd64, linux/arm64
│ - Cache: ✓ Enabled
└─ Build Method Tab:
- No additional fields
✓ Proceed to Step 4
Scenario 2: Complex app with multi-stage Docker build
Step 3: Configuration
├─ Basic Tab:
│ - Base Image: node:18
│ - Instructions: (build and bundle commands)
│ - Tags: latest
├─ Environment Tab:
│ - (None)
├─ Advanced Tab:
│ - Dockerfile Path: ./Dockerfile.prod
│ - Target Stage: production ← KEY: specify which stage
│ - Build Context: .
└─ Build Method Tab:
- (Container build, no extra fields)
✓ Proceed to Step 4
Scenario 3: Kaniko on Kubernetes
Step 3: Configuration
├─ Basic Tab:
│ - Base Image: (IGNORED - Kaniko uses Dockerfile)
│ - Instructions: (IGNORED - Kaniko uses Dockerfile)
│ - Tags: latest, v1.0
├─ Environment Tab:
│ - REGISTRY_URL=gcr.io/my-project
│ - KANIKO_CACHE=true
├─ Advanced Tab:
│ - (No Advanced options for Kaniko in Advanced tab)
└─ Build Method Tab:
- Dockerfile: (Full Dockerfile content pasted/edited here)
FROM ubuntu:20.04
RUN apt-get update && apt-get install -y build-essential
COPY . /app
RUN make build
CMD ["./app"]
- Build Context: .
✓ Proceed to Step 4
Scenario 4: Paketo Buildpacks
Step 3: Configuration
├─ Basic Tab:
│ - Base Image: (IGNORED - Paketo auto-detects)
│ - Instructions: (IGNORED - Paketo auto-generates)
│ - Tags: latest
├─ Environment Tab:
│ - BP_NODE_VERSION=18
├─ Advanced Tab:
│ - Cache Repository: gcr.io/my-project/cache
└─ Build Method Tab:
- Builder: paketobuildpacks/builder:base
✓ Proceed to Step 4
Implementation Architecture
Component: ConfigurationStep.tsx
Props:
interface ConfigurationStepProps {
wizardState: WizardState
onUpdate: (updates: Partial<WizardState>) => void
}
Internal State:
activeTab: 'basic' | 'advanced' | 'environment' | 'build'
Key Functions:
renderBasicConfig()- Renders Tab 1renderEnvironmentConfig()- Renders Tab 2renderAdvancedConfig()- Renders Tab 3renderBuildMethodSpecific()- Renders Tab 4updateBuildConfig(updates)- Updates buildConfig in wizardState
Key Features:
- Tabs are simple buttons that change
activeTabstate - Tab content rendered conditionally based on
activeTab - All updates call
onUpdate()with partial WizardState - Parent component (BuildCreationWizard) manages overall state
- Validation messages appear at bottom, updated in real-time
How Each Tab's Data Flows to the Backend
Important Clarification: Why All 3 Tabs Matter for Kaniko
You asked: "If Kaniko needs entire dockerfile, what purpose these 3 tabs serve?"
Answer: Even though Kaniko requires full Dockerfile content, the other tabs serve critical purposes:
Tab 1: Basic (IGNORED for Kaniko, STORED in BuildConfig)
Basic tab fields: baseImage, instructions, tags
├─ For Kaniko: NOT USED (Kaniko has everything in Dockerfile)
├─ For Buildx: USED (baseImage becomes first FROM line, instructions become RUN/COPY/etc)
├─ For Container: USED (same as Buildx)
└─ STORED IN: buildConfig.buildArgs, buildConfig.cache settings
Actually, here's the truth: Basic tab fields are NEVER sent to backend for Kaniko
because Kaniko doesn't need them - it uses the Dockerfile instead.
BUT: Tags ARE sent! (manifest.tags)
Build names and descriptions ARE sent! (manifest.name, manifest.description)
Tab 2: Environment (USED for ALL methods including Kaniko!)
Environment tab fields: key=value pairs
├─ For Kaniko: SENT as manifest.environment
│ └─ Used as build-time environment variables when Kaniko runs
│ └─ Example: NPM_ENV=production passed to the Kaniko builder
│
├─ For Buildx: SENT as manifest.environment
│ └─ Available to all RUN instructions in Dockerfile
│ └─ Example: RUN npm run build (with NPM_ENV set)
│
└─ For ALL methods:
└─ BUILD-TIME variables, not just "nice to have"
└─ Critical for passing config: REGISTRY_URL, BUILD_FLAGS, VERSION, etc.
Real Kaniko Example:
# Dockerfile content (from Build Method tab)
FROM ubuntu:20.04
# This environment variable comes from Environment tab!
RUN echo "Building in environment: ${BUILD_ENV}"
RUN npm install
RUN npm run build --prod
ENV APP_ENV=$BUILD_ENV
When Kaniko builds:
API Payload environment: { "BUILD_ENV": "production", "NPM_REGISTRY": "https://..." }
↓ (These are available to Dockerfile)
Kaniko executes: podman build with ENV vars set
→ RUN npm install (with NPM_REGISTRY available)
→ RUN npm run build --prod
→ ENV APP_ENV=production
Tab 3: Advanced (Mostly IGNORED for Kaniko, Used for other methods)
Advanced tab fields: dockerfile path, build context, target stage, platforms, cache
├─ For Kaniko:
│ └─ Dockerfile path: IGNORED (Kaniko uses full content from Build Method tab)
│ └─ Build context: USED! (buildConfig.buildContext = ".")
│ └─ Target stage: IGNORED (Kaniko uses Dockerfile as-is)
│ └─ Platforms: N/A
│ └─ Cache settings: STORED (buildConfig.cache, buildConfig.cacheRepo)
│
├─ For Buildx:
│ └─ Dockerfile path: USED
│ └─ Build context: USED
│ └─ Target stage: USED (multi-stage builds)
│ └─ Platforms: USED! (buildConfig.platforms = ["linux/amd64", "linux/arm64"])
│ └─ Cache: USED (buildConfig.cache, buildConfig.cacheRepo)
│
└─ For Container:
└─ Similar to Buildx but no multi-platform support
Tab 4: Build Method (REQUIRED for each method)
Build Method tab fields: Method-specific configuration
├─ For Kaniko:
│ ├─ Dockerfile (REQUIRED): Full content
│ │ └─ Sent as: buildConfig.dockerfile
│ └─ Build context (REQUIRED): ".", "./src", etc.
│ └─ Sent as: buildConfig.buildContext
│
├─ For Buildx:
│ └─ No extra fields! Uses Basic + Advanced
│
├─ For Container:
│ └─ No extra fields! Uses Basic + Advanced
│
├─ For Paketo:
│ └─ Builder selection (REQUIRED)
│ └─ Sent as: buildConfig.paketoConfig.builder
│
└─ For Packer:
└─ Packer template (REQUIRED)
└─ Sent as: buildConfig.packerTemplate
Complete Data Flow Example: Kaniko Build
What User Enters:
Step 1: Build Method (User selects "Kaniko")
Project: MyProject
Build Name: My App Build
Build Method: Kaniko
Step 2: Tool Selection
SBOM Tool: syft
Scan Tool: trivy
Registry: harbor
Secrets Manager: vault
Step 3: Configuration
Tab 1: Basic (irrelevant for Kaniko, but form shows it)
Base Image: [ignored for Kaniko]
Instructions: [ignored for Kaniko]
Tags: latest, v1.0.0
Tab 2: Environment
NPM_ENV = production
NPM_REGISTRY = https://registry.npmjs.org
CACHE_DIR = /tmp/cache
Tab 3: Advanced
Dockerfile Path: [ignored]
Build Context: .
Cache Enabled: true
Cache Repo: harbor.mycompany.com/cache
Tab 4: Build Method
Dockerfile:
FROM node:18-alpine
RUN npm config set registry $NPM_REGISTRY
WORKDIR /app
COPY . .
RUN npm ci
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
Build Context: .
API Payload Sent:
{
"tenant_id": "702ea47b-22ec-439c-87b3-69f5c7e4c334",
"project_id": "81234567-890a-bcde-f012-345678901234",
"manifest": {
"name": "My App Build",
"description": "",
"type": "kaniko",
"base_image": "", // ← Ignored for Kaniko
"instructions": [], // ← Ignored for Kaniko
"environment": { // ← FROM Tab 2!
"NPM_ENV": "production",
"NPM_REGISTRY": "https://registry.npmjs.org",
"CACHE_DIR": "/tmp/cache"
},
"tags": ["latest", "v1.0.0"], // ← FROM Tab 1!
"metadata": {},
"build_config": {
"build_type": "kaniko",
"sbom_tool": "syft",
"scan_tool": "trivy",
"registry_type": "harbor",
"secret_manager_type": "vault",
"dockerfile": "FROM node:18-alpine\nRUN npm config set registry $NPM_REGISTRY\n...", // ← FROM Tab 4!
"build_context": ".", // ← FROM Tab 3!
"build_args": {},
"cache": true, // ← FROM Tab 3!
"cache_repo": "harbor.mycompany.com/cache" // ← FROM Tab 3!
}
}
}
How Backend Uses This:
// Backend receives and parses into Go structs
func (h *BuildHandler) CreateBuild(w http.ResponseWriter, r *http.Request) {
var req CreateBuildRequest
json.NewDecoder(r.Body).Decode(&req)
// req.Manifest contains all configuration
// req.Manifest.BuildConfig contains the build method specific config
// When Kaniko build runs:
// 1. Start Kaniko executor with:
// - Dockerfile content: req.Manifest.BuildConfig.Dockerfile
// - Build context: req.Manifest.BuildConfig.BuildContext = "."
// - Environment: req.Manifest.Environment (NPM_ENV, NPM_REGISTRY, CACHE_DIR)
// - Cache config: req.Manifest.BuildConfig.Cache = true
//
// 2. After build completes:
// - Tag image with: req.Manifest.Tags (["latest", "v1.0.0"])
// - Push to: req.Manifest.BuildConfig.RegistryType (harbor)
// - Generate SBOM with: req.Manifest.BuildConfig.SBOMTool (syft)
// - Scan image with: req.Manifest.BuildConfig.ScanTool (trivy)
}
Summary: Tab Purposes for Kaniko
| Tab | Fields | Purpose for Kaniko | Status |
|---|---|---|---|
| Basic | Base image, instructions | Ignored (Kaniko has these in Dockerfile) | ✗ Not Used |
| Tags | Specify image tags after build | ✓ USED | |
| Environment | Key-value variables | Available to Dockerfile RUN commands | ✓ USED |
| (e.g., NPM_ENV, BUILD_FLAGS) | Build-time configuration | ✓ CRITICAL | |
| Advanced | Dockerfile path | Not needed (using full content) | ✗ Not Used |
| Build context | Directory with build context files (source code) | ✓ USED | |
| Cache settings | Enable/configure build cache | ✓ USED | |
| Build Method | Dockerfile content | Full Dockerfile to execute | ✓ REQUIRED |
| Build context path | Where source files are located | ✓ REQUIRED |
Root Cause:
You selected Kaniko as your build method, which has different requirements than other methods.
Solution:
- Navigate to the Build Method tab (rightmost tab)
- Fill in the Dockerfile textarea with your complete Dockerfile content
- Fill in the Build Context field (usually
.for current directory) - Errors should disappear
Why Kaniko is Different:
- Kaniko is Google's container build tool
- It requires the entire Dockerfile content as a string, not individual instructions
- This is different from
docker buildwhich reads Dockerfile from filesystem - Makes sense: Kaniko can run in restricted environments (Kubernetes pods) without Docker daemon
UX Design Principles
1. Progressive Disclosure
- Basic users only need Tab 1
- Advanced users can explore Tabs 3 & 4
- Encourages learning curve progression
2. Method-Specific Guidance
- Each build method has a blue info box explaining its purpose
- Users know what they're building with
3. Real-Time Validation
- Errors appear at bottom of form
- Users see what's missing immediately
- No surprises on next step
4. Clear Labeling
- Each field has description text
- Placeholders show expected format
- Required fields marked with
*
5. Organized Categories
- Basic: Essential, common to all
- Environment: Optional, for all
- Advanced: Optional, method-specific
- Build Method: Required, method-specific
Summary Table
| Tab | Purpose | Required? | Used For | Who Fills It? |
|---|---|---|---|---|
| Basic | Common build config | Yes | Base image, instructions, tags | All users |
| Environment | Build-time variables | No | ENV vars, flags, metadata | Power users |
| Advanced | Advanced options | No | Multi-stage, multi-platform, caching | Advanced users |
| Build Method | Method-specific config | Yes | Kaniko Dockerfile, Paketo builder, etc. | All users (specific to chosen method) |
Next Steps
After Configuration Step: → Step 4: Validation & Submission
- Review all collected data
- Show summary of build configuration
- Final validation before creating build
- Submit to backend API