Basic Usage
Learn how to use gVisor with containers through practical examples and common use cases.
Running Your First gVisor Container
With Docker
The simplest way to run a container with gVisor:
# Run a basic container
docker run --rm --runtime=runsc hello-world
# Run an interactive container
docker run --rm -it --runtime=runsc ubuntu:20.04 /bin/bash
With containerd and ctr
Using containerd's ctr command:
# Pull an image
sudo ctr image pull docker.io/library/alpine:latest
# Run with gVisor runtime
sudo ctr run --runtime=runsc --rm -t docker.io/library/alpine:latest test-container sh
Container Lifecycle Management
Starting and Stopping Containers
# Start a long-running container
docker run -d --name=gvisor-test --runtime=runsc nginx
# Check container status
docker ps
# Stop the container
docker stop gvisor-test
# Remove the container
docker rm gvisor-test
Executing Commands in Running Containers
# Start a container
docker run -d --name=my-app --runtime=runsc nginx
# Execute commands inside
docker exec -it my-app /bin/bash
docker exec my-app ps aux
docker exec my-app cat /proc/version
Working with Volumes and Networking
Volume Mounting
gVisor supports various types of volume mounts:
# Bind mount from host
docker run --rm -it --runtime=runsc \
-v /host/path:/container/path \
alpine:latest sh
# Named volume
docker volume create my-volume
docker run --rm -it --runtime=runsc \
-v my-volume:/data \
alpine:latest sh
# tmpfs mount
docker run --rm -it --runtime=runsc \
--tmpfs /tmp:noexec,nosuid,size=100m \
alpine:latest sh
Networking
gVisor containers support standard Docker networking:
# Default bridge network
docker run --rm --runtime=runsc nginx
# Custom network
docker network create my-network
docker run --rm --runtime=runsc \
--network=my-network \
nginx
# Port mapping
docker run -d --runtime=runsc \
-p 8080:80 \
nginx
Environment Variables and Configuration
Setting Environment Variables
# Single environment variable
docker run --rm --runtime=runsc \
-e MY_VAR=value \
alpine:latest env
# Multiple variables
docker run --rm --runtime=runsc \
-e VAR1=value1 \
-e VAR2=value2 \
alpine:latest env
# From file
echo "DB_HOST=localhost" > .env
echo "DB_PORT=5432" >> .env
docker run --rm --runtime=runsc \
--env-file .env \
alpine:latest env
Working Directory and User
# Set working directory
docker run --rm -it --runtime=runsc \
-w /app \
alpine:latest pwd
# Run as specific user
docker run --rm -it --runtime=runsc \
-u 1000:1000 \
alpine:latest id
# Run as non-root user
docker run --rm -it --runtime=runsc \
--user nobody \
alpine:latest whoami
Resource Limits and Constraints
Memory Limits
# Set memory limit
docker run --rm --runtime=runsc \
-m 512m \
alpine:latest sh -c 'cat /proc/meminfo | head -5'
# Memory and swap limit
docker run --rm --runtime=runsc \
-m 512m --memory-swap 1g \
alpine:latest free -h
CPU Limits
# CPU shares (relative weight)
docker run --rm --runtime=runsc \
--cpu-shares 512 \
alpine:latest cat /sys/fs/cgroup/cpu/cpu.shares
# CPU cores
docker run --rm --runtime=runsc \
--cpus="1.5" \
alpine:latest nproc
Multi-Container Applications
Docker Compose with gVisor
Create a docker-compose.yml file:
version: '3.8'
services:
web:
image: nginx
ports:
- "8080:80"
runtime: runsc
volumes:
- ./html:/usr/share/nginx/html:ro
app:
image: node:16-alpine
runtime: runsc
working_dir: /app
volumes:
- .:/app
command: npm start
db:
image: postgres:13
runtime: runsc
environment:
POSTGRES_PASSWORD: secret
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Run with:
docker-compose up -d
Service Communication
# Create a custom network
docker network create app-network
# Start database
docker run -d --name=db \
--runtime=runsc \
--network=app-network \
-e POSTGRES_PASSWORD=secret \
postgres:13
# Start application (can communicate with db via hostname 'db')
docker run -d --name=app \
--runtime=runsc \
--network=app-network \
-e DATABASE_URL=postgresql://postgres:secret@db:5432/app \
my-app:latest
Debugging and Monitoring
Container Inspection
# Inspect container details
docker inspect container-name
# View container logs
docker logs container-name
# Monitor resource usage
docker stats container-name
Process Monitoring
# View processes in container
docker exec container-name ps aux
# Monitor system calls (with debug enabled)
docker run --rm --runtime=runsc \
--runtime-opt debug=true \
alpine:latest strace ls /
Health Checks
# Run container with health check
docker run -d --runtime=runsc \
--health-cmd="curl -f http://localhost/ || exit 1" \
--health-interval=30s \
--health-timeout=10s \
--health-retries=3 \
nginx
# Check health status
docker inspect --format='{{.State.Health.Status}}' container-name
Common Patterns and Best Practices
Stateless Applications
# Run stateless web service
docker run -d --runtime=runsc \
-p 3000:3000 \
--restart=unless-stopped \
node:16-alpine node server.js
Batch Processing
# Process data with resource limits
docker run --rm --runtime=runsc \
-v /data:/input:ro \
-v /results:/output \
-m 2g --cpus="2" \
data-processor:latest process /input /output
Development Environment
# Interactive development container
docker run -it --rm --runtime=runsc \
-v $(pwd):/workspace \
-w /workspace \
-p 3000:3000 \
node:16 bash
# Inside container
npm install
npm run dev
Performance Considerations
Platform Selection
# Use KVM for better performance (if available)
docker run --rm --runtime=runsc \
--runtime-opt platform=kvm \
alpine:latest echo "Using KVM"
# Check platform being used
docker run --rm --runtime=runsc \
--runtime-opt debug=true \
alpine:latest echo "Check logs for platform info"
Memory and CPU Tuning
# Optimize for memory-intensive applications
docker run --runtime=runsc \
-m 4g \
--memory-swappiness=1 \
memory-intensive-app
# Optimize for CPU-intensive applications
docker run --runtime=runsc \
--cpus="4" \
--cpu-shares 1024 \
cpu-intensive-app
Security Features in Practice
Running Untrusted Code
# Safely run untrusted workload
docker run --rm --runtime=runsc \
--read-only \
--tmpfs /tmp \
--user nobody \
--cap-drop ALL \
untrusted-image:latest
Isolation Verification
# Check that gVisor is handling system calls
docker run --rm --runtime=runsc \
--runtime-opt debug=true \
alpine:latest cat /proc/version
# Should show gVisor version, not host kernel version
Troubleshooting Common Issues
Container Won't Start
# Check gVisor logs
sudo journalctl -u docker | grep runsc
# Run with detailed logging
docker run --rm --runtime=runsc \
--runtime-opt debug=true \
--runtime-opt debug-log=/tmp/runsc.log \
alpine:latest echo "test"
Performance Issues
# Try different platform
docker run --rm --runtime=runsc \
--runtime-opt platform=ptrace \
alpine:latest echo "test"
# Check resource constraints
docker run --rm --runtime=runsc \
alpine:latest sh -c 'cat /proc/meminfo; cat /proc/cpuinfo'
Next Steps
Now that you understand basic usage, explore:
- Configuration Options - Advanced gVisor configuration
- Kubernetes Integration - Using gVisor with Kubernetes
- Advanced Examples - Complex deployment scenarios