Skip to main content

Build Wizard

Never written a Dockerfile before? Don't worry! Build Wizard analyzes your project and automatically generates an optimized Dockerfile for you. With just a few clicks, you can have your container build ready to go.

Build Wizard Benefits
  • Auto-detection: Automatically identifies project language, framework, and package manager.
  • Optimized Templates: Best practices like multi-stage builds and non-root users are applied.
  • Monorepo Support: Handles projects with multiple services at once.
  • Ready to Use: Generated Dockerfile is auto-committed to GitLab, ready to build immediately.

Build Environment

When to Use

  • New projects: Containerize a project started without a Dockerfile.
  • Legacy migration: Convert an existing project to Docker-based.
  • Monorepo setup: Containerize multiple services at once.
  • Rapid prototyping: Quickly set up a build environment with optimized templates.
Already have a Dockerfile?

Projects that already have a Dockerfile skip Build Wizard and start building directly. If you want to replace an existing Dockerfile, you can generate a new one in Build Wizard.


Supported Frameworks

Node.js

  • Next.js (SSR, port 3000): React full-stack framework supporting App Router and Pages Router.
  • React (SPA, port 80): React SPA including CRA and Vite
  • Vue.js (SPA, port 80): Vue 2/3 applications.
  • Angular (SPA, port 80): Angular CLI projects.
  • NestJS (API, port 3000): TypeScript backend framework
  • Express.js (API, port 3000): Node.js web framework

Python

  • FastAPI (API, port 8000): High-performance async API framework
  • Django (API, port 8000): Python full-stack framework
  • Flask (API, port 5000): Lightweight micro framework
  • Streamlit (SSR, port 8501): Data app/dashboard framework

Java

  • Spring Boot (API, port 8080): Java enterprise framework
  • Quarkus (API, port 8080): Cloud-native Java

Other Languages

  • Go (Compiled, port 8080): Uses go mod for package management.
  • Rust (Compiled, port 8080): Uses cargo for package management.
  • .NET/C# (Compiled, port 8080): Uses dotnet for package management.
  • Ruby (API, port 3000): Uses bundler for package management.
  • PHP (API, port 80): Uses composer for package management.
  • Static Site (Static, port 80): No package manager required.

Understanding Build Types

Build Wizard automatically selects the appropriate build type based on the framework.

  • SPA (Static site / Single Page Application): Final image contains Nginx + built static files.
  • SSR (Server-side rendering): Final image contains Node.js runtime + application.
  • API (Backend API server): Final image contains runtime + application code.
  • Compiled (Compiled language like Go, Rust): Final image contains binary only (lightweight image)
  • Static (Pure static files): Final image contains Nginx + HTML/CSS/JS
Why Build Type Matters

Dockerfile structure, base image, and run commands differ based on build type. For example, SPA is served via Nginx after building, while SSR handles requests directly through a Node.js server.


Build Wizard Flow

Step 0: Project Analysis → Step 1: Build Settings → Step 2: File Preview → Step 3: GitLab Commit
flowchart LR
A[Open Build Wizard] --> B[Detect Project Type]
B --> C{Monorepo?}
C -->|Yes| D[Select Services]
C -->|No| E[Single Config]
D --> F[Generate Template]
E --> F
F --> G[Edit Files]
G --> H[Commit to GitLab]
H --> I[Ready to Build]

Step 0: Open Build Wizard

How to Open

  1. Navigate to the [Service Management] page
  2. Click the Build stage on the row for the service to configure
  3. The Build Wizard modal opens automatically.

Auto-open Conditions

  • No Dockerfile: Build Wizard opens automatically.
  • Dockerfile present: Build starts immediately.
  • Only docker-compose.yml: Build Wizard opens (notification that Dockerfile is needed)
  • Steps display: Shows current progress (0~3)
  • Git URL: Repository URL to analyze (auto-filled)
  • Branch: Target branch (pulled from service settings)
  • Detect project type button: Click to start analysis.

Step 1: Detect Project Type

1.1 Run Detection

Click the Detect Project Type button and KIWI analyzes the GitLab repository.

1.2 Analysis Items

  • Project type: Detected by the presence of config files. (e.g., package.json → Node.js)
  • Framework: Detected by dependency analysis. (e.g., next package → Next.js)
  • Package manager: Verified by lock file. (e.g., yarn.lock → Yarn)
  • TypeScript: Whether tsconfig.json exists. (Yes/No)
  • Build type: Determined by framework. (e.g., Next.js → SSR)
  • Monorepo: Detected by sub-directory analysis. (e.g., frontend/, backend/)

1.3 Detection Result Screen

Single Project

Project analysis complete!

Project type: Node.js
Framework: Next.js
Package manager: npm
Build type: SSR (Server-side rendering)
TypeScript: Yes
Default port: 3000

Monorepo

Monorepo detected: 3 sub-projects found

┌────────────┬───────────┬─────────────┬──────────┐
│ Path │ Type │ Framework │ Select │
├────────────┼───────────┼─────────────┼──────────┤
│ frontend/ │ Node.js │ React │ ✓ │
│ backend/ │ Python │ FastAPI │ ✓ │
│ admin/ │ Node.js │ Vue.js │ ✓ │
└────────────┴───────────┴─────────────┴──────────┘

1.4 Existing File Warning

If a Dockerfile or docker-compose.yml already exists:

Existing Build Files Found

Files already exist: Dockerfile, docker-compose.yml Proceeding will overwrite these files.


Step 2: Build Settings

2.1 Single Project Settings

Basic Settings

  • Project type: Detected language. Editable. (e.g., Node.js)
  • Service name: Name used in docker-compose. (e.g., my-app)
  • Port number: Port exposed by the container. (e.g., 3000)

Language Version Settings

  • Version: Language runtime version. (e.g., Node.js 18, 20, 22)
  • Base OS: Container base OS. (alpine, slim, bullseye)
Version Selection Guide
  • alpine: Minimum image size (fewer vulnerabilities in security scans)
  • slim: Lightweight Debian-based (better compatibility)
  • bullseye/bookworm: Full Debian (all packages available)

Advanced Options (Collapse section)

  • Health Check (enabled by default): Adds container health checks. Required in production environments.
  • Non-root User (enabled by default): Run as a non-root user. Recommended for security.

2.2 Monorepo Settings

Service Selection Table

  • Select: Checkbox for services to build
  • Path: Sub-project directory path
  • Project type: Detected language
  • Framework: Detected framework
  • Version: Selectable language version.
  • Base OS: Selectable OS
  • Port: Per-service port settings.

Advanced Options Per Service

Individually configurable for each service:

  • Enable/disable Health Check
  • Enable/disable Non-root User

2.3 Generate Template

Click the Generate Template button to create a Dockerfile and docker-compose.yml matching the settings.


Step 3: File Preview and Editing

3.1 Monaco Editor

Generated files are displayed in Monaco Editor (VS Code-based).

  • Syntax highlighting: Dockerfile and YAML syntax highlighting.
  • Autocomplete: Keyword autocomplete support
  • Error checking: Real-time syntax error display
  • Line numbers: Line number display

3.2 Generated Files

Single Project

  • Dockerfile (root): Container image build
  • docker-compose.yml (root): Local development orchestration.

Monorepo

  • Dockerfile (each service directory): Per-service image build
  • docker-compose.yml (root): Full service orchestration.

3.3 Dockerfile Examples

Next.js (SSR)

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production=false
COPY . .
RUN npm run build

# Production stage
FROM node:20-alpine AS production
WORKDIR /app

# Non-root user setup
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001

COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder /app/public ./public

USER nextjs
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/ || exit 1

CMD ["node", "server.js"]

React (SPA)

# Build stage
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Production stage
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost/ || exit 1

CMD ["nginx", "-g", "daemon off;"]

FastAPI (Python)

FROM python:3.11-slim

WORKDIR /app

# Non-root user
RUN addgroup --system app && adduser --system --group app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

RUN chown -R app:app /app
USER app

EXPOSE 8000

HEALTHCHECK --interval=30s --timeout=3s \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Spring Boot (Java)

# Build stage
FROM eclipse-temurin:17-jdk AS builder
WORKDIR /app
COPY . .
RUN ./gradlew bootJar --no-daemon

# Production stage
FROM eclipse-temurin:17-jre
WORKDIR /app

RUN addgroup --system spring && adduser --system --group spring

COPY --from=builder /app/build/libs/*.jar app.jar

RUN chown -R spring:spring /app
USER spring

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s \
CMD curl -f http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java", "-jar", "app.jar"]

Go

# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# Production stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates

WORKDIR /app
RUN addgroup -S app && adduser -S app -G app

COPY --from=builder /app/main .

RUN chown -R app:app /app
USER app

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1

CMD ["./main"]

3.4 docker-compose.yml Examples

Single Service

version: '3.8'
services:
my-app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=production
restart: unless-stopped

Monorepo (Multiple Services)

version: '3.8'
services:
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "3000:3000"
depends_on:
- backend
restart: unless-stopped

backend:
build:
context: ./backend
dockerfile: Dockerfile
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://db:5432/app
restart: unless-stopped

admin:
build:
context: ./admin
dockerfile: Dockerfile
ports:
- "3001:80"
restart: unless-stopped

3.5 File Customization

You can directly edit the generated files as needed.

Common modifications:

  • Add environment variables: ENV NODE_ENV=production
  • Change port: EXPOSE 8080
  • Install additional packages: RUN apk add --no-cache curl
  • Change build command: RUN npm run build:prod
  • Volume mount: Add volumes to docker-compose.

Step 4: GitLab Commit

4.1 Execute Commit

Click the Commit to GitLab button to automatically commit the generated files to the repository.

4.2 Commit Information

  • Commit message: chore: Add Dockerfile generated by KIWI Build Wizard
  • Branch: Default branch configured in the service.
  • Author: KIWI System

4.3 Generated Files

  • Single project: Dockerfile, docker-compose.yml
  • Monorepo: frontend/Dockerfile, backend/Dockerfile, docker-compose.yml

4.4 Commit Complete

  1. Verify the "Build environment files have been committed to GitLab!" message
  2. Build Wizard closes automatically.
  3. Now click the Build stage again to start the build

Real-world Usage Scenarios

Scenario 1: Containerizing a New Next.js Project

Situation: You want to deploy a project created with create-next-app using KIWI.

Steps:

  1. Register a service in [Service Management] (enter Git URL)
  2. Click Build → Build Wizard opens automatically.
  3. Click Detect project type
  4. Review detection results: Next.js, npm, SSR type
  5. Select version: Node.js 20, alpine
  6. Advanced options: Health Check checked, Non-root checked.
  7. Click Generate Template
  8. Review Dockerfile content (Next.js standalone mode optimized)
  9. Click Commit to GitLab
  10. Ready to build!

Scenario 2: Monorepo Project Setup

Situation: Deploying a monorepo with a Frontend(React) + Backend(FastAPI) structure.

Steps:

  1. Enter monorepo Git URL when registering the service.
  2. Click Build → Build Wizard opens.
  3. Click Detect project type
  4. Monorepo detected: 2 sub-projects.
  5. Configure in the service selection table:
    • frontend/: React, Node.js 20, alpine, port 3000
    • backend/: FastAPI, Python 3.11, slim, port 8000
  6. Click Generate Template
  7. Review Dockerfile for each service and root docker-compose.yml
  8. Click Commit to GitLab
  9. Both services ready to build!

Scenario 3: Legacy Spring Boot App Migration

Situation: Migrating an existing Spring Boot project to containers.

Steps:

  1. Register service
  2. Click Build → Build Wizard opens.
  3. Detect project type: Spring Boot, Gradle.
  4. Verify settings:
    • Java version: 17 (based on project's sourceCompatibility)
    • Base OS: Eclipse Temurin JRE
  5. Advanced options: Health Check checked (using Spring Actuator)
  6. Click Generate Template
  7. Review and modify Dockerfile:
    • Customize Gradle build command if needed.
    • Verify Actuator health endpoint path
  8. Click Commit to GitLab

Troubleshooting

Project Type Detection Failure

  • Detected as "Unknown" type: No standard config files. Add package.json, pom.xml, go.mod, etc.
  • Framework not detected: Dependency analysis failed. Manually select the framework.
  • Analysis timeout: Large repository. Limit scope to a specific branch.

GitLab Connection Error

  • 401 Unauthorized: Token expired. Renew the GitLab Access Token.
  • 403 Forbidden: Insufficient permissions. Check api, write_repository permissions for the token.
  • 404 Not Found: Repository/branch not found. Verify the Git URL and branch name.

Commit Failure

  • "Protected branch": Branch is protected. Use a different branch or remove protection.
  • "Merge conflict": File conflict occurred. Delete the existing files and retry.
  • "File too large": Large file exists. Add exclusion settings to .gitignore.

Build File Generation Error

  • Invalid port: Auto-detection error. Manually specify the port number.
  • Build command error: Non-standard script. Edit the Dockerfile directly.
  • Dependency installation failure: Private registry issue. Add authentication settings to Dockerfile.
  • Sub-projects not detected: Non-standard structure. Add config files to each sub-directory.
  • Inter-service dependencies: docker-compose configuration needed. Manually add depends_on.
  • Shared code references: Build context issue. Consider a root-level Dockerfile.

Best Practices

Dockerfile Optimization

  1. Use multi-stage builds: Exclude build tools from production image
  2. Leverage layer caching: Copy frequently changing files last
  3. Use alpine base: Minimize image size
  4. Non-root user: Enhance container security.
  5. Add health check: Support K8s/Docker health management.

Security Considerations

  1. Do not hardcode secrets in Dockerfile.
  2. Exclude sensitive files with .dockerignore
  3. Run as non-root user.
  4. Update base images regularly.
  5. Exclude source code with multi-stage builds.