Complete installation, setup, and configuration guide for the Work Mac Studio as a high-performance Docker development server.
## Enable Remote Login (SSH)
sudo systemsetup -setremotelogin on
## Configure Energy Saver (prevent sleep)
sudo pmset -a displaysleep 0 disksleep 0 sleep 0
## Enable automatic security updates
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticCheckEnabled -bool true
sudo defaults write /Library/Preferences/com.apple.SoftwareUpdate AutomaticDownload -bool true
## Increase file limits for development
echo 'kern.maxfiles=65536' | sudo tee -a /etc/sysctl.conf
echo 'kern.maxfilesperproc=32768' | sudo tee -a /etc/sysctl.conf
## Disable Spotlight indexing for development directories
sudo mdutil -i off /Users/$(whoami)/docker/
sudo mdutil -i off /Users/$(whoami)/git/
## Install Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
## Add to shell path
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
## Install core packages
brew install \
git \
docker-compose \
dive \
lazydocker \
ctop \
httpie \
jq \
yq \
tree \
htop \
wget \
curl \
tmux \
vim
## Install GUI applications
brew install --cask \
docker \
visual-studio-code \
tailscale \
lens \
iterm2
## Docker Desktop already installed via Homebrew above
## Start Docker Desktop
open /Applications/Docker.app
## Wait for Docker to start (check with)
docker version
Configure in Docker Desktop preferences:
General:
Resources:
Docker Engine:
Features in development:
Start Docker Desktop when you log in: ✅
Use Docker Compose V2: ✅
CPUs: 16-18 cores (leave 2-4 for macOS)
Memory: 48-96GB (depending on total RAM)
Swap: 2GB
Disk image size: 200GB+
{
"builder": {
"gc": {
"defaultKeepStorage": "20GB",
"enabled": true
}
},
"experimental": true,
"features": {
"buildkit": true
}
}
## Create multi-arch builder
docker buildx create --name multiarch --use --bootstrap
## Verify available platforms
docker buildx ls
## Inspect builder capabilities
docker buildx inspect multiarch
## Create test Dockerfile
mkdir -p ~/docker/test
cat > ~/docker/test/Dockerfile << 'EOF'
FROM alpine:latest
RUN echo "Hello from $(uname -m)"
CMD ["echo", "Multi-arch test successful"]
EOF
## Build for multiple platforms
cd ~/docker/test
docker buildx build --platform linux/amd64,linux/arm64 -t test-multiarch .
## Create main development structure
mkdir -p ~/docker/{projects,volumes,configs,scripts,registry}
mkdir -p ~/docker/projects/{work,personal,testing,cicd}
mkdir -p ~/docker/configs/{compose,buildkit,registry}
mkdir -p ~/docker/volumes/{data,logs,cache}
## Create git workspace
mkdir -p ~/git/{work,personal,homelab}
Create ~/docker/configs/compose/docker-compose.base.yml:
version: '3.9'
## Common environment variables
x-common-variables: &common-variables
TZ: ${TZ:-America/New_York}
PUID: ${PUID:-1000}
PGID: ${PGID:-1000}
## Common network configuration
x-common-networks: &common-networks
networks:
- development
## Default networks
networks:
development:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
monitoring:
driver: bridge
ipam:
config:
- subnet: 172.21.0.0/16
## Common volumes
volumes:
development_data:
driver: local
registry_data:
driver: local
monitoring_data:
driver: local
Create ~/docker/configs/.env:
## Docker Environment Configuration
TZ=America/New_York
PUID=1000
PGID=1000
## Registry Configuration
REGISTRY_HOST=localhost
REGISTRY_PORT=5000
REGISTRY_USER=developer
REGISTRY_PASS=development
## Development Configuration
DEV_WORKSPACE=/Users/$(whoami)/docker/projects
LOG_LEVEL=info
## Networking
DOCKER_NETWORK_SUBNET=172.20.0.0/16
MONITORING_NETWORK_SUBNET=172.21.0.0/16
## Tailscale already installed via Homebrew
## Start Tailscale service
sudo tailscale up
## Set hostname
sudo tailscale set --hostname work-mac-studio
## Get Tailscale IP
TAILSCALE_IP=$(tailscale ip -4)
echo "Tailscale IP: $TAILSCALE_IP"
## Test connectivity to homelab servers
for server in lucille4 nas02 loose-seal lucille5; do
echo "Testing $server..."
ping -c 3 $server
done
## Generate SSH key for work development
ssh-keygen -t ed25519 -f ~/.ssh/work-mac-studio -C "work-mac-studio@speicher.family"
## Add to SSH agent
ssh-add ~/.ssh/work-mac-studio
Create ~/.ssh/config:
## Work Mac Studio SSH Configuration
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/work-mac-studio
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/work-mac-studio
## Homelab servers
Host lucille4 nas02 loose-seal lucille5
User mspeicher
IdentityFile ~/.ssh/work-mac-studio
ServerAliveInterval 60
## Default settings
Host *
AddKeysToAgent yes
UseKeychain yes
ServerAliveInterval 60
ServerAliveCountMax 3
## Create mount points
sudo mkdir -p /Volumes/nas02-docker
sudo mkdir -p /Volumes/nas02-development
## Create auto-mount script
cat > ~/docker/scripts/mount-nas.sh << 'EOF'
#!/bin/bash
## Auto-mount NAS shares for development
## Mount Docker volume backup location
if ! mount | grep -q "/Volumes/nas02-docker"; then
echo "Mounting nas02 Docker share..."
mount_smbfs //mspeicher@nas02.local/docker /Volumes/nas02-docker
fi
## Mount development share
if ! mount | grep -q "/Volumes/nas02-development"; then
echo "Mounting nas02 development share..."
mount_smbfs //mspeicher@nas02.local/development /Volumes/nas02-development
fi
echo "NAS shares mounted successfully"
EOF
chmod +x ~/docker/scripts/mount-nas.sh
Create ~/docker/projects/work/registry/docker-compose.yml:
version: '3.9'
services:
registry:
image: registry:2
container_name: work-registry
restart: unless-stopped
ports:
- "5000:5000"
volumes:
- registry_data:/var/lib/registry
- ./config:/etc/docker/registry
- ./auth:/auth
environment:
REGISTRY_AUTH: htpasswd
REGISTRY_AUTH_HTPASSWD_PATH: /auth/htpasswd
REGISTRY_AUTH_HTPASSWD_REALM: Registry Realm
REGISTRY_STORAGE_DELETE_ENABLED: true
networks:
- development
volumes:
registry_data:
networks:
development:
external: true
## Create registry auth
mkdir -p ~/docker/projects/work/registry/auth
## Create htpasswd file
docker run --rm --entrypoint htpasswd \
httpd:2 -Bbn developer development > ~/docker/projects/work/registry/auth/htpasswd
## Start registry
cd ~/docker/projects/work/registry
docker-compose up -d
## Test registry
curl http://localhost:5000/v2/_catalog
## Add insecure registry to Docker Desktop
## In Docker Desktop → Settings → Docker Engine, add:
{
"insecure-registries": ["localhost:5000", "work-mac-studio:5000"]
}
## Tag and push test image
docker tag alpine:latest localhost:5000/test/alpine:latest
docker push localhost:5000/test/alpine:latest
## Verify image in registry
curl http://localhost:5000/v2/test/alpine/tags/list
Create ~/docker/projects/monitoring/docker-compose.yml:
version: '3.9'
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:latest
container_name: cadvisor
ports:
- "8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
devices:
- /dev/kmsg
restart: unless-stopped
networks:
- monitoring
prometheus:
image: prom/prometheus:latest
container_name: prometheus
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--storage.tsdb.retention.time=200h'
- '--web.enable-lifecycle'
restart: unless-stopped
networks:
- monitoring
volumes:
prometheus_data:
networks:
monitoring:
external: true
Create ~/docker/projects/monitoring/prometheus.yml:
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
- job_name: 'docker-daemon'
static_configs:
- targets: ['host.docker.internal:9323']
Create ~/docker/scripts/setup-logging.sh:
#!/bin/bash
## Configure log forwarding to homelab Seq
## Install log forwarder
brew install vector
## Create Vector configuration
cat > ~/.vector/vector.toml << 'EOF'
[sources.docker_logs]
type = "docker_logs"
[transforms.docker_transform]
type = "remap"
inputs = ["docker_logs"]
source = '''
.hostname = "work-mac-studio"
.service = "docker"
'''
[sinks.seq]
type = "http"
inputs = ["docker_transform"]
uri = "http://seq.speicher.family:12201/api/events/raw"
method = "post"
compression = "gzip"
[sinks.seq.headers]
X-Seq-ApiKey = "development"
EOF
## Start Vector service
brew services start vector
EOF
chmod +x ~/docker/scripts/setup-logging.sh
## Install Trivy for vulnerability scanning
brew install aquasecurity/trivy/trivy
## Install Docker Bench for security
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc:ro \
-v /lib/systemd/system:/lib/systemd/system:ro \
-v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
--label docker_bench_security \
docker/docker-bench-security
Create ~/docker/scripts/security-scan.sh:
#!/bin/bash
## Container security scanning
echo "Scanning local images for vulnerabilities..."
## Get list of all local images
images=$(docker images --format "{{.Repository}}:{{.Tag}}" | grep -v "<none>")
for image in $images; do
echo "Scanning $image..."
trivy image --quiet --format table $image
done
echo "Security scan completed"
## Enable macOS firewall
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --setglobalstate on
## Allow Docker Desktop
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /Applications/Docker.app
## Allow specific ports for development
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/prometheus
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/local/bin/cadvisor
Create ~/docker/scripts/health-check.sh:
#!/bin/bash
## Work Mac Studio health check
echo "=== Work Mac Studio Health Check ==="
echo
## Docker status
echo "Docker Desktop Status:"
docker version --format '{{.Server.Version}}' 2>/dev/null && echo "✅ Docker running" || echo "❌ Docker not running"
echo
## Container status
echo "Running Containers:"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo
## Resource usage
echo "System Resources:"
echo "CPU Usage: $(top -l 1 | grep "CPU usage" | awk '{print $3}')"
echo "Memory: $(vm_stat | grep "Pages free" | awk '{print $3}' | sed 's/\.//')"
echo
## Network status
echo "Network Connectivity:"
ping -c 1 google.com >/dev/null 2>&1 && echo "✅ Internet connectivity" || echo "❌ No internet"
tailscale status >/dev/null 2>&1 && echo "✅ Tailscale connected" || echo "❌ Tailscale disconnected"
echo
## Storage status
echo "Storage Usage:"
df -h / | tail -1 | awk '{print "Root: " $5 " used of " $2}'
docker system df
echo
echo "Health check completed"
## Create test build
mkdir -p ~/docker/test/multiarch
cd ~/docker/test/multiarch
cat > Dockerfile << 'EOF'
FROM alpine:latest
RUN apk add --no-cache curl
COPY test.sh /test.sh
RUN chmod +x /test.sh
CMD ["/test.sh"]
EOF
cat > test.sh << 'EOF'
#!/bin/sh
echo "Architecture: $(uname -m)"
echo "OS: $(uname -s)"
echo "Hostname: $(hostname)"
curl -s http://httpbin.org/ip | grep origin
EOF
## Build for multiple architectures
docker buildx build --platform linux/amd64,linux/arm64 -t localhost:5000/test/multiarch:latest --push .
## Test the image
docker run --rm localhost:5000/test/multiarch:latest
Create ~/docker/scripts/maintenance.sh:
#!/bin/bash
## Automated maintenance tasks
echo "Starting Docker maintenance..."
## Clean up stopped containers
echo "Cleaning stopped containers..."
docker container prune -f
## Clean up unused images
echo "Cleaning unused images..."
docker image prune -a -f
## Clean up unused volumes
echo "Cleaning unused volumes..."
docker volume prune -f
## Clean up unused networks
echo "Cleaning unused networks..."
docker network prune -f
## Backup registry data
echo "Backing up registry data..."
if [ -d "/Volumes/nas02-docker" ]; then
rsync -av ~/docker/projects/work/registry/data/ /Volumes/nas02-docker/backups/registry/
fi
echo "Maintenance completed"
## Add to crontab
(crontab -l 2>/dev/null; echo "0 2 * * 0 ~/docker/scripts/maintenance.sh") | crontab -
For detailed development workflows, see the Docker Development Overview.