Skip to content

docker

Comprehensive instructions for building secure, compliant Docker containers within Optum using golden images, SaaS Artifactory authentication, and enterprise best practices.

IDE:
claude
codex
vscode
Version:
0.0.0

Docker Container Building Instructions for Optum

Your Mission

As GitHub Copilot, you are an expert in building Docker containers within Optum's enterprise environment. Your goal is to guide developers in creating secure, compliant, and efficient containers using Optum's golden images, SaaS Artifactory, and enterprise security standards.

Core Requirements

1. Golden Image Mandate

  • MUST USE: Optum-approved golden images from edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/
  • NO EXTERNAL IMAGES: Never use Docker Hub, Alpine, Ubuntu, or other public registry images directly
  • Chain Guard Verified: All golden images include SBOM, vulnerability scanning, and supply chain attestation

2. Artifactory Authentication

  • Authentication Required: Must authenticate with SaaS Artifactory for golden image access
  • OIDC Preferred: Use OIDC authentication in CI/CD pipelines
  • Local Development: Use token-based authentication for local builds

3. Security Standards

  • Non-Root Users: Always run containers as non-root users
  • Multi-Stage Builds: Use multi-stage builds to minimize final image size
  • Health Checks: Implement comprehensive health checks
  • Resource Limits: Define appropriate resource constraints

Docker Authentication

1. CI/CD Pipeline Authentication

# GitHub Actions Example
- name: Configure Artifactory Connection
  id: artifactory-setup
  uses: uhg-pipelines/epl-jf/configure-saas-connection@latest
  with:
    jfrog-project-key: your-project-key
    
# Docker login is handled automatically by the action
# Both central and edge registries are configured

2. Local Development Authentication

#!/bin/bash
# login-artifactory.sh
# Authenticate with Optum SaaS Artifactory for local development

set -e

echo "Logging into Optum SaaS Artifactory..."

# Central registry (for pushing)
docker login centraluhg.jfrog.io

# Edge registry (for pulling golden images)
docker login edgeinternal1uhg.optum.com:443

echo "✅ Authentication successful!"
echo "You can now pull golden images and push to project repositories"

3. Authentication Script with Token

#!/bin/bash
# auth-with-token.sh
# Authenticate using access token (for automation)

if [ -z "$ARTIFACTORY_TOKEN" ]; then
    echo "❌ Error: ARTIFACTORY_TOKEN environment variable is required"
    exit 1
fi

if [ -z "$ARTIFACTORY_USER" ]; then
    echo "❌ Error: ARTIFACTORY_USER environment variable is required"
    exit 1
fi

echo "Authenticating with Artifactory using token..."

# Login to edge registry for golden images
echo "$ARTIFACTORY_TOKEN" | docker login edgeinternal1uhg.optum.com:443 \
    --username "$ARTIFACTORY_USER" --password-stdin

# Login to central registry for publishing
echo "$ARTIFACTORY_TOKEN" | docker login centraluhg.jfrog.io \
    --username "$ARTIFACTORY_USER" --password-stdin

echo "✅ Token authentication successful!"

Dockerfile Examples

1. Node.js Application (Multi-Stage)

# syntax=docker/dockerfile:1
# Build stage using golden image
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/node/dev:18 AS builder

WORKDIR /app

# Copy package files
COPY package*.json ./

# Install dependencies
RUN npm ci --only=production && npm cache clean --force

# Copy source code
COPY src/ ./src/
COPY public/ ./public/
COPY tsconfig.json ./

# Build application
RUN npm run build

# Production stage using minimal golden image
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/node/dev:18-slim AS production

WORKDIR /app

# Copy built application and production dependencies
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./

# Create non-root user for security
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set proper file ownership
RUN chown -R appuser:appgroup /app

# Create directory for application data
RUN mkdir -p /app/data && chown -R appuser:appgroup /app/data

# Switch to non-root user
USER appuser

# Expose application port
EXPOSE 3000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD curl --fail http://localhost:3000/health || exit 1

# Start application
CMD ["node", "dist/main.js"]

2. Python Application (Flask/FastAPI)

# syntax=docker/dockerfile:1
# Build stage
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/python:latest-dev  AS builder

WORKDIR /app

# Copy requirements first for better layer caching
COPY requirements.txt requirements-dev.txt ./

# Install dependencies
RUN pip install --no-cache-dir --user -r requirements.txt

# Production stage
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/python:latest-slim AS production

WORKDIR /app

# Copy installed packages from builder stage
COPY --from=builder /root/.local /root/.local

# Copy application code
COPY src/ ./src/
COPY config/ ./config/

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set proper permissions
RUN chown -R appuser:appgroup /app

# Create application data directory
RUN mkdir -p /app/logs /app/uploads && \
    chown -R appuser:appgroup /app/logs /app/uploads

# Switch to non-root user
USER appuser

# Update PATH to include user-installed packages
ENV PATH=/root/.local/bin:$PATH

# Expose application port
EXPOSE 8000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD curl --fail http://localhost:8000/health || exit 1

# Start application
CMD ["python", "-m", "src.main"]

3. Java Application (Spring Boot)

# syntax=docker/dockerfile:1
# Build stage
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/amazon-corretto-jdk/dev:17 AS builder

WORKDIR /app

# Copy Maven/Gradle files
COPY pom.xml ./
COPY mvnw ./
COPY .mvn .mvn

# Download dependencies (for better layer caching)
RUN ./mvnw dependency:go-offline -B

# Copy source code
COPY src ./src

# Build application
RUN ./mvnw clean package -DskipTests

# Production stage using JRE
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/amazon-corretto-jre/dev:17 AS production

WORKDIR /app

# Copy built JAR from builder stage
COPY --from=builder /app/target/*.jar app.jar

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set proper permissions
RUN chown -R appuser:appgroup /app

# Create application directories
RUN mkdir -p /app/logs /app/config && \
    chown -R appuser:appgroup /app/logs /app/config

# Switch to non-root user
USER appuser

# Expose application port
EXPOSE 8080

# Health check using Spring Boot Actuator
HEALTHCHECK --interval=30s --timeout=10s --start-period=45s --retries=3 \
    CMD curl --fail http://localhost:8080/actuator/health || exit 1

# JVM tuning for containers
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"

# Start application
CMD ["java", "-jar", "app.jar"]

4. .NET Core Application

# syntax=docker/dockerfile:1
# Build stage
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/dotnet-sdk/dev:8.0 AS builder

WORKDIR /app

# Copy project files
COPY *.csproj ./
RUN dotnet restore

# Copy source code
COPY . ./

# Build and publish
RUN dotnet publish -c Release -o out

# Production stage using runtime image
FROM edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/aspnet-runtime/dev:8.0 AS production

WORKDIR /app

# Copy built application
COPY --from=builder /app/out .

# Create non-root user
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# Set proper permissions
RUN chown -R appuser:appgroup /app

# Switch to non-root user
USER appuser

# Expose application port
EXPOSE 5000

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD curl --fail http://localhost:5000/health || exit 1

# Start application
ENTRYPOINT ["dotnet", "YourApp.dll"]

Build Scripts

1. Complete Build Script

#!/bin/bash
# build-container.sh
# Complete container build script for Optum environment

set -e

# Configuration
PROJECT_NAME="your-project"
VERSION=${1:-"latest"}
REGISTRY="edgeinternal1uhg.optum.com:443"
DOCKER_REPO="your-project-docker-np-loc"

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${YELLOW}🏗️  Building ${PROJECT_NAME} container v${VERSION}${NC}"

# Step 1: Verify Docker is running
if ! docker info > /dev/null 2>&1; then
    echo -e "${RED}❌ Docker is not running. Please start Docker Desktop.${NC}"
    exit 1
fi

# Step 2: Authenticate with Artifactory
echo -e "${YELLOW}🔐 Authenticating with Optum Artifactory...${NC}"
if ! docker login $REGISTRY; then
    echo -e "${RED}❌ Failed to authenticate with Artifactory${NC}"
    exit 1
fi

# Step 3: Pull latest golden images
echo -e "${YELLOW}📥 Pulling latest golden images...${NC}"
docker pull edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/node/dev:18
docker pull edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/node/dev:18-slim

# Step 4: Build the application image
echo -e "${YELLOW}🔨 Building application image...${NC}"
IMAGE_TAG="${REGISTRY}/${DOCKER_REPO}/${PROJECT_NAME}:${VERSION}"

docker build \
    --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
    --build-arg VERSION=${VERSION} \
    --build-arg VCS_REF=$(git rev-parse --short HEAD) \
    -t ${IMAGE_TAG} \
    .

# Step 5: Security scan (if available)
echo -e "${YELLOW}🔍 Running security scan...${NC}"
if command -v trivy &> /dev/null; then
    trivy image --exit-code 0 --severity HIGH,CRITICAL ${IMAGE_TAG}
else
    echo -e "${YELLOW}⚠️  Trivy not installed. Consider adding security scanning.${NC}"
fi

# Step 6: Test the image
echo -e "${YELLOW}🧪 Testing the image...${NC}"
CONTAINER_ID=$(docker run -d -p 3000:3000 ${IMAGE_TAG})
sleep 10

if curl -f http://localhost:3000/health; then
    echo -e "${GREEN}✅ Health check passed${NC}"
    docker stop ${CONTAINER_ID}
    docker rm ${CONTAINER_ID}
else
    echo -e "${RED}❌ Health check failed${NC}"
    docker logs ${CONTAINER_ID}
    docker stop ${CONTAINER_ID}
    docker rm ${CONTAINER_ID}
    exit 1
fi

# Step 7: Push to registry
echo -e "${YELLOW}📤 Pushing to registry...${NC}"
if docker push ${IMAGE_TAG}; then
    echo -e "${GREEN}✅ Successfully pushed ${IMAGE_TAG}${NC}"
else
    echo -e "${RED}❌ Failed to push image${NC}"
    exit 1
fi

# Step 8: Cleanup local images (optional)
read -p "Clean up local build images? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
    docker image prune -f
    echo -e "${GREEN}✅ Cleaned up local images${NC}"
fi

echo -e "${GREEN}🎉 Build complete! Image: ${IMAGE_TAG}${NC}"

2. Development Build Script

#!/bin/bash
# dev-build.sh
# Quick development build script

set -e

PROJECT_NAME="your-project"
DEV_TAG="dev"

echo "🚀 Quick development build..."

# Build with dev tag
docker build -t ${PROJECT_NAME}:${DEV_TAG} .

# Run locally for testing
echo "Starting local development container..."
docker run -d \
    --name ${PROJECT_NAME}-dev \
    -p 3000:3000 \
    -v $(pwd)/src:/app/src \
    -e NODE_ENV=development \
    ${PROJECT_NAME}:${DEV_TAG}

echo "✅ Development container running at http://localhost:3000"
echo "Container name: ${PROJECT_NAME}-dev"
echo ""
echo "Useful commands:"
echo "  docker logs ${PROJECT_NAME}-dev"
echo "  docker exec -it ${PROJECT_NAME}-dev /bin/sh"
echo "  docker stop ${PROJECT_NAME}-dev && docker rm ${PROJECT_NAME}-dev"

3. CI/CD Build Script

#!/bin/bash
# ci-build.sh
# CI/CD pipeline build script

set -e

# Required environment variables
: ${JFROG_PROJECT_KEY:?"JFROG_PROJECT_KEY environment variable is required"}
: ${BUILD_NUMBER:?"BUILD_NUMBER environment variable is required"}
: ${GIT_COMMIT:?"GIT_COMMIT environment variable is required"}

PROJECT_NAME="your-project"
VERSION="${BUILD_NUMBER}"
IMAGE_TAG="edgeinternal1uhg.optum.com:443/${JFROG_PROJECT_KEY}-docker-np-loc/${PROJECT_NAME}:${VERSION}"

echo "🏗️ CI/CD Build - ${PROJECT_NAME}:${VERSION}"

# Build with comprehensive metadata
docker build \
    --build-arg BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ') \
    --build-arg VERSION=${VERSION} \
    --build-arg VCS_REF=${GIT_COMMIT} \
    --build-arg BUILD_NUMBER=${BUILD_NUMBER} \
    --label "org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
    --label "org.opencontainers.image.version=${VERSION}" \
    --label "org.opencontainers.image.revision=${GIT_COMMIT}" \
    --label "org.opencontainers.image.source=https://github.com/OptumInsight-Platform/${PROJECT_NAME}" \
    --label "optum.project=${JFROG_PROJECT_KEY}" \
    --label "optum.build.number=${BUILD_NUMBER}" \
    -t ${IMAGE_TAG} \
    .

# Tag with latest for current branch
if [ "${GITHUB_REF}" = "refs/heads/main" ]; then
    LATEST_TAG="edgeinternal1uhg.optum.com:443/${JFROG_PROJECT_KEY}-docker-np-loc/${PROJECT_NAME}:latest"
    docker tag ${IMAGE_TAG} ${LATEST_TAG}
    docker push ${LATEST_TAG}
fi

# Push versioned image
docker push ${IMAGE_TAG}

echo "✅ Successfully built and pushed ${IMAGE_TAG}"

Docker Compose for Local Development

1. Basic Docker Compose

# docker-compose.yml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=development
      - LOG_LEVEL=debug
    volumes:
      - ./src:/app/src:ro
      - ./config:/app/config:ro
      - app_data:/app/data
    depends_on:
      - database
      - redis
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

  database:
    image: edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/postgres/dev:15
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=myapp
      - POSTGRES_PASSWORD=development
    volumes:
      - postgres_data:/var/lib/postgresql/data
    ports:
      - "5432:5432"

  redis:
    image: edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/redis/dev:7
    volumes:
      - redis_data:/data
    ports:
      - "6379:6379"

volumes:
  app_data:
  postgres_data:
  redis_data:

networks:
  default:
    name: myapp-network

Best Practices

1. Dockerfile Optimization

  • Use multi-stage builds to minimize final image size
  • Copy dependency files before source code for better layer caching
  • Combine RUN commands to reduce layers
  • Use specific golden image tags instead of latest
  • Clean up package caches in the same RUN command

2. Security Practices

  • Always run as non-root user
  • Use read-only root filesystem when possible
  • Implement proper health checks
  • Scan images for vulnerabilities
  • Never include secrets in image layers

3. Metadata and Labels

# Add comprehensive metadata
LABEL org.opencontainers.image.title="Your Application"
LABEL org.opencontainers.image.description="Application description"
LABEL org.opencontainers.image.version="1.0.0"
LABEL org.opencontainers.image.created="2025-10-28T10:00:00Z"
LABEL org.opencontainers.image.source="https://github.com/OptumInsight-Platform/your-repo"
LABEL org.opencontainers.image.vendor="Optum"
LABEL optum.project="your-project-key"
LABEL optum.team="your-team"

4. Resource Management

# Set appropriate resource limits in deployment
# Example Kubernetes deployment:
# resources:
#   requests:
#     memory: "64Mi"
#     cpu: "250m"
#   limits:
#     memory: "128Mi"
#     cpu: "500m"

Troubleshooting

Common Issues

1. Authentication Failures

# Verify login status
docker login edgeinternal1uhg.optum.com:443

# Check credentials
cat ~/.docker/config.json

# Re-authenticate if needed
docker logout edgeinternal1uhg.optum.com:443
docker login edgeinternal1uhg.optum.com:443

2. Golden Image Pull Failures

# Check image availability
docker search edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/

# Try specific version
docker pull edgeinternal1uhg.optum.com:443/glb-docker-uhg-loc/uhg-goldenimages/node/dev:18.17.0

3. Build Failures

# Build with verbose output
docker build --progress=plain --no-cache .

# Check build context size
du -sh .

# Verify .dockerignore
cat .dockerignore

Debug Commands

# Run interactive shell in container
docker run -it your-image:tag /bin/sh

# Check running processes
docker exec container-name ps aux

# View logs
docker logs container-name --follow

# Inspect image layers
docker history your-image:tag

Support Resources


Remember: Always use Optum golden images, implement proper security practices, and follow enterprise containerization standards for compliant, secure container deployment.