Skip to content

Commit 1cb8e36

Browse files
committed
feat: Use socat for the Docker socket if needed
1 parent 83f46d5 commit 1cb8e36

File tree

3 files changed

+75
-20
lines changed

3 files changed

+75
-20
lines changed

features/src/docker-out/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Installs a Docker client which re-uses the host Docker socket.
66

77
```json
88
"features": {
9-
"ghcr.io/postfinance/devcontainer-features/docker-out:0.3.0": {
9+
"ghcr.io/postfinance/devcontainer-features/docker-out:0.4.0": {
1010
"version": "latest",
1111
"composeVersion": "latest",
1212
"buildxVersion": "latest",
@@ -36,7 +36,7 @@ Installs a Docker client which re-uses the host Docker socket.
3636

3737
### VS Code Extensions
3838

39-
- `ms-azuretools.vscode-docker`
39+
- `ms-azuretools.vscode-containers`
4040

4141
## Notes
4242

features/src/docker-out/devcontainer-feature.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"id": "docker-out",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"name": "Docker outside Docker",
55
"description": "Installs a Docker client which re-uses the host Docker socket.",
66
"options": {
@@ -51,7 +51,7 @@
5151
"default": "",
5252
"description": "The download URL to use for Docker binaries."
5353
},
54-
"versionsUrl":{
54+
"versionsUrl": {
5555
"type": "string",
5656
"default": "",
5757
"description": "The URL to use for checking available versions."
@@ -70,14 +70,14 @@
7070
"customizations": {
7171
"vscode": {
7272
"extensions": [
73-
"ms-azuretools.vscode-docker"
73+
"ms-azuretools.vscode-containers"
7474
]
7575
}
7676
},
7777
"mounts": [
7878
{
7979
"source": "/var/run/docker.sock",
80-
"target": "/var/run/docker.sock",
80+
"target": "/var/run/docker-host.sock",
8181
"type": "bind"
8282
}
8383
],

features/src/docker-out/docker-init.sh

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,82 @@
11
#!/usr/bin/env bash
22
set -e
33

4-
# Find the GID of the socket
5-
SOCKET_GID=$(stat -c '%g' /var/run/docker.sock)
6-
7-
# Find an existing group with the same GID
8-
# This is needed eg. for alpine which already has GID 999 (ping)
9-
# If this breaks some things, we might need to implement a solution based on socat
10-
EXISTING_GROUP=$(getent group $SOCKET_GID | cut -d: -f1)
11-
if [ -n "$EXISTING_GROUP" ]; then
12-
# Delete this group
13-
sudo groupdel $EXISTING_GROUP
14-
fi
4+
# Wrapper function to only use sudo if not already root
5+
sudoIf() {
6+
if [ "$(id -u)" -ne 0 ]; then
7+
sudo "$@"
8+
else
9+
"$@"
10+
fi
11+
}
12+
13+
# Source socket (socket on the host)
14+
SOURCE_SOCKET="${SOURCE_SOCKET:-"/var/run/docker-host.sock"}"
15+
# Target socket (socket in the container)
16+
TARGET_SOCKET="${TARGET_SOCKET:-"/var/run/docker.sock"}"
1517

1618
# Determine the correct user
1719
USERNAME="${USERNAME:-"${_REMOTE_USER:-"auto"}"}"
1820
if [ "${USERNAME}" = "auto" ]; then
1921
USERNAME=$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)
2022
fi
2123

22-
# Create a matching docker group in the container and add the current user to it
23-
sudo groupadd -g $SOCKET_GID docker
24-
sudo usermod -a -G docker $USERNAME
24+
# Check if the docker group exists
25+
if ! getent group docker > /dev/null 2>&1; then
26+
# Create the docker group
27+
echo "Adding missing docker group"
28+
sudoIf groupadd --system docker
29+
fi
30+
31+
# Add the user to the docker group
32+
sudoIf usermod -a -G docker $USERNAME
33+
34+
# By default, make the source and target sockets the same
35+
if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then
36+
sudoIf touch "${SOURCE_SOCKET}"
37+
sudoIf ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}"
38+
fi
39+
40+
# Get the id of the docker group
41+
DOCKER_GID=$(getent group docker | cut -d: -f3)
42+
43+
# Find the GID of the source socket
44+
SOCKET_GID=$(stat -c '%g' ${SOURCE_SOCKET})
45+
46+
# If the group ids don't match, we need to adjust
47+
if [ "$DOCKER_GID" = "$SOCKET_GID" ]; then
48+
echo "Docker group GID matches socket GID ($DOCKER_GID), no changes needed."
49+
else
50+
# Find an existing group with the same GID as the source socket
51+
EXISTING_GROUP=$(getent group $SOCKET_GID | cut -d: -f1)
52+
# If no group is found, just adjust the docker group to match the socket GID
53+
if [ -z "$EXISTING_GROUP" ]; then
54+
echo "Adjusting docker group GID ($DOCKER_GID) to match socket GID ($SOCKET_GID)."
55+
sudoIf groupmod -g $SOCKET_GID docker
56+
else
57+
# Use socat
58+
echo "Using socat to bridge socket from GID $SOCKET_GID to docker GID $DOCKER_GID."
59+
sudoIf rm -rf ${TARGET_SOCKET}
60+
# Check if socat is installed
61+
if command -v socat > /dev/null 2>&1; then
62+
echo "socat is already installed."
63+
else
64+
echo "socat is not installed. Installing socat."
65+
if command -v apt-get > /dev/null 2>&1; then
66+
# Apt-based
67+
sudoIf apt-get update && sudoIf apt-get install -y socat
68+
elif command -v apk > /dev/null 2>&1; then
69+
# Apk-based
70+
sudoIf apk add socat
71+
else
72+
echo "Error: socat is required but could not be installed. Please install socat manually."
73+
exit 1
74+
fi
75+
fi
76+
# Create the socat bridge
77+
sudoIf socat UNIX-CONNECT:${SOURCE_SOCKET} UNIX-LISTEN:${TARGET_SOCKET},fork,user=${USERNAME},group=docker,mode=660
78+
fi
79+
fi
2580

2681
# Execute whatever commands were passed in (if any). This allows us
2782
# to set this script to ENTRYPOINT while still executing the default CMD.

0 commit comments

Comments
 (0)