Skip to content

Commit 3e10209

Browse files
adarnimrodasottile
authored andcommitted
A more reliable way to get the container id.
The hostname is not always the container id. Get the container id from /proc/1/cgroup. Fixes pre-commit#1918.
1 parent 6829425 commit 3e10209

File tree

2 files changed

+65
-36
lines changed

2 files changed

+65
-36
lines changed

pre_commit/languages/docker.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import hashlib
22
import json
33
import os
4-
import socket
54
from typing import Sequence
65
from typing import Tuple
76

@@ -26,12 +25,24 @@ def _is_in_docker() -> bool:
2625
return False
2726

2827

28+
def _get_container_id() -> str:
29+
# It's assumed that we already check /proc/1/cgroup in _is_in_docker. The
30+
# cpuset cgroup controller existed since cgroups were introduced so this
31+
# way of getting the container ID is pretty reliable.
32+
with open('/proc/1/cgroup', 'rb') as f:
33+
for line in f.readlines():
34+
if line.split(b':')[1] == b'cpuset':
35+
return os.path.basename(line.split(b':')[2]).strip().decode()
36+
raise RuntimeError('Failed to find the container ID in /proc/1/cgroup.')
37+
38+
2939
def _get_docker_path(path: str) -> str:
3040
if not _is_in_docker():
3141
return path
32-
hostname = socket.gethostname()
3342

34-
_, out, _ = cmd_output_b('docker', 'inspect', hostname)
43+
container_id = _get_container_id()
44+
45+
_, out, _ = cmd_output_b('docker', 'inspect', container_id)
3546

3647
container, = json.loads(out)
3748
for mount in container['Mounts']:

tests/languages/docker_test.py

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,41 @@
99

1010
from pre_commit.languages import docker
1111

12+
DOCKER_CGROUP_EXAMPLE = b'''\
13+
12:hugetlb:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
14+
11:blkio:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
15+
10:freezer:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
16+
9:cpu,cpuacct:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
17+
8:pids:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
18+
7:rdma:/
19+
6:net_cls,net_prio:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
20+
5:cpuset:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
21+
4:devices:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
22+
3:memory:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
23+
2:perf_event:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
24+
1:name=systemd:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
25+
0::/system.slice/containerd.service
26+
''' # noqa: E501
27+
28+
# The ID should match the above cgroup example.
29+
CONTAINER_ID = 'c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7' # noqa: E501
30+
31+
NON_DOCKER_CGROUP_EXAMPLE = b'''\
32+
12:perf_event:/
33+
11:hugetlb:/
34+
10:devices:/
35+
9:blkio:/
36+
8:rdma:/
37+
7:cpuset:/
38+
6:cpu,cpuacct:/
39+
5:freezer:/
40+
4:memory:/
41+
3:pids:/
42+
2:net_cls,net_prio:/
43+
1:name=systemd:/init.scope
44+
0::/init.scope
45+
'''
46+
1247

1348
def test_docker_fallback_user():
1449
def invalid_attribute():
@@ -37,45 +72,25 @@ def _mock_open(data):
3772

3873

3974
def test_in_docker_docker_in_file():
40-
docker_cgroup_example = b'''\
41-
12:hugetlb:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
42-
11:blkio:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
43-
10:freezer:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
44-
9:cpu,cpuacct:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
45-
8:pids:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
46-
7:rdma:/
47-
6:net_cls,net_prio:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
48-
5:cpuset:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
49-
4:devices:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
50-
3:memory:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
51-
2:perf_event:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
52-
1:name=systemd:/docker/c33988ec7651ebc867cb24755eaf637a6734088bc7eef59d5799293a9e5450f7
53-
0::/system.slice/containerd.service
54-
''' # noqa: E501
55-
with _mock_open(docker_cgroup_example):
75+
with _mock_open(DOCKER_CGROUP_EXAMPLE):
5676
assert docker._is_in_docker() is True
5777

5878

5979
def test_in_docker_docker_not_in_file():
60-
non_docker_cgroup_example = b'''\
61-
12:perf_event:/
62-
11:hugetlb:/
63-
10:devices:/
64-
9:blkio:/
65-
8:rdma:/
66-
7:cpuset:/
67-
6:cpu,cpuacct:/
68-
5:freezer:/
69-
4:memory:/
70-
3:pids:/
71-
2:net_cls,net_prio:/
72-
1:name=systemd:/init.scope
73-
0::/init.scope
74-
'''
75-
with _mock_open(non_docker_cgroup_example):
80+
with _mock_open(NON_DOCKER_CGROUP_EXAMPLE):
7681
assert docker._is_in_docker() is False
7782

7883

84+
def test_get_container_id():
85+
with _mock_open(DOCKER_CGROUP_EXAMPLE):
86+
assert docker._get_container_id() == CONTAINER_ID
87+
88+
89+
def test_get_container_id_failure():
90+
with _mock_open(b''), pytest.raises(RuntimeError):
91+
docker._get_container_id()
92+
93+
7994
def test_get_docker_path_not_in_docker_returns_same():
8095
with mock.patch.object(docker, '_is_in_docker', return_value=False):
8196
assert docker._get_docker_path('abc') == 'abc'
@@ -84,7 +99,10 @@ def test_get_docker_path_not_in_docker_returns_same():
8499
@pytest.fixture
85100
def in_docker():
86101
with mock.patch.object(docker, '_is_in_docker', return_value=True):
87-
yield
102+
with mock.patch.object(
103+
docker, '_get_container_id', return_value=CONTAINER_ID,
104+
):
105+
yield
88106

89107

90108
def _linux_commonpath():

0 commit comments

Comments
 (0)