Docker Support
Docker Support
Section titled “Docker Support”LeanJ supports profiling Java applications running in Docker containers with automatic discovery and registration.
Overview
Section titled “Overview”Docker containers with the agent automatically register with the controller using push-based discovery. No manual configuration needed!
1. Configure Agent in Dockerfile
Section titled “1. Configure Agent in Dockerfile”Add the agent to your Dockerfile:
# Copy agent JARCOPY dist/agent/agent-core-1.0.0-SNAPSHOT.jar /agent/agent.jar
# Configure Java agentENV JAVA_TOOL_OPTIONS="-javaagent:/agent/agent.jar=package=com.myapp"
# Optional: Set project name for identificationENV LEANJ_PROJECT=my-service
# Optional: Set controller host (if not localhost)ENV LEANJ_CONTROLLER_HOST=host.docker.internalENV LEANJ_CONTROLLER_PORT=98762. Build Docker Image
Section titled “2. Build Docker Image”docker build -t my-java-app .3. Start Controller
Section titled “3. Start Controller”Make sure the controller is running:
leanj controller startImportant: If controller is on host and container needs to connect:
- Use
host.docker.internal(Docker Desktop) or - Use host’s IP address or
- Run controller in a shared network
4. Run Container
Section titled “4. Run Container”docker run -d \ --name my-service \ -p 8080:8080 \ my-java-appThe agent automatically:
- Detects Docker environment
- Registers with controller
- Starts sending metrics
Discovery
Section titled “Discovery”View Docker JVMs
Section titled “View Docker JVMs”leanj jvmsOutput:
Found 2 JVM(s):
1. my-service ID: def456 Environment: docker App: my-service Container: abc123def456Docker-Specific Fields
Section titled “Docker-Specific Fields”Docker JVMs show:
- Environment:
docker(instead oflocal) - Container ID: Docker container identifier
- App Name: From
LEANJ_PROJECTenv var - PID: Not available (null for Docker)
Attaching
Section titled “Attaching”Attach to Docker JVM
Section titled “Attach to Docker JVM”Using JVM ID:
leanj attach --jvm-id def456Note: Docker JVMs use push-based discovery, so they’re already registered. The attach command confirms the connection.
Environment Detection
Section titled “Environment Detection”The agent automatically detects Docker environment by checking:
/.dockerenvfile existence/proc/self/cgroupcontains “docker”DOCKER_HOSTenvironment variable- Container ID from hostname or cgroup
Registration Flow
Section titled “Registration Flow”When a Docker container starts:
- Agent starts with Java application
- Detects Docker environment
- Registers with controller via HTTP POST:
POST http://controller:9877/api/v1/jvms/register
- Sends heartbeat every 30 seconds
- Sends metrics via TCP on port 9876
Registration Payload
Section titled “Registration Payload”{ "jvmId": "uuid-generated", "environment": "docker", "containerId": "order-service", "appName": "order-service", "labels": { "project": "order-service" }}Heartbeat
Section titled “Heartbeat”Docker agents send periodic heartbeats:
- Interval: Every 30 seconds
- Endpoint:
POST /api/v1/jvms/{jvmId}/heartbeat - Purpose: Keep registration alive, update
lastSeenAt
Controller removes stale JVMs after 60 seconds of no heartbeat.
Controller Network Configuration
Section titled “Controller Network Configuration”Docker Desktop (Mac/Windows)
Section titled “Docker Desktop (Mac/Windows)”Use host.docker.internal:
ENV LEANJ_CONTROLLER_HOST=host.docker.internalENV LEANJ_CONTROLLER_PORT=9876Use host’s IP or shared network:
Option 1: Host IP
ENV LEANJ_CONTROLLER_HOST=172.17.0.1Option 2: Shared Network
# Create networkdocker network create profiler-net
# Run controller in networkdocker run -d --network profiler-net --name controller ...
# Run app in same networkdocker run -d --network profiler-net ...Docker Compose
Section titled “Docker Compose”version: '3.8'services: controller: # Controller service (if containerized)
app: build: . environment: - JAVA_TOOL_OPTIONS=-javaagent:/agent/agent.jar=package=com.myapp - LEANJ_PROJECT=my-service - LEANJ_CONTROLLER_HOST=controller - LEANJ_CONTROLLER_PORT=9876 networks: - profiler-net
networks: profiler-net: driver: bridgeKubernetes
Section titled “Kubernetes”LeanJ works in Kubernetes too:
- Mount agent JAR as ConfigMap or volume
- Set JAVA_TOOL_OPTIONS in deployment
- Configure controller host to service name or IP
- Agents register automatically
Example deployment:
apiVersion: apps/v1kind: Deploymentmetadata: name: my-appspec: template: spec: containers: - name: app env: - name: JAVA_TOOL_OPTIONS value: "-javaagent:/agent/agent.jar=package=com.myapp" - name: LEANJ_CONTROLLER_HOST value: "profiler-controller.default.svc.cluster.local" volumeMounts: - name: agent mountPath: /agent volumes: - name: agent configMap: name: profiler-agentTroubleshooting
Section titled “Troubleshooting”Container Not Appearing
Section titled “Container Not Appearing”Issue: Docker JVM not in jvms list
Solution:
- Check agent is configured:
echo $JAVA_TOOL_OPTIONS - Verify controller is accessible from container
- Check controller logs:
logs/profiler-controller.log - Verify network connectivity
Connection Refused
Section titled “Connection Refused”Issue: Agent can’t connect to controller
Solution:
- Check controller host/port configuration
- Verify network connectivity:
ping controller-host - Test HTTP endpoint:
curl http://controller:9877/api/v1/status - Check firewall rules
Stale JVMs
Section titled “Stale JVMs”Issue: Old containers still in list
Solution:
- Controller auto-removes after 60 seconds of no heartbeat
- Or manually remove:
leanj detach --jvm-id <id>
Best Practices
Section titled “Best Practices”- Use project names: Set
LEANJ_PROJECTfor easy identification - Shared networks: Use Docker networks for better isolation
- Resource limits: Set appropriate memory/CPU limits
- Health checks: Monitor agent registration in logs
- Labels: Use labels for filtering and organization
Next Steps
Section titled “Next Steps”- Learn about IntelliJ integration
- Explore CLI commands
- Read How It Works for architecture details