544 lines
13 KiB
Markdown
544 lines
13 KiB
Markdown
---
|
|
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.
|