Initial commit
This commit is contained in:
543
skills/docker-git-bash-guide.md
Normal file
543
skills/docker-git-bash-guide.md
Normal file
@@ -0,0 +1,543 @@
|
||||
---
|
||||
name: docker-git-bash-guide
|
||||
description: Comprehensive Windows Git Bash and MINGW path conversion guide for Docker volume mounts and commands
|
||||
---
|
||||
|
||||
# Docker on Windows Git Bash / MINGW - Path Conversion Guide
|
||||
|
||||
This skill provides comprehensive guidance on handling Docker commands in Git Bash (MINGW) on Windows, with specific focus on volume mount path conversion issues and solutions.
|
||||
|
||||
## The Path Conversion Problem
|
||||
|
||||
When running Docker commands in Git Bash (MINGW) or MSYS2 on Windows, automatic path conversion can cause serious issues with volume mounts and other Docker commands.
|
||||
|
||||
### What Triggers Automatic Conversion
|
||||
|
||||
MSYS/MINGW shells automatically convert arguments that look like Unix paths when calling Windows executables (like `docker.exe`):
|
||||
|
||||
**Examples of problematic conversions:**
|
||||
```bash
|
||||
# What you type:
|
||||
docker run -v /c/Users/project:/app myimage
|
||||
|
||||
# What Docker receives (BROKEN):
|
||||
docker run -v C:\Program Files\Git\c\Users\project:/app myimage
|
||||
```
|
||||
|
||||
**Triggers for path conversion:**
|
||||
- Leading forward slash (`/`) in arguments
|
||||
- Colon-separated path lists (`/foo:/bar`)
|
||||
- Arguments with path components after `-` or `,`
|
||||
|
||||
**What's exempt from conversion:**
|
||||
- Arguments containing `=` (variable assignments)
|
||||
- Drive letters (`C:`)
|
||||
- Arguments with `;` (already Windows format)
|
||||
- Arguments starting with `//` (network paths/Windows switches)
|
||||
|
||||
## Shell Detection for Docker Commands
|
||||
|
||||
### Detecting Git Bash / MINGW Environment
|
||||
|
||||
Use these environment variables to detect when path conversion issues may occur:
|
||||
|
||||
```bash
|
||||
# Most reliable: Check for MSYSTEM
|
||||
if [ -n "$MSYSTEM" ]; then
|
||||
echo "Running in Git Bash/MINGW - path conversion needed"
|
||||
fi
|
||||
|
||||
# Alternative: Check uname
|
||||
if [[ "$(uname -s)" == MINGW* ]]; then
|
||||
echo "Running in MINGW environment"
|
||||
fi
|
||||
|
||||
# Environment variable to check:
|
||||
# MSYSTEM values: MINGW64, MINGW32, MSYS
|
||||
```
|
||||
|
||||
## Solution 1: MSYS_NO_PATHCONV (Recommended for Git Bash)
|
||||
|
||||
The most reliable solution for Git Bash on Windows.
|
||||
|
||||
### Per-Command Usage
|
||||
|
||||
Prefix each Docker command with `MSYS_NO_PATHCONV=1`:
|
||||
|
||||
```bash
|
||||
# Volume mount with $(pwd)
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
|
||||
# Volume mount with absolute path
|
||||
MSYS_NO_PATHCONV=1 docker run -v /c/Users/project:/app myimage
|
||||
|
||||
# Multiple volume mounts
|
||||
MSYS_NO_PATHCONV=1 docker run \
|
||||
-v $(pwd)/data:/data \
|
||||
-v $(pwd)/config:/etc/config \
|
||||
myimage
|
||||
```
|
||||
|
||||
### Shell-Level Configuration
|
||||
|
||||
Disable path conversion for all Docker commands in your session:
|
||||
|
||||
```bash
|
||||
# Add to ~/.bashrc or run in current shell
|
||||
export MSYS_NO_PATHCONV=1
|
||||
|
||||
# Now all Docker commands work normally
|
||||
docker run -v $(pwd):/app myimage
|
||||
```
|
||||
|
||||
### Function Wrapper (Automatic per Docker Command)
|
||||
|
||||
Create a function wrapper that automatically disables path conversion:
|
||||
|
||||
```bash
|
||||
# Add to ~/.bashrc
|
||||
docker() {
|
||||
(export MSYS_NO_PATHCONV=1; command docker.exe "$@")
|
||||
}
|
||||
|
||||
# Or using MSYS2_ARG_CONV_EXCL for MSYS2
|
||||
docker() {
|
||||
(export MSYS2_ARG_CONV_EXCL='*'; command docker.exe "$@")
|
||||
}
|
||||
|
||||
# Make function available in subshells
|
||||
export -f docker
|
||||
```
|
||||
|
||||
## Solution 2: MSYS2_ARG_CONV_EXCL (MSYS2 Specific)
|
||||
|
||||
For MSYS2 environments (not standard Git Bash):
|
||||
|
||||
```bash
|
||||
# Disable all argument conversion
|
||||
export MSYS2_ARG_CONV_EXCL='*'
|
||||
|
||||
# Selective exclusion (specific patterns)
|
||||
export MSYS2_ARG_CONV_EXCL='--dir=;/test'
|
||||
|
||||
# Environment variable conversion exclusion
|
||||
export MSYS2_ENV_CONV_EXCL='*'
|
||||
```
|
||||
|
||||
## Solution 3: Double Leading Slash
|
||||
|
||||
Prefix paths with an extra `/` to prevent conversion:
|
||||
|
||||
```bash
|
||||
# Single slash (converted - BROKEN)
|
||||
docker run -v /c/Users/project:/app myimage
|
||||
|
||||
# Double slash (not converted - WORKS)
|
||||
docker run -v //c/Users/project:/app myimage
|
||||
|
||||
# Works in Git Bash on Windows
|
||||
# Treated as single slash on Linux (portable)
|
||||
```
|
||||
|
||||
**Advantages:**
|
||||
- No environment variables needed
|
||||
- Works without wrapper functions
|
||||
- Portable (extra slash ignored on Linux)
|
||||
|
||||
**Disadvantages:**
|
||||
- Less readable
|
||||
- Easy to forget
|
||||
- Doesn't look like standard Docker syntax
|
||||
|
||||
## Solution 4: Use $(pwd) with Proper Escaping
|
||||
|
||||
Always use lowercase `$(pwd)` (not `$PWD`) with proper syntax:
|
||||
|
||||
```bash
|
||||
# CORRECT: Round brackets, lowercase pwd, no quotes
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
|
||||
# CORRECT: With subdirectories
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd)/src:/app/src myimage
|
||||
|
||||
# WRONG: Uppercase PWD variable (may not convert correctly)
|
||||
docker run -v $PWD:/app myimage
|
||||
|
||||
# WRONG: Without MSYS_NO_PATHCONV (path gets mangled)
|
||||
docker run -v $(pwd):/app myimage
|
||||
```
|
||||
|
||||
## Docker Volume Mount Best Practices (Git Bash on Windows)
|
||||
|
||||
### For docker run Commands
|
||||
|
||||
```bash
|
||||
# Named volumes (no path conversion issue)
|
||||
docker run -v my-named-volume:/data myimage
|
||||
|
||||
# Bind mount with MSYS_NO_PATHCONV (RECOMMENDED)
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
|
||||
# Bind mount with double slash (ALTERNATIVE)
|
||||
docker run -v //c/Users/project:/app myimage
|
||||
|
||||
# Read-only bind mount
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd)/config:/etc/config:ro myimage
|
||||
|
||||
# Multiple volumes
|
||||
MSYS_NO_PATHCONV=1 docker run \
|
||||
-v $(pwd)/src:/app/src \
|
||||
-v $(pwd)/data:/app/data \
|
||||
-v my-named-volume:/var/lib/data \
|
||||
myimage
|
||||
```
|
||||
|
||||
### For docker-compose.yml Files
|
||||
|
||||
Docker Compose files use forward slashes and relative paths - **these work correctly** in Git Bash:
|
||||
|
||||
```yaml
|
||||
# WORKS WITHOUT MODIFICATION in Git Bash
|
||||
services:
|
||||
app:
|
||||
image: myimage
|
||||
volumes:
|
||||
# Relative paths (RECOMMENDED)
|
||||
- ./src:/app/src
|
||||
- ./data:/app/data
|
||||
|
||||
# Named volumes (RECOMMENDED)
|
||||
- my-data:/var/lib/data
|
||||
|
||||
# Windows absolute paths with forward slashes (WORKS)
|
||||
- C:/Users/project:/app
|
||||
|
||||
# Unix-style paths (WORKS if referring to WSL/MINGW paths)
|
||||
- /c/Users/project:/app
|
||||
|
||||
volumes:
|
||||
my-data:
|
||||
```
|
||||
|
||||
**Important:** When running `docker compose` commands:
|
||||
|
||||
```bash
|
||||
# No special handling needed for compose files
|
||||
docker compose up -d
|
||||
|
||||
# But if you use command-line volume overrides:
|
||||
MSYS_NO_PATHCONV=1 docker compose run -v $(pwd)/extra:/extra app
|
||||
```
|
||||
|
||||
## Complete Examples
|
||||
|
||||
### Example 1: Simple Application Development
|
||||
|
||||
```bash
|
||||
# Set up environment once per session
|
||||
export MSYS_NO_PATHCONV=1
|
||||
|
||||
# Run with live code reload
|
||||
docker run -d \
|
||||
--name dev-app \
|
||||
-v $(pwd)/src:/app/src \
|
||||
-v $(pwd)/public:/app/public \
|
||||
-p 3000:3000 \
|
||||
node:20-alpine \
|
||||
npm run dev
|
||||
|
||||
# View logs
|
||||
docker logs -f dev-app
|
||||
```
|
||||
|
||||
### Example 2: Database with Data Persistence
|
||||
|
||||
```bash
|
||||
# Use named volume for database data (no path issues)
|
||||
docker run -d \
|
||||
--name postgres-db \
|
||||
-e POSTGRES_PASSWORD=mypassword \
|
||||
-v pgdata:/var/lib/postgresql/data \
|
||||
-p 5432:5432 \
|
||||
postgres:16-alpine
|
||||
|
||||
# Mount init scripts with MSYS_NO_PATHCONV
|
||||
MSYS_NO_PATHCONV=1 docker run -d \
|
||||
--name postgres-db \
|
||||
-e POSTGRES_PASSWORD=mypassword \
|
||||
-v pgdata:/var/lib/postgresql/data \
|
||||
-v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql:ro \
|
||||
-p 5432:5432 \
|
||||
postgres:16-alpine
|
||||
```
|
||||
|
||||
### Example 3: Full Stack with Docker Compose
|
||||
|
||||
```bash
|
||||
# Project structure:
|
||||
# /c/Users/project/
|
||||
# ├── docker-compose.yml
|
||||
# ├── backend/
|
||||
# ├── frontend/
|
||||
# └── data/
|
||||
|
||||
# docker-compose.yml (no special path handling needed)
|
||||
cat > docker-compose.yml <<'EOF'
|
||||
services:
|
||||
backend:
|
||||
build: ./backend
|
||||
volumes:
|
||||
- ./backend/src:/app/src
|
||||
- ./data:/app/data
|
||||
ports:
|
||||
- "4000:4000"
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
volumes:
|
||||
- ./frontend/src:/app/src
|
||||
- ./frontend/public:/app/public
|
||||
ports:
|
||||
- "3000:3000"
|
||||
depends_on:
|
||||
- backend
|
||||
|
||||
database:
|
||||
image: postgres:16-alpine
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_PASSWORD: changeme
|
||||
|
||||
volumes:
|
||||
db-data:
|
||||
EOF
|
||||
|
||||
# Start everything (works normally)
|
||||
docker compose up -d
|
||||
|
||||
# Override with additional volume (needs MSYS_NO_PATHCONV)
|
||||
MSYS_NO_PATHCONV=1 docker compose run -v $(pwd)/scripts:/scripts backend bash
|
||||
```
|
||||
|
||||
## Troubleshooting Path Issues
|
||||
|
||||
### Problem: "No such file or directory" errors
|
||||
|
||||
**Symptoms:**
|
||||
```
|
||||
Error response from daemon: invalid mount config for type "bind":
|
||||
bind source path does not exist: C:\Program Files\Git\c\Users\project
|
||||
```
|
||||
|
||||
**Diagnosis:**
|
||||
- Path has been incorrectly converted by MINGW
|
||||
- Notice `C:\Program Files\Git\` prefix added
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Add MSYS_NO_PATHCONV before command
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
```
|
||||
|
||||
### Problem: Volume appears empty in container
|
||||
|
||||
**Symptoms:**
|
||||
- Container starts successfully
|
||||
- But mounted directory is empty
|
||||
- Files exist on host
|
||||
|
||||
**Diagnosis:**
|
||||
- Path conversion mangled the source path
|
||||
- Docker created empty directory instead
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Use MSYS_NO_PATHCONV with $(pwd)
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd)/data:/data myimage
|
||||
|
||||
# Or use double slash
|
||||
docker run -v //c/Users/project/data:/data myimage
|
||||
|
||||
# Or use named volumes for persistent data
|
||||
docker run -v my-named-volume:/data myimage
|
||||
```
|
||||
|
||||
### Problem: Path with spaces fails
|
||||
|
||||
**Symptoms:**
|
||||
```
|
||||
Error: invalid reference format
|
||||
```
|
||||
|
||||
**Diagnosis:**
|
||||
- Spaces in Windows paths not properly quoted
|
||||
- Path conversion + spaces = disaster
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Use MSYS_NO_PATHCONV and quote $(pwd)
|
||||
MSYS_NO_PATHCONV=1 docker run -v "$(pwd)":/app myimage
|
||||
|
||||
# Or avoid spaces in project paths entirely (RECOMMENDED)
|
||||
# Move project from:
|
||||
# C:/Users/My Name/My Projects/app
|
||||
# To:
|
||||
# C:/Users/MyName/projects/app
|
||||
```
|
||||
|
||||
### Problem: $PWD not working correctly
|
||||
|
||||
**Symptoms:**
|
||||
- Using `$PWD` variable instead of `$(pwd)`
|
||||
- Inconsistent behavior
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# WRONG: Using $PWD
|
||||
docker run -v $PWD:/app myimage
|
||||
|
||||
# CORRECT: Using $(pwd)
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
|
||||
# Explanation:
|
||||
# $(pwd) is a command that returns current directory
|
||||
# $PWD is an environment variable that may not be properly formatted
|
||||
```
|
||||
|
||||
## Testing Your Configuration
|
||||
|
||||
Create a test script to verify Docker volume mounts work correctly:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# test-docker-volume.sh
|
||||
|
||||
echo "Testing Docker volume mounts in Git Bash..."
|
||||
|
||||
# Create test file
|
||||
mkdir -p test-mount
|
||||
echo "Hello from host" > test-mount/test.txt
|
||||
|
||||
# Test 1: With MSYS_NO_PATHCONV
|
||||
echo "Test 1: With MSYS_NO_PATHCONV"
|
||||
MSYS_NO_PATHCONV=1 docker run --rm -v $(pwd)/test-mount:/data alpine cat /data/test.txt
|
||||
|
||||
# Test 2: With double slash
|
||||
echo "Test 2: With double slash"
|
||||
docker run --rm -v //$(pwd)/test-mount:/data alpine cat /data/test.txt
|
||||
|
||||
# Test 3: Without workaround (should fail)
|
||||
echo "Test 3: Without workaround (may fail)"
|
||||
docker run --rm -v $(pwd)/test-mount:/data alpine cat /data/test.txt
|
||||
|
||||
# Cleanup
|
||||
rm -rf test-mount
|
||||
|
||||
echo "Testing complete!"
|
||||
```
|
||||
|
||||
Run it:
|
||||
```bash
|
||||
chmod +x test-docker-volume.sh
|
||||
./test-docker-volume.sh
|
||||
```
|
||||
|
||||
## Recommended Configuration
|
||||
|
||||
Add to your `~/.bashrc`:
|
||||
|
||||
```bash
|
||||
# Docker path conversion fix for Git Bash on Windows
|
||||
export MSYS_NO_PATHCONV=1
|
||||
|
||||
# Or use a wrapper function if you prefer per-command control
|
||||
docker() {
|
||||
(export MSYS_NO_PATHCONV=1; command docker.exe "$@")
|
||||
}
|
||||
export -f docker
|
||||
|
||||
# Alias for docker compose (if needed)
|
||||
alias docker-compose='MSYS_NO_PATHCONV=1 docker compose'
|
||||
```
|
||||
|
||||
## Platform Detection Script
|
||||
|
||||
Use this to automatically detect and configure Docker for Git Bash:
|
||||
|
||||
```bash
|
||||
# Add to ~/.bashrc
|
||||
# Detect if running in Git Bash/MINGW on Windows
|
||||
if [ -n "$MSYSTEM" ] || [[ "$(uname -s)" == MINGW* ]]; then
|
||||
# Running in Git Bash/MINGW
|
||||
echo "Git Bash detected - enabling Docker path conversion fix"
|
||||
export MSYS_NO_PATHCONV=1
|
||||
|
||||
# Optional: Create wrapper function for explicit control
|
||||
docker() {
|
||||
(export MSYS_NO_PATHCONV=1; command docker.exe "$@")
|
||||
}
|
||||
export -f docker
|
||||
fi
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Environment Variables
|
||||
|
||||
| Variable | Purpose | Values |
|
||||
|----------|---------|--------|
|
||||
| `MSYS_NO_PATHCONV` | Disable all path conversion (Git Bash) | `1` to disable |
|
||||
| `MSYS2_ARG_CONV_EXCL` | Exclude specific arguments (MSYS2) | `'*'` or patterns |
|
||||
| `MSYS2_ENV_CONV_EXCL` | Exclude environment variables (MSYS2) | `'*'` or patterns |
|
||||
| `MSYSTEM` | MSYS subsystem indicator | `MINGW64`, `MINGW32`, `MSYS` |
|
||||
|
||||
### Command Patterns
|
||||
|
||||
```bash
|
||||
# RECOMMENDED: Export once per session
|
||||
export MSYS_NO_PATHCONV=1
|
||||
docker run -v $(pwd):/app myimage
|
||||
|
||||
# Per-command prefix
|
||||
MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app myimage
|
||||
|
||||
# Double slash workaround
|
||||
docker run -v //c/Users/project:/app myimage
|
||||
|
||||
# Named volumes (no path issues)
|
||||
docker run -v my-data:/data myimage
|
||||
|
||||
# Docker Compose (relative paths work)
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### What Works Without Modification
|
||||
|
||||
These Docker commands work normally in Git Bash without special handling:
|
||||
|
||||
- Named volumes: `-v my-volume:/data`
|
||||
- Network commands: `docker network create`
|
||||
- Image commands: `docker build`, `docker pull`
|
||||
- Container commands without volumes: `docker run myimage`
|
||||
- Docker Compose with relative paths in YAML
|
||||
|
||||
### What Needs MSYS_NO_PATHCONV
|
||||
|
||||
These commands require path conversion fixes:
|
||||
|
||||
- Bind mounts with absolute paths: `-v /c/Users/project:/app`
|
||||
- Bind mounts with $(pwd): `-v $(pwd):/app`
|
||||
- Volume mounts on docker run command line
|
||||
- Any command with Unix-style absolute paths
|
||||
|
||||
## Summary
|
||||
|
||||
**Best Practice for Git Bash on Windows:**
|
||||
|
||||
1. **Add to ~/.bashrc:** `export MSYS_NO_PATHCONV=1`
|
||||
2. **Use relative paths in docker-compose.yml:** `./src:/app/src`
|
||||
3. **Use named volumes for data:** `my-data:/var/lib/data`
|
||||
4. **Use $(pwd) with MSYS_NO_PATHCONV** for bind mounts: `MSYS_NO_PATHCONV=1 docker run -v $(pwd):/app`
|
||||
|
||||
This configuration ensures Docker commands work correctly in Git Bash on Windows without path conversion issues.
|
||||
Reference in New Issue
Block a user