home / skills / josiahsiegel / claude-plugin-marketplace / docker-git-bash-guide

docker-git-bash-guide skill

/plugins/docker-master/skills/docker-git-bash-guide

npx playbooks add skill josiahsiegel/claude-plugin-marketplace --skill docker-git-bash-guide

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
13.1 KB
---
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.