A secure, containerized development environment for educational and development purposes. This project provides a Docker-based lab environment with SSH access, multiple user accounts, and development tools, designed for learning, testing, and development workflows.
- π Multi-User Environment: 6 pre-configured user accounts (admin + 5 regular users)
- π Public SSH Access: Secure remote access via playit.gg tunneling
- π οΈ Development Tools: Python 3.x, Node.js, Git, and essential utilities
- πΎ Persistent Storage: User data persists across container restarts with separate volumes for Alpine and Ubuntu
- βοΈ Runtime Configuration: Environment-based configuration management
- π Security Focused: Proper user isolation and SSH key support
- π SSH Key Synchronization: Shared SSH host keys between Alpine and Ubuntu containers
- π₯ Health Monitoring: Built-in health checks for SSH service availability
- ποΈ Alpine & Ubuntu Support: Choose between lightweight Alpine (173MB) or full Ubuntu (968MB)
- Docker (version 20.10 or higher)
- Docker Compose (version 2.0 or higher)
- Git for cloning the repository
git clone https://github.com/nazdridoy/nazdocker-lab.git
cd nazdocker-lab# Create separate data directories for Alpine and Ubuntu
mkdir -p data/{alpine,ubuntu}/{admin,user1,user2,user3,user4,user5}
mkdir -p logs/{alpine,ubuntu}
# Generate SSH host keys (optional - will be auto-generated if missing)
./scripts/manage-ssh-keys.sh generate
# Configure environment variables
cp .env.example .env
# Edit .env with your configurationChoose your preferred version:
Ubuntu Version (Recommended for Development):
docker-compose -f docker-compose.ubuntu.yml up -dAlpine Version (Recommended for Production - 82% smaller):
docker-compose -f docker-compose.alpine.yml up -d# Local SSH access
ssh admin@localhost -p 2222
# Password: admin123| Username | Default Password | Sudo Access | Purpose |
|---|---|---|---|
admin |
admin123 |
β Yes | Administrative tasks |
user1 |
user123 |
β No | Regular development |
user2 |
user123 |
β No | Regular development |
user3 |
user123 |
β No | Regular development |
user4 |
user123 |
β No | Regular development |
user5 |
user123 |
β No | Regular development |
root |
root123 |
β Yes | System administration |
The lab environment uses shared SSH host keys between Alpine and Ubuntu containers to ensure consistent SSH connections:
# Generate new SSH host keys
./scripts/manage-ssh-keys.sh generate
# Check SSH key fingerprints
./scripts/manage-ssh-keys.sh check
# Backup SSH keys
./scripts/manage-ssh-keys.sh backup
# Restore SSH keys from backup
./scripts/manage-ssh-keys.sh restore backup/ssh-20231201-143022Benefits:
- β Same SSH host keys across both containers
- β No SSH host key warnings when switching containers
- β Centralized key management
- β Easy key rotation and backup
The lab uses environment variables for secure configuration. Copy .env.example to .env and customize:
# Required: Playit.gg secret key for public access
PLAYIT_SECRET_KEY=your_playit_secret_key_here
# User passwords (change these!)
ADMIN_PASSWORD=your_admin_password_here
USER_PASSWORD=your_user_password_here
ROOT_PASSWORD=your_root_password_here
# Optional: SSH port mapping
SSH_PORT=2222- Change default passwords immediately after first login
- Use SSH keys instead of password authentication when possible
- Never commit your
.envfile to version control - SSH host keys are automatically ignored by
.gitignorefor security - Regular updates of the base image and installed packages
# SSH to any user
ssh admin@localhost -p 2222
ssh user1@localhost -p 2222
# ... etcThe environment includes playit.gg tunneling for public SSH access:
- Configure playit.gg: Set your secret key in
.env - Check tunnel status: Monitor container logs for tunnel URL
- Connect remotely: Use the provided public URL
# Check tunnel status
docker-compose -f docker-compose.ubuntu.yml logs lab-environment-ubuntu | grep -i "playit\|tunnel"
# Connect via public URL (example)
ssh admin@your-tunnel-url.playit.gg -p 12345- Python 3.x with pip package manager
- uv - Fast Python package manager (replaces pip, pip-tools, pipx, poetry, pyenv, virtualenv)
- uvx - Run Python tools in ephemeral environments
- Node.js with npm package manager
- Git for version control
- SSH server for remote access
- curl for HTTP requests
- jq for JSON processing
- ping for network testing
- ifconfig for network configuration
- apt package manager (Ubuntu) / apk package manager (Alpine)
nazdocker-lab/
βββ Dockerfile.ubuntu # Ubuntu container definition with health checks
βββ Dockerfile.alpine # Alpine container definition (189MB)
βββ start.sh # Cross-platform startup script
βββ docker-compose.ubuntu.yml # Ubuntu Docker Compose orchestration
βββ docker-compose.alpine.yml # Alpine Docker Compose orchestration
βββ .env.example # Environment variables template
βββ README.md # This file
βββ docs/ # Modular documentation
βββ LICENSE # GPL v3 license
βββ config/ # Configuration files
β βββ ssh/ # Shared SSH host keys (gitignored)
β βββ ssh_host_rsa_key
β βββ ssh_host_rsa_key.pub
β βββ ssh_host_ecdsa_key
β βββ ssh_host_ecdsa_key.pub
β βββ ssh_host_ed25519_key
β βββ ssh_host_ed25519_key.pub
βββ scripts/ # Utility scripts
β βββ manage-ssh-keys.sh # SSH key management script
βββ data/ # Persistent user data (separated by container type)
β βββ alpine/ # Alpine container data
β β βββ admin/ # Admin home directory (Alpine)
β β βββ user1/ # User1 home directory (Alpine)
β β βββ user2/ # User2 home directory (Alpine)
β β βββ user3/ # User3 home directory (Alpine)
β β βββ user4/ # User4 home directory (Alpine)
β β βββ user5/ # User5 home directory (Alpine)
β βββ ubuntu/ # Ubuntu container data
β βββ admin/ # Admin home directory (Ubuntu)
β βββ user1/ # User1 home directory (Ubuntu)
β βββ user2/ # User2 home directory (Ubuntu)
β βββ user3/ # User3 home directory (Ubuntu)
β βββ user4/ # User4 home directory (Ubuntu)
β βββ user5/ # User5 home directory (Ubuntu)
βββ logs/ # Application logs (separated by container type)
βββ alpine/ # Alpine container logs
βββ ubuntu/ # Ubuntu container logs
# Start Ubuntu environment
docker-compose -f docker-compose.ubuntu.yml up -d
# SSH into lab
ssh admin@localhost -p 2222
# Develop in your persistent home directory
# Install packages: sudo apt-get install (admin only)
# Use uv for Python development
uv init myproject # Create new Python project
uv add requests # Add dependency
uv run myproject/main.py # Run Python script
uvx ruff check # Run linter in ephemeral environment
# Stop when done
docker-compose -f docker-compose.ubuntu.yml down# Start Alpine environment (82% smaller)
docker-compose -f docker-compose.alpine.yml up -d
# SSH into lab (same commands)
ssh admin@localhost -p 2222
# Develop in your persistent home directory
# Install packages: sudo apk add (admin only)
# Use uv for Python development
uv init myproject # Create new Python project
uv add requests # Add dependency
uv run myproject/main.py # Run Python script
uvx ruff check # Run linter in ephemeral environment
# Stop when done
docker-compose -f docker-compose.alpine.yml down# Build Ubuntu image
docker-compose -f docker-compose.ubuntu.yml build
# Build Alpine image
docker-compose -f docker-compose.alpine.yml build
# Build both images
docker-compose -f docker-compose.ubuntu.yml build && docker-compose -f docker-compose.alpine.yml buildWith separate volumes, you can run both Alpine and Ubuntu containers at the same time:
# Start both environments
docker-compose -f docker-compose.ubuntu.yml up -d
docker-compose -f docker-compose.alpine.yml up -d
# Access Ubuntu lab (port 2222)
ssh admin@localhost -p 2222
# Access Alpine lab (port 2223 - you'll need to modify SSH_PORT in .env)
ssh admin@localhost -p 2223
# Both containers use the same SSH host keys, so no key warnings when switching
# Stop both environments
docker-compose -f docker-compose.ubuntu.yml down
docker-compose -f docker-compose.alpine.yml down- All users have password authentication enabled
- SSH keys are not configured by default
- Default passwords should be changed immediately
- Change all default passwords after first login
- Configure SSH key authentication for better security
- Use strong, unique passwords for each user
- Regular security updates of the base image
- Monitor access logs for suspicious activity
Both Ubuntu and Alpine versions include built-in health checks that monitor SSH service availability:
- Health Check Interval: 30 seconds
- Timeout: 10 seconds per check
- Start Period: 40 seconds grace period after container startup
- Retries: 3 consecutive failures before marking as unhealthy
- Healthy: SSH service is running and accepting connections
- Unhealthy: SSH service is stopped or not responding
- Starting: Container is in the grace period after startup
# Check container health status
docker ps
# View detailed health information
docker inspect student-lab-ubuntu | grep -A 20 "Health"
# Monitor health check logs
docker inspect student-lab-ubuntu | grep -A 10 "Healthcheck"The lab environment uses separate volumes for Alpine and Ubuntu containers to ensure complete isolation and prevent data conflicts:
data/
βββ alpine/ # Alpine container data
β βββ admin/ # Admin user data (Alpine)
β βββ user1/ # User1 data (Alpine)
β βββ user2/ # User2 data (Alpine)
β βββ user3/ # User3 data (Alpine)
β βββ user4/ # User4 data (Alpine)
β βββ user5/ # User5 data (Alpine)
βββ ubuntu/ # Ubuntu container data
βββ admin/ # Admin user data (Ubuntu)
βββ user1/ # User1 data (Ubuntu)
βββ user2/ # User2 data (Ubuntu)
βββ user3/ # User3 data (Ubuntu)
βββ user4/ # User4 data (Ubuntu)
βββ user5/ # User5 data (Ubuntu)
logs/
βββ alpine/ # Alpine container logs
βββ ubuntu/ # Ubuntu container logs
- π Complete Isolation: Alpine and Ubuntu containers have completely separate data storage
- π Concurrent Operation: Both container types can run simultaneously without conflicts
- π¦ Easy Management: Backup, restore, or manage data for each container type separately
- π§Ή Clean Organization: Clear separation makes it obvious which data belongs to which container
- π Independent Scaling: Scale Alpine and Ubuntu environments independently
- Alpine Container: Stores data in
./data/alpine/and logs in./logs/alpine/ - Ubuntu Container: Stores data in
./data/ubuntu/and logs in./logs/ubuntu/
| Version | Base Image | Final Size | Size Reduction |
|---|---|---|---|
| Ubuntu | ubuntu:24.04 |
1.05GB | - |
| Alpine | alpine:3.22 |
189MB | 82% smaller |
Use Alpine When:
- Resource constraints are a concern
- Fast deployments are needed
- Security is a priority
- Production environments where size matters
Use Ubuntu When:
- Maximum compatibility is needed
- Familiar environment is preferred
- Specific Ubuntu packages are required
- Development/testing environments
- Package Management:
apt(Ubuntu) vsapk(Alpine) - Service Management:
service(Ubuntu) vs direct commands (Alpine) - User Groups:
sudo(Ubuntu) vswheel(Alpine) - Build Time: Alpine builds ~50% faster
- Startup Time: Alpine starts ~30% faster
- SSH Keys: Both containers use identical SSH host keys for consistency
Both versions are configured with optimized resource limits:
- CPU: Maximum 2 cores, minimum 1 core reserved
- Memory: Maximum 2GB, minimum 1GB reserved
- Network: Standard bridge networking
- Storage: Persistent volumes for user data
- Documentation Index: Complete modular documentation
- Quick Start Guide: Get up and running in minutes
- Project Structure: Complete project overview
- Container Management: Docker container operations
- User Management: User account management
- Remote Access: SSH access and tunneling
- Troubleshooting: Common issues and solutions
- Docker Documentation: Docker basics
- SSH Documentation: SSH configuration
We welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone your fork
git clone https://github.com/your-username/nazdocker-lab.git
cd nazdocker-lab
# Add upstream remote
git remote add upstream https://github.com/nazdridoy/nazdocker-lab.git
# Create feature branch
git checkout -b feature/your-feature-nameContainer won't start:
# Check logs
docker-compose logs
# Validate configuration
docker-compose configSSH connection refused:
# Check container status
docker-compose ps
# Check SSH service
docker-compose -f docker-compose.ubuntu.yml exec lab-environment-ubuntu service ssh statusEnvironment variables not loading:
# Verify .env file exists
ls -la .env
# Check variable resolution
docker-compose config | grep -E "(PLAYIT_SECRET_KEY|ADMIN_PASSWORD)"For more detailed troubleshooting, see Troubleshooting Guide.
This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.
- Docker for containerization technology
- Ubuntu for the base operating system
- Playit.gg for tunneling services
- OpenSSH for secure shell access
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Documentation Index
Note: This is a development and educational tool. Always follow security best practices and change default credentials before use in production environments.