スキル一覧に戻る
fajjarnr

container-specialist

by fajjarnr

0🍴 0📅 2026年1月25日
GitHubで見るManusで実行

SKILL.md


name: container-specialist description: Skill untuk membuat dan mengelola container images menggunakan best practices - UBI9 base images, multi-stage builds, security hardening, dan OpenShift compatibility.

Container Specialist Skill

Skill ini memberikan panduan komprehensif untuk membuat container images yang aman, efisien, dan production-ready untuk PayU Digital Banking Platform.

When to Use This Skill

Gunakan skill ini ketika:

  • Membuat Dockerfile baru untuk microservice
  • Memperbaiki atau mengoptimasi Dockerfile yang ada
  • Memastikan container image memenuhi standar keamanan
  • Menyiapkan images untuk deployment ke OpenShift
  • Troubleshooting container build atau runtime issues

🔒 Mandatory Requirements

1. Base Image: Red Hat UBI9

[!IMPORTANT] WAJIB menggunakan Red Hat Universal Base Image 9 (UBI9) untuk semua container images.

Alasan:

  • Certified untuk Red Hat OpenShift
  • Security updates dan patches dari Red Hat
  • FIPS 140-2 compliant
  • Smaller attack surface dibanding full OS images

Official UBI9 Images:

ImageUse CaseSize
registry.access.redhat.com/ubi9/openjdk-21:1.20Build stage (Java 21)~400MB
registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20Runtime stage (Java 21)~200MB
registry.access.redhat.com/ubi9/ubi-minimalMinimal base~100MB
registry.access.redhat.com/ubi9/python-312Python 3.12~350MB

❌ DILARANG menggunakan:

  • eclipse-temurin:*-alpine
  • openjdk:*
  • amazoncorretto:*
  • Non-UBI base images

2. Multi-stage Build

[!IMPORTANT] WAJIB menggunakan multi-stage build untuk memisahkan build dan runtime environments.

Benefits:

  • Smaller final image size (50-80% reduction)
  • No build tools in production image
  • Reduced attack surface
  • Better layer caching

Structure:

####
# Build stage
####
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20 AS build
# Build application here...

####
# Runtime stage
####
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20
# Only copy built artifacts
COPY --from=build --chown=185 /build/target/*.jar /deployments/app.jar

3. Non-root User

[!CAUTION] DILARANG menjalankan container sebagai root user di runtime stage.

Default User untuk UBI Images:

  • User ID: 185 (jboss user)
  • Group ID: 0 (root group - required for OpenShift)

Pattern:

# Build stage - root OK untuk install dependencies
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20 AS build
USER root
RUN microdnf install -y maven && microdnf clean all
# ... build steps ...

# Runtime stage - HARUS non-root
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20
USER 185

OpenShift Compatibility:

  • OpenShift runs containers with arbitrary UID
  • Files must be readable/writable by group 0
  • Use --chown=185:0 atau --chown=185

4. Mandatory Labels

[!IMPORTANT] WAJIB menambahkan labels berikut untuk traceability dan documentation.

LABEL maintainer="backend-team@payu.id"
LABEL description="PayU Service Name - Brief Description"
LABEL version="1.0.0"

Optional but Recommended Labels:

LABEL org.opencontainers.image.title="payu-service-name"
LABEL org.opencontainers.image.description="Detailed description"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.vendor="PayU Indonesia"
LABEL org.opencontainers.image.url="https://github.com/payu/service"
LABEL org.opencontainers.image.source="https://github.com/payu/service"
LABEL org.opencontainers.image.licenses="Proprietary"

5. Health Checks

[!IMPORTANT] WAJIB menambahkan HEALTHCHECK untuk container orchestration.

Spring Boot Services:

HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:${PORT}/actuator/health || exit 1

Quarkus Services:

HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
    CMD curl -f http://localhost:${PORT}/q/health || exit 1

Parameters:

ParameterValueDescription
--interval30sTime between health checks
--timeout3sMaximum time for health check
--start-period30-60sGrace period before first check
--retries3Consecutive failures before unhealthy

📁 Dockerfile Templates

Template: Spring Boot Service

####
# Build stage - Using Red Hat UBI9 OpenJDK 21 with Maven
####
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20 AS build

USER root
WORKDIR /build

# Install Maven
RUN microdnf install -y maven && microdnf clean all

# Copy pom.xml first for dependency caching
COPY pom.xml ./

# Download dependencies (cached layer)
RUN mvn dependency:go-offline -B

# Copy source code
COPY src ./src

# Build the application
RUN mvn package -DskipTests -Dspring-boot.build-image.skip=true && \
    mv target/*.jar target/app.jar

####
# Runtime stage - Using minimal UBI9 OpenJDK 21 runtime
####
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20

LABEL maintainer="backend-team@payu.id"
LABEL description="PayU [SERVICE_NAME] - [DESCRIPTION]"
LABEL version="1.0.0"

# Use non-root user (185 is the default jboss user in UBI images)
USER 185

WORKDIR /deployments

# Copy the built artifact from build stage
COPY --from=build --chown=185 /build/target/app.jar /deployments/app.jar

# Expose the service port
EXPOSE [PORT]

# JVM configuration for containers
ENV JAVA_OPTS="-XX:+UseContainerSupport \
    -XX:MaxRAMPercentage=75.0 \
    -XX:InitialRAMPercentage=50.0 \
    -XX:+UseG1GC \
    -XX:MaxGCPauseMillis=200 \
    -XX:+HeapDumpOnOutOfMemoryError \
    -XX:HeapDumpPath=/deployments/heapdump.hprof \
    -Djava.security.egd=file:/dev/./urandom"

# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=60s --retries=3 \
    CMD curl -f http://localhost:[PORT]/actuator/health || exit 1

# Run the application
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /deployments/app.jar"]

Template: Quarkus Service (Fast-JAR)

####
# Build stage - Using Red Hat UBI9 OpenJDK 21 with Maven
####
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20 AS build

USER root
WORKDIR /build

# Install Maven
RUN microdnf install -y maven && microdnf clean all

# Copy pom.xml first for dependency caching
COPY pom.xml ./

# Download dependencies (cached layer)
RUN mvn dependency:go-offline -B

# Copy source code
COPY src ./src

# Build the Quarkus application (fast-jar format)
RUN mvn package -DskipTests

####
# Runtime stage - Using minimal UBI9 OpenJDK 21 runtime
####
FROM registry.access.redhat.com/ubi9/openjdk-21-runtime:1.20

LABEL maintainer="backend-team@payu.id"
LABEL description="PayU [SERVICE_NAME] - [DESCRIPTION]"
LABEL version="1.0.0"

# Use non-root user (185 is the default jboss user in UBI images)
USER 185

WORKDIR /deployments

# Copy Quarkus fast-jar structure
COPY --from=build --chown=185 /build/target/quarkus-app/lib/ /deployments/lib/
COPY --from=build --chown=185 /build/target/quarkus-app/*.jar /deployments/
COPY --from=build --chown=185 /build/target/quarkus-app/app/ /deployments/app/
COPY --from=build --chown=185 /build/target/quarkus-app/quarkus/ /deployments/quarkus/

# Expose the service port
EXPOSE [PORT]

# JVM configuration for Quarkus
ENV JAVA_OPTS="-XX:+UseContainerSupport \
    -XX:MaxRAMPercentage=75.0 \
    -XX:+UseG1GC \
    -XX:MaxGCPauseMillis=100 \
    -Dquarkus.http.host=0.0.0.0 \
    -Djava.util.logging.manager=org.jboss.logmanager.LogManager"

# Health check using Quarkus health endpoint
HEALTHCHECK --interval=30s --timeout=3s --start-period=30s --retries=3 \
    CMD curl -f http://localhost:[PORT]/q/health || exit 1

# Run the Quarkus application
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar /deployments/quarkus-run.jar"]

Template: Quarkus Native (GraalVM)

####
# Build stage - GraalVM Native Image
####
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20 AS build

USER root
WORKDIR /build

# Install Maven and native-image requirements
RUN microdnf install -y maven gcc glibc-devel zlib-devel && \
    microdnf clean all

COPY pom.xml ./
RUN mvn dependency:go-offline -B

COPY src ./src
RUN mvn package -DskipTests -Pnative

####
# Runtime stage - Minimal for native
####
FROM registry.access.redhat.com/ubi9/ubi-minimal:9.3

LABEL maintainer="backend-team@payu.id"
LABEL description="PayU [SERVICE_NAME] - [DESCRIPTION] (Native)"
LABEL version="1.0.0"

USER 185
WORKDIR /deployments

COPY --from=build --chown=185 /build/target/*-runner /deployments/app

EXPOSE [PORT]

HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
    CMD curl -f http://localhost:[PORT]/q/health || exit 1

ENTRYPOINT ["/deployments/app", "-Dquarkus.http.host=0.0.0.0"]

⚙️ JVM Configuration

Container-Aware JVM Settings

ENV JAVA_OPTS="-XX:+UseContainerSupport \
    -XX:MaxRAMPercentage=75.0 \
    -XX:InitialRAMPercentage=50.0 \
    -XX:+UseG1GC \
    -XX:MaxGCPauseMillis=200 \
    -XX:+HeapDumpOnOutOfMemoryError \
    -XX:HeapDumpPath=/deployments/heapdump.hprof \
    -Djava.security.egd=file:/dev/./urandom"

Explanation:

SettingValuePurpose
UseContainerSupportenabledJVM respects container memory limits
MaxRAMPercentage75%Maximum heap as % of container memory
InitialRAMPercentage50%Initial heap as % of container memory
UseG1GCenabledG1 garbage collector (recommended)
MaxGCPauseMillis100-200msTarget GC pause time
HeapDumpOnOutOfMemoryErrorenabledDump heap on OOM for debugging
java.security.egd/dev/./urandomFaster random number generation

🔐 Security Best Practices

1. No Secrets in Images

# ❌ SALAH - secrets di image
ENV DATABASE_PASSWORD=mysecret

# ✅ BENAR - secrets dari environment/secrets
ENV DATABASE_PASSWORD=""

2. Clean Up After Install

# ✅ BENAR - clean up dalam satu layer
RUN microdnf install -y maven && \
    mvn package -DskipTests && \
    microdnf remove -y maven && \
    microdnf clean all && \
    rm -rf /var/cache/yum

3. Use .dockerignore

# .dockerignore
.git
.gitignore
*.md
Dockerfile
.dockerignore
target/
!target/*.jar
node_modules/
.env
*.log

4. Pin Image Versions

# ✅ BENAR - pinned version
FROM registry.access.redhat.com/ubi9/openjdk-21:1.20

# ❌ SALAH - floating tag
FROM registry.access.redhat.com/ubi9/openjdk-21:latest

📊 Port Assignments

ServicePortProtocol
account-service8001HTTP
auth-service8002HTTP
transaction-service8003HTTP
wallet-service8004HTTP
billing-service8005HTTP
notification-service8006HTTP
gateway-service8080HTTP
bi-fast-simulator8090HTTP
dukcapil-simulator8091HTTP
qris-simulator8092HTTP

🏗️ Build Commands

Build Image

# Build dengan tag
docker build -t payu/account-service:1.0.0 ./backend/account-service

# Build dengan multiple tags
docker build \
  -t payu/account-service:1.0.0 \
  -t payu/account-service:latest \
  ./backend/account-service

# Build dengan build args
docker build \
  --build-arg MAVEN_OPTS="-Xmx1g" \
  -t payu/account-service:1.0.0 \
  ./backend/account-service

Build for OpenShift

# Build menggunakan Podman (OpenShift native)
podman build -t payu/account-service:1.0.0 ./backend/account-service

# Push to OpenShift internal registry
podman push payu/account-service:1.0.0 \
  image-registry.openshift-image-registry.svc:5000/payu-dev/account-service:1.0.0

🔍 Verification Checklist

Sebelum merge, pastikan Dockerfile memenuhi checklist berikut:

  • Base image menggunakan UBI9 (registry.access.redhat.com/ubi9/...)
  • Multi-stage build (minimal 2 stages: build dan runtime)
  • Non-root user di runtime stage (USER 185)
  • Labels: maintainer, description, version
  • HEALTHCHECK dengan parameter yang sesuai
  • EXPOSE dengan port yang benar
  • JVM container-aware settings (MaxRAMPercentage, UseContainerSupport)
  • Tidak ada secrets hardcoded
  • .dockerignore file exists
  • Image version di-pin (tidak menggunakan :latest)

ResourcePath
PayU Development Skill.agent/skills/payu-development/SKILL.md
Code Review Skill.agent/skills/code-review/SKILL.md
ArchitectureARCHITECTURE.md

Last Updated: January 2026

スコア

総合スコア

50/100

リポジトリの品質指標に基づく評価

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

0/10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

3ヶ月以内に更新がある

0/10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

0/5

レビュー

💬

レビュー機能は近日公開予定です