Loading...
Loading...
Platform-specific Docker considerations for Windows, Linux, and macOS
npx skill4agent add josiahsiegel/claude-plugin-marketplace docker-platform-guide\/D:/repos/project/file.tsxD:\repos\project\file.tsx# Check current driver
docker info | grep "Storage Driver"
# Recommended: overlay2
# /etc/docker/daemon.json
{
"storage-driver": "overlay2"
}/etc/docker/daemon.json{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true,
"userland-proxy": false,
"userns-remap": "default",
"icc": false,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 64000,
"Soft": 64000
}
}
}# Enable in daemon.json
{
"userns-remap": "default"
}
# Restart Docker
sudo systemctl restart docker
# Result: root in container = unprivileged user on host# Check SELinux status
sestatus
# Run container with SELinux enabled
docker run --security-opt label=type:svirt_sandbox_file_t myimage
# Volume labels
docker run -v /host/path:/container/path:z myimage # Private label
docker run -v /host/path:/container/path:Z myimage # Shared label# Check AppArmor status
sudo aa-status
# Run with default Docker profile
docker run --security-opt apparmor=docker-default myimage
# Create custom profile
sudo aa-genprof docker run myimage# Check Docker service status
sudo systemctl status docker
# Enable on boot
sudo systemctl enable docker
# Restart Docker
sudo systemctl restart docker
# View logs
sudo journalctl -u docker -f
# Configure service
sudo systemctl edit docker# Check cgroup version
stat -fc %T /sys/fs/cgroup/
# If using cgroup v2, ensure Docker version >= 20.10
# /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}# Install Docker
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
# Non-root user
sudo usermod -aG docker $USER# Install Docker
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/fedora/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io
# Start Docker
sudo systemctl start docker
sudo systemctl enable docker
# Non-root user
sudo usermod -aG docker $USER# Install Docker
apk add docker docker-compose
# Start Docker
rc-update add docker boot
service docker startDocker Desktop → Preferences → Resources → Advanced
- CPUs: Allocate based on workload (default: half available)
- Memory: Allocate generously (default: 2GB, recommend 4-8GB)
- Swap: 1GB minimum
- Disk image size: 60GB+ for developmentvolumes:
# Host writes delayed (best for source code)
- ./src:/app/src:delegated
# Container writes cached (best for build outputs)
- ./build:/app/build:cached
# Default consistency (slowest but safest)
- ./data:/app/data:consistent# Access host from container
host.docker.internal
# Example: Connect to host PostgreSQL
docker run -e DATABASE_URL=postgresql://host.docker.internal:5432/db myapp# Check image architecture
docker image inspect node:20-alpine | grep Architecture
# M-series Macs are ARM64
# Some images only available for AMD64
# Build multi-platform
docker buildx build --platform linux/amd64,linux/arm64 -t myapp .
# Run AMD64 image on ARM (via emulation)
docker run --platform linux/amd64 myimage # SlowerDocker Desktop → Features in development → Use Rosetta for x86/amd64 emulationCPUs: 4-6 (for development)
Memory: 6-8 GB (for development)
Swap: 1-2 GB
Disk image size: 100+ GB (grows dynamically){
"builder": {
"gc": {
"enabled": true,
"defaultKeepStorage": "20GB"
}
},
"experimental": false,
"features": {
"buildkit": true
}
}# macOS user ID and group ID
id -u # Usually 501
id -g # Usually 20
# Match in container
docker run --user 501:20 myimage
# Or in Dockerfile
RUN adduser -u 501 -g 20 appuser
USER appuser# docker-compose.yml for development
version: '3.8'
services:
app:
build: .
volumes:
# Source code with delegated (better performance)
- ./src:/app/src:delegated
# node_modules in volume (much faster than bind mount)
- node_modules:/app/node_modules
ports:
- "3000:3000"
environment:
- NODE_ENV=development
volumes:
node_modules:# Find process using port
lsof -i :PORT
kill -9 PID# Run as Administrator
wsl --install
# Or manually
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
# Set WSL2 as default
wsl --set-default-version 2
# Install Ubuntu (or other distro)
wsl --install -d UbuntuSettings → Resources → WSL Integration
- Enable integration with default distro
- Select additional distros# Forward slashes (recommended, works everywhere)
docker run -v C:/Users/name/project:/app myimage
# Backslashes (need escaping in some contexts)
docker run -v C:\Users\name\project:/app myimage
# In docker-compose.yml (forward slashes)
volumes:
- C:/Users/name/project:/app
# Or relative paths
volumes:
- ./src:/app/src# What you type in Git Bash:
docker run -v $(pwd):/app myimage
# What Git Bash converts it to (BROKEN):
docker run -v C:\Program Files\Git\d\repos\project:/app myimage# Per-command fix
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
# Session-wide fix (add to ~/.bashrc)
export MSYS_NO_PATHCONV=1
# Function wrapper (automatic for all Docker commands)
docker() {
(export MSYS_NO_PATHCONV=1; command docker.exe "$@")
}
export -f docker# Use double leading slash to prevent conversion
docker run -v //c/Users/project:/app myimage
# Works with $(pwd) too
docker run -v //$(pwd):/app myimage# Named volumes work without any fixes
docker run -v my-data:/data myimage$(pwd)# Detect Git Bash/MINGW and auto-configure
if [ -n "$MSYSTEM" ] || [[ "$(uname -s)" == MINGW* ]]; then
export MSYS_NO_PATHCONV=1
echo "Git Bash detected - Docker path conversion fix enabled"
fi# Docker on Git Bash fix
if [ -n "$MSYSTEM" ]; then
export MSYS_NO_PATHCONV=1
fidocker-git-bash-guideDocker Desktop → Settings → Resources → File Sharing
Add: C:\, D:\, etc.# Git configuration
git config --global core.autocrlf input
# Or per-repo (.gitattributes)
* text=auto
*.sh text eol=lf
*.bat text eol=crlf# In Dockerfile for scripts
FROM alpine
COPY script.sh /
# Ensure LF endings
RUN dos2unix /script.sh || sed -i 's/\r$//' /script.sh# Allow Docker Desktop
New-NetFirewallRule -DisplayName "Docker Desktop" -Direction Inbound -Program "C:\Program Files\Docker\Docker\Docker Desktop.exe" -Action Allow
# Check blocked ports
netstat -ano | findstr :PORT# Run PowerShell in container
docker run -it mcr.microsoft.com/powershell:lts-7.4-windowsservercore-ltsc2022
# Windows container example
docker run -it mcr.microsoft.com/windows/servercore:ltsc2022 cmd
# Check container type
docker info | Select-String "OSType"# Stop Docker Desktop and WSL
wsl --shutdown
# Compact disk image (run as Administrator)
# Method 1: Optimize-VHD (requires Hyper-V tools)
Optimize-VHD -Path "$env:LOCALAPPDATA\Docker\wsl\data\ext4.vhdx" -Mode Full
# Method 2: diskpart
diskpart
# In diskpart:
select vdisk file="C:\Users\YourName\AppData\Local\Docker\wsl\data\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
exit# docker-compose.yml for Windows
version: '3.8'
services:
app:
build: .
volumes:
# Use forward slashes
- ./src:/app/src
# Named volumes for better performance
- node_modules:/app/node_modules
ports:
- "3000:3000"
environment:
- NODE_ENV=development
# Windows-specific: ensure proper line endings
command: sh -c "dos2unix /app/scripts/*.sh && npm start"
volumes:
node_modules:# Run Docker Desktop as Administrator
# Or grant permissions to Docker Desktop
icacls "C:\ProgramData\DockerDesktop" /grant Users:F /T\\wsl$\Ubuntu\home\user\project${PWD}| Feature | Linux | macOS | Windows |
|---|---|---|---|
| Performance | Excellent (native) | Good (VM overhead) | Good (WSL2) to Fair (Hyper-V) |
| File sharing | Native | Slow (improving with VirtioFS) | Slow (better in WSL2) |
| Resource efficiency | Best | Good | Good (WSL2) |
| Feature set | Complete | Complete | Complete (LCOW) |
| Production | Standard | Dev only | Dev only (LCOW) |
| Ease of use | Moderate | Easy (Docker Desktop) | Easy (Docker Desktop) |
| Cost | Free | Free (Docker Desktop Personal) | Free (Docker Desktop Personal) |
# Create buildx builder
docker buildx create --name multiplatform --driver docker-container --use
# Build for multiple platforms
docker buildx build \
--platform linux/amd64,linux/arm64,linux/arm/v7 \
-t myimage:latest \
--push \
.# Works on all platforms
FROM node:20-alpine
# Use COPY with --chmod (not RUN chmod, which is slower)
COPY script.sh /usr/local/bin/
# Use environment variables for paths
ENV APP_HOME=/app
WORKDIR ${APP_HOME}
# Use exec form for CMD/ENTRYPOINT (works on Windows containers too)
CMD ["node", "server.js"]version: '3.8'
services:
app:
build: .
volumes:
# Relative paths work everywhere
- ./src:/app/src
# Named volumes (platform-agnostic)
- data:/app/data
environment:
# Use environment variables
- NODE_ENV=${NODE_ENV:-development}
volumes:
data:# Test on different platforms with buildx
docker buildx build --platform linux/amd64 -t myapp:amd64 --load .
docker run --rm myapp:amd64
docker buildx build --platform linux/arm64 -t myapp:arm64 --load .
docker run --rm myapp:arm64