We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Path is not mounted correctly when running Docker hooks from Docker
**Situation**:

- In our CI we want to run `pre-commit` inside Docker.
- Some of our hooks are `docker_image`

**Problem**
This line mostly https://github.com/pre-commit/pre-commit/blob/528c7afd18dafa6e47ce73add2c8e1550d105674/pre_commit/languages/docker.py#L94

Currently `pre-commit` mounts the current directory to `/src` and uses current directory name as mount base.
However this does not work when `pre-commit` is run inside the container on some mounted path already, because mount points are relative to the host, not to the container.

 Example: 
```
/opt/my_code      <- host, mounts /opt/my_code:/project
/project              <- in Docker running pre-commit, pre-commit is doing mount /project:/src
/src                   <-  (in Dockerized hook)
```

Currently pre-commit will try to mount it as `-v /project:/src,rw,Z`. Expected - to mount it as `-v /opt/my_code:/src`

**Possible solution**:

When I replaced `os.getcwd()` from the code above to `translate_path(os.getcwd())` where `translate_path` is taken from https://gist.github.com/dpfoose/f96d4e4b76c2e01265619d545b77987a, it worked perfectly. It does add extra `docker` pip-dependency though.

**See also**: https://forums.docker.com/t/mounting-a-volume-not-working-with-running-docker-in-docker/25775/2

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pre_commit/languages/docker.py`
Content:
```
1 import hashlib
2 import os
3 from typing import Sequence
4 from typing import Tuple
5 
6 import pre_commit.constants as C
7 from pre_commit.hook import Hook
8 from pre_commit.languages import helpers
9 from pre_commit.prefix import Prefix
10 from pre_commit.util import clean_path_on_failure
11 
12 ENVIRONMENT_DIR = 'docker'
13 PRE_COMMIT_LABEL = 'PRE_COMMIT'
14 get_default_version = helpers.basic_get_default_version
15 healthy = helpers.basic_healthy
16 
17 
18 def md5(s: str) -> str:  # pragma: win32 no cover
19     return hashlib.md5(s.encode()).hexdigest()
20 
21 
22 def docker_tag(prefix: Prefix) -> str:  # pragma: win32 no cover
23     md5sum = md5(os.path.basename(prefix.prefix_dir)).lower()
24     return f'pre-commit-{md5sum}'
25 
26 
27 def build_docker_image(
28         prefix: Prefix,
29         *,
30         pull: bool,
31 ) -> None:  # pragma: win32 no cover
32     cmd: Tuple[str, ...] = (
33         'docker', 'build',
34         '--tag', docker_tag(prefix),
35         '--label', PRE_COMMIT_LABEL,
36     )
37     if pull:
38         cmd += ('--pull',)
39     # This must come last for old versions of docker.  See #477
40     cmd += ('.',)
41     helpers.run_setup_cmd(prefix, cmd)
42 
43 
44 def install_environment(
45         prefix: Prefix, version: str, additional_dependencies: Sequence[str],
46 ) -> None:  # pragma: win32 no cover
47     helpers.assert_version_default('docker', version)
48     helpers.assert_no_additional_deps('docker', additional_dependencies)
49 
50     directory = prefix.path(
51         helpers.environment_dir(ENVIRONMENT_DIR, C.DEFAULT),
52     )
53 
54     # Docker doesn't really have relevant disk environment, but pre-commit
55     # still needs to cleanup its state files on failure
56     with clean_path_on_failure(directory):
57         build_docker_image(prefix, pull=True)
58         os.mkdir(directory)
59 
60 
61 def get_docker_user() -> Tuple[str, ...]:  # pragma: win32 no cover
62     try:
63         return ('-u', f'{os.getuid()}:{os.getgid()}')
64     except AttributeError:
65         return ()
66 
67 
68 def docker_cmd() -> Tuple[str, ...]:  # pragma: win32 no cover
69     return (
70         'docker', 'run',
71         '--rm',
72         *get_docker_user(),
73         # https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from
74         # The `Z` option tells Docker to label the content with a private
75         # unshared label. Only the current container can use a private volume.
76         '-v', f'{os.getcwd()}:/src:rw,Z',
77         '--workdir', '/src',
78     )
79 
80 
81 def run_hook(
82         hook: Hook,
83         file_args: Sequence[str],
84         color: bool,
85 ) -> Tuple[int, bytes]:  # pragma: win32 no cover
86     # Rebuild the docker image in case it has gone missing, as many people do
87     # automated cleanup of docker images.
88     build_docker_image(hook.prefix, pull=False)
89 
90     entry_exe, *cmd_rest = hook.cmd
91 
92     entry_tag = ('--entrypoint', entry_exe, docker_tag(hook.prefix))
93     cmd = (*docker_cmd(), *entry_tag, *cmd_rest)
94     return helpers.run_xargs(hook, cmd, file_args, color=color)
95
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pre_commit/languages/docker.py b/pre_commit/languages/docker.py
--- a/pre_commit/languages/docker.py
+++ b/pre_commit/languages/docker.py
@@ -1,5 +1,7 @@
 import hashlib
+import json
 import os
+import socket
 from typing import Sequence
 from typing import Tuple
 
@@ -8,6 +10,7 @@
 from pre_commit.languages import helpers
 from pre_commit.prefix import Prefix
 from pre_commit.util import clean_path_on_failure
+from pre_commit.util import cmd_output_b
 
 ENVIRONMENT_DIR = 'docker'
 PRE_COMMIT_LABEL = 'PRE_COMMIT'
@@ -15,6 +18,34 @@
 healthy = helpers.basic_healthy
 
 
+def _is_in_docker() -> bool:
+    try:
+        with open('/proc/1/cgroup', 'rb') as f:
+            return b'docker' in f.read()
+    except FileNotFoundError:
+        return False
+
+
+def _get_docker_path(path: str) -> str:
+    if not _is_in_docker():
+        return path
+    hostname = socket.gethostname()
+
+    _, out, _ = cmd_output_b('docker', 'inspect', hostname)
+
+    container, = json.loads(out)
+    for mount in container['Mounts']:
+        src_path = mount['Source']
+        to_path = mount['Destination']
+        if os.path.commonpath((path, to_path)) == to_path:
+            # So there is something in common,
+            # and we can proceed remapping it
+            return path.replace(to_path, src_path)
+    # we're in Docker, but the path is not mounted, cannot really do anything,
+    # so fall back to original path
+    return path
+
+
 def md5(s: str) -> str:  # pragma: win32 no cover
     return hashlib.md5(s.encode()).hexdigest()
 
@@ -73,7 +104,7 @@
         # https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from
         # The `Z` option tells Docker to label the content with a private
         # unshared label. Only the current container can use a private volume.
-        '-v', f'{os.getcwd()}:/src:rw,Z',
+        '-v', f'{_get_docker_path(os.getcwd())}:/src:rw,Z',
         '--workdir', '/src',
     )

{"golden_diff": "diff --git a/pre_commit/languages/docker.py b/pre_commit/languages/docker.py\n--- a/pre_commit/languages/docker.py\n+++ b/pre_commit/languages/docker.py\n@@ -1,5 +1,7 @@\n import hashlib\n+import json\n import os\n+import socket\n from typing import Sequence\n from typing import Tuple\n \n@@ -8,6 +10,7 @@\n from pre_commit.languages import helpers\n from pre_commit.prefix import Prefix\n from pre_commit.util import clean_path_on_failure\n+from pre_commit.util import cmd_output_b\n \n ENVIRONMENT_DIR = 'docker'\n PRE_COMMIT_LABEL = 'PRE_COMMIT'\n@@ -15,6 +18,34 @@\n healthy = helpers.basic_healthy\n \n \n+def _is_in_docker() -> bool:\n+    try:\n+        with open('/proc/1/cgroup', 'rb') as f:\n+            return b'docker' in f.read()\n+    except FileNotFoundError:\n+        return False\n+\n+\n+def _get_docker_path(path: str) -> str:\n+    if not _is_in_docker():\n+        return path\n+    hostname = socket.gethostname()\n+\n+    _, out, _ = cmd_output_b('docker', 'inspect', hostname)\n+\n+    container, = json.loads(out)\n+    for mount in container['Mounts']:\n+        src_path = mount['Source']\n+        to_path = mount['Destination']\n+        if os.path.commonpath((path, to_path)) == to_path:\n+            # So there is something in common,\n+            # and we can proceed remapping it\n+            return path.replace(to_path, src_path)\n+    # we're in Docker, but the path is not mounted, cannot really do anything,\n+    # so fall back to original path\n+    return path\n+\n+\n def md5(s: str) -> str:  # pragma: win32 no cover\n     return hashlib.md5(s.encode()).hexdigest()\n \n@@ -73,7 +104,7 @@\n         # https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from\n         # The `Z` option tells Docker to label the content with a private\n         # unshared label. Only the current container can use a private volume.\n-        '-v', f'{os.getcwd()}:/src:rw,Z',\n+        '-v', f'{_get_docker_path(os.getcwd())}:/src:rw,Z',\n         '--workdir', '/src',\n     )\n", "issue": "Path is not mounted correctly when running Docker hooks from Docker\n**Situation**:\r\n\r\n- In our CI we want to run `pre-commit` inside Docker.\r\n- Some of our hooks are `docker_image`\r\n\r\n**Problem**\r\nThis line mostly https://github.com/pre-commit/pre-commit/blob/528c7afd18dafa6e47ce73add2c8e1550d105674/pre_commit/languages/docker.py#L94\r\n\r\nCurrently `pre-commit` mounts the current directory to `/src` and uses current directory name as mount base.\r\nHowever this does not work when `pre-commit` is run inside the container on some mounted path already, because mount points are relative to the host, not to the container.\r\n\r\n Example: \r\n```\r\n/opt/my_code      <- host, mounts /opt/my_code:/project\r\n/project              <- in Docker running pre-commit, pre-commit is doing mount /project:/src\r\n/src                   <-  (in Dockerized hook)\r\n```\r\n\r\nCurrently pre-commit will try to mount it as `-v /project:/src,rw,Z`. Expected - to mount it as `-v /opt/my_code:/src`\r\n\r\n**Possible solution**:\r\n\r\nWhen I replaced `os.getcwd()` from the code above to `translate_path(os.getcwd())` where `translate_path` is taken from https://gist.github.com/dpfoose/f96d4e4b76c2e01265619d545b77987a, it worked perfectly. It does add extra `docker` pip-dependency though.\r\n\r\n**See also**: https://forums.docker.com/t/mounting-a-volume-not-working-with-running-docker-in-docker/25775/2\n", "before_files": [{"content": "import hashlib\nimport os\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit.hook import Hook\nfrom pre_commit.languages import helpers\nfrom pre_commit.prefix import Prefix\nfrom pre_commit.util import clean_path_on_failure\n\nENVIRONMENT_DIR = 'docker'\nPRE_COMMIT_LABEL = 'PRE_COMMIT'\nget_default_version = helpers.basic_get_default_version\nhealthy = helpers.basic_healthy\n\n\ndef md5(s: str) -> str:  # pragma: win32 no cover\n    return hashlib.md5(s.encode()).hexdigest()\n\n\ndef docker_tag(prefix: Prefix) -> str:  # pragma: win32 no cover\n    md5sum = md5(os.path.basename(prefix.prefix_dir)).lower()\n    return f'pre-commit-{md5sum}'\n\n\ndef build_docker_image(\n        prefix: Prefix,\n        *,\n        pull: bool,\n) -> None:  # pragma: win32 no cover\n    cmd: Tuple[str, ...] = (\n        'docker', 'build',\n        '--tag', docker_tag(prefix),\n        '--label', PRE_COMMIT_LABEL,\n    )\n    if pull:\n        cmd += ('--pull',)\n    # This must come last for old versions of docker.  See #477\n    cmd += ('.',)\n    helpers.run_setup_cmd(prefix, cmd)\n\n\ndef install_environment(\n        prefix: Prefix, version: str, additional_dependencies: Sequence[str],\n) -> None:  # pragma: win32 no cover\n    helpers.assert_version_default('docker', version)\n    helpers.assert_no_additional_deps('docker', additional_dependencies)\n\n    directory = prefix.path(\n        helpers.environment_dir(ENVIRONMENT_DIR, C.DEFAULT),\n    )\n\n    # Docker doesn't really have relevant disk environment, but pre-commit\n    # still needs to cleanup its state files on failure\n    with clean_path_on_failure(directory):\n        build_docker_image(prefix, pull=True)\n        os.mkdir(directory)\n\n\ndef get_docker_user() -> Tuple[str, ...]:  # pragma: win32 no cover\n    try:\n        return ('-u', f'{os.getuid()}:{os.getgid()}')\n    except AttributeError:\n        return ()\n\n\ndef docker_cmd() -> Tuple[str, ...]:  # pragma: win32 no cover\n    return (\n        'docker', 'run',\n        '--rm',\n        *get_docker_user(),\n        # https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from\n        # The `Z` option tells Docker to label the content with a private\n        # unshared label. Only the current container can use a private volume.\n        '-v', f'{os.getcwd()}:/src:rw,Z',\n        '--workdir', '/src',\n    )\n\n\ndef run_hook(\n        hook: Hook,\n        file_args: Sequence[str],\n        color: bool,\n) -> Tuple[int, bytes]:  # pragma: win32 no cover\n    # Rebuild the docker image in case it has gone missing, as many people do\n    # automated cleanup of docker images.\n    build_docker_image(hook.prefix, pull=False)\n\n    entry_exe, *cmd_rest = hook.cmd\n\n    entry_tag = ('--entrypoint', entry_exe, docker_tag(hook.prefix))\n    cmd = (*docker_cmd(), *entry_tag, *cmd_rest)\n    return helpers.run_xargs(hook, cmd, file_args, color=color)\n", "path": "pre_commit/languages/docker.py"}], "after_files": [{"content": "import hashlib\nimport json\nimport os\nimport socket\nfrom typing import Sequence\nfrom typing import Tuple\n\nimport pre_commit.constants as C\nfrom pre_commit.hook import Hook\nfrom pre_commit.languages import helpers\nfrom pre_commit.prefix import Prefix\nfrom pre_commit.util import clean_path_on_failure\nfrom pre_commit.util import cmd_output_b\n\nENVIRONMENT_DIR = 'docker'\nPRE_COMMIT_LABEL = 'PRE_COMMIT'\nget_default_version = helpers.basic_get_default_version\nhealthy = helpers.basic_healthy\n\n\ndef _is_in_docker() -> bool:\n    try:\n        with open('/proc/1/cgroup', 'rb') as f:\n            return b'docker' in f.read()\n    except FileNotFoundError:\n        return False\n\n\ndef _get_docker_path(path: str) -> str:\n    if not _is_in_docker():\n        return path\n    hostname = socket.gethostname()\n\n    _, out, _ = cmd_output_b('docker', 'inspect', hostname)\n\n    container, = json.loads(out)\n    for mount in container['Mounts']:\n        src_path = mount['Source']\n        to_path = mount['Destination']\n        if os.path.commonpath((path, to_path)) == to_path:\n            # So there is something in common,\n            # and we can proceed remapping it\n            return path.replace(to_path, src_path)\n    # we're in Docker, but the path is not mounted, cannot really do anything,\n    # so fall back to original path\n    return path\n\n\ndef md5(s: str) -> str:  # pragma: win32 no cover\n    return hashlib.md5(s.encode()).hexdigest()\n\n\ndef docker_tag(prefix: Prefix) -> str:  # pragma: win32 no cover\n    md5sum = md5(os.path.basename(prefix.prefix_dir)).lower()\n    return f'pre-commit-{md5sum}'\n\n\ndef build_docker_image(\n        prefix: Prefix,\n        *,\n        pull: bool,\n) -> None:  # pragma: win32 no cover\n    cmd: Tuple[str, ...] = (\n        'docker', 'build',\n        '--tag', docker_tag(prefix),\n        '--label', PRE_COMMIT_LABEL,\n    )\n    if pull:\n        cmd += ('--pull',)\n    # This must come last for old versions of docker.  See #477\n    cmd += ('.',)\n    helpers.run_setup_cmd(prefix, cmd)\n\n\ndef install_environment(\n        prefix: Prefix, version: str, additional_dependencies: Sequence[str],\n) -> None:  # pragma: win32 no cover\n    helpers.assert_version_default('docker', version)\n    helpers.assert_no_additional_deps('docker', additional_dependencies)\n\n    directory = prefix.path(\n        helpers.environment_dir(ENVIRONMENT_DIR, C.DEFAULT),\n    )\n\n    # Docker doesn't really have relevant disk environment, but pre-commit\n    # still needs to cleanup its state files on failure\n    with clean_path_on_failure(directory):\n        build_docker_image(prefix, pull=True)\n        os.mkdir(directory)\n\n\ndef get_docker_user() -> Tuple[str, ...]:  # pragma: win32 no cover\n    try:\n        return ('-u', f'{os.getuid()}:{os.getgid()}')\n    except AttributeError:\n        return ()\n\n\ndef docker_cmd() -> Tuple[str, ...]:  # pragma: win32 no cover\n    return (\n        'docker', 'run',\n        '--rm',\n        *get_docker_user(),\n        # https://docs.docker.com/engine/reference/commandline/run/#mount-volumes-from-container-volumes-from\n        # The `Z` option tells Docker to label the content with a private\n        # unshared label. Only the current container can use a private volume.\n        '-v', f'{_get_docker_path(os.getcwd())}:/src:rw,Z',\n        '--workdir', '/src',\n    )\n\n\ndef run_hook(\n        hook: Hook,\n        file_args: Sequence[str],\n        color: bool,\n) -> Tuple[int, bytes]:  # pragma: win32 no cover\n    # Rebuild the docker image in case it has gone missing, as many people do\n    # automated cleanup of docker images.\n    build_docker_image(hook.prefix, pull=False)\n\n    entry_exe, *cmd_rest = hook.cmd\n\n    entry_tag = ('--entrypoint', entry_exe, docker_tag(hook.prefix))\n    cmd = (*docker_cmd(), *entry_tag, *cmd_rest)\n    return helpers.run_xargs(hook, cmd, file_args, color=color)\n", "path": "pre_commit/languages/docker.py"}]}