Skip to content

Commit 67847c8

Browse files
committed
Adding a flag to switch the logic for better management.
1 parent b8312b4 commit 67847c8

6 files changed

Lines changed: 108 additions & 28 deletions

File tree

src/docker-in-docker/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Create child containers *inside* a container, independent from the host's docker
2424
| installDockerBuildx | Install Docker Buildx | boolean | true |
2525
| installDockerComposeSwitch | Install Compose Switch (provided docker compose is available) which is a replacement to the Compose V1 docker-compose (python) executable. It translates the command line into Compose V2 docker compose then runs the latter. | boolean | false |
2626
| disableIp6tables | Disable ip6tables (this option is only applicable for Docker versions 27 and greater) | boolean | false |
27+
| iptablesSwitchAtRuntime | If true, the iptables alternative is selected at container start (inside docker-init.sh) instead of at image build time. Useful when the desired iptables backend depends on the host kernel at runtime rather than at build time. | boolean | false |
2728

2829
## Customizations
2930

src/docker-in-docker/devcontainer-feature.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,11 @@
6060
"type": "boolean",
6161
"default": false,
6262
"description": "Disable ip6tables (this option is only applicable for Docker versions 27 and greater)"
63+
},
64+
"iptablesSwitchAtRuntime": {
65+
"type": "boolean",
66+
"default": false,
67+
"description": "If true, the iptables alternative is selected at container start (inside docker-init.sh) instead of at image build time. Useful when the desired iptables backend depends on the host kernel at runtime rather than at build time."
6368
}
6469
},
6570
"entrypoint": "/usr/local/share/docker-init.sh",

src/docker-in-docker/install.sh

Lines changed: 29 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ MICROSOFT_GPG_KEYS_ROLLING_URI="https://packages.microsoft.com/keys/microsoft-ro
2222
DOCKER_MOBY_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal jammy noble"
2323
DOCKER_LICENSED_ARCHIVE_VERSION_CODENAMES="trixie bookworm buster bullseye bionic focal hirsute impish jammy noble resolute"
2424
DISABLE_IP6_TABLES="${DISABLEIP6TABLES:-false}"
25+
IPTABLES_SWITCH_AT_RUNTIME="${IPTABLESSWITCHATRUNTIME:-false}"
2526

2627
# Default: Exit on any failure.
2728
set -e
@@ -313,29 +314,31 @@ if [ "${ADJUSTED_ID}" = "debian" ] && command -v update-ca-certificates > /dev/n
313314
update-ca-certificates
314315
fi
315316

316-
# Swap to legacy iptables for compatibility (Debian only)
317-
#if [ "${ADJUSTED_ID}" = "debian" ]; then
317+
# Swap to legacy iptables for compatibility (Debian only) - install-time path.
318+
# When IPTABLES_SWITCH_AT_RUNTIME=true the same logic is emitted into
319+
# docker-init.sh and runs at container start instead.
320+
if [ "${IPTABLES_SWITCH_AT_RUNTIME}" != "true" ] && [ "${ADJUSTED_ID}" = "debian" ]; then
318321
# On distros where legacy iptables is no longer kernel-supported (e.g. Ubuntu 26.04 / resolute),
319322
# prefer iptables-nft. Otherwise prefer legacy for backward compatibility.
320-
# use_nft=false
321-
# case "${VERSION_CODENAME}" in
322-
# resolute) use_nft=true ;;
323-
# esac
324-
325-
# if [ "${use_nft}" = "true" ] && type iptables-nft > /dev/null 2>&1; then
326-
# echo "(*) Setting iptables alternatives to nft for better compatibility with newer kernels"
327-
# update-alternatives --set iptables /usr/sbin/iptables-nft || true
328-
# update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true
329-
# elif type iptables-legacy > /dev/null 2>&1 && iptables-legacy -L > /dev/null 2>&1; then
330-
# echo "(*) Setting iptables alternatives to legacy for better compatibility with Docker and older kernels"
331-
# update-alternatives --set iptables /usr/sbin/iptables-legacy || true
332-
# update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true
333-
# elif type iptables-nft > /dev/null 2>&1; then
334-
# echo "(*) Setting iptables alternatives to nft for better compatibility with newer kernels for non resolute"
335-
# update-alternatives --set iptables /usr/sbin/iptables-nft || true
336-
# update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true
337-
# fi
338-
#fi
323+
use_nft=false
324+
case "${VERSION_CODENAME}" in
325+
resolute) use_nft=true ;;
326+
esac
327+
328+
if [ "${use_nft}" = "true" ] && type iptables-nft > /dev/null 2>&1; then
329+
echo "(*) Setting iptables alternatives to nft for better compatibility with newer kernels"
330+
update-alternatives --set iptables /usr/sbin/iptables-nft || true
331+
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true
332+
elif type iptables-legacy > /dev/null 2>&1 && iptables-legacy -L > /dev/null 2>&1; then
333+
echo "(*) Setting iptables alternatives to legacy for better compatibility with Docker and older kernels"
334+
update-alternatives --set iptables /usr/sbin/iptables-legacy || true
335+
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy || true
336+
elif type iptables-nft > /dev/null 2>&1; then
337+
echo "(*) Setting iptables alternatives to nft for better compatibility with newer kernels for non resolute"
338+
update-alternatives --set iptables /usr/sbin/iptables-nft || true
339+
update-alternatives --set ip6tables /usr/sbin/ip6tables-nft || true
340+
fi
341+
fi
339342

340343
# Set up the necessary repositories
341344
if [ "${USE_MOBY}" = "true" ]; then
@@ -973,13 +976,15 @@ DOCKER_DEFAULT_ADDRESS_POOL=${DOCKER_DEFAULT_ADDRESS_POOL}
973976
DOCKER_DEFAULT_IP6_TABLES=${DOCKER_DEFAULT_IP6_TABLES}
974977
EOF
975978

976-
# On Debian-based images, re-assert the iptables alternative at container start.
977-
if [ "${ADJUSTED_ID}" = "debian" ]; then
979+
# On Debian-based images, re-assert the iptables alternative at container start
980+
# (only when the user opted into runtime switching via iptablesSwitchAtRuntime=true).
981+
if [ "${IPTABLES_SWITCH_AT_RUNTIME}" = "true" ] && [ "${ADJUSTED_ID}" = "debian" ]; then
978982
tee -a /usr/local/share/docker-init.sh > /dev/null \
979983
<< 'EOF'
980984
# Prefer legacy only when the ip_tables kernel module is actually present.
981985
# (Do NOT call `iptables-legacy -L/-nL` to test this — it auto-modprobes ip_tables
982-
# and would defeat hosts/scenarios where the module is intentionally absent.)
986+
# and would defeat hosts/scenarios where the module is intentionally absent
987+
# such as the newer kernels which leaves out ip_tables legacy.)
983988
if type iptables-legacy > /dev/null 2>&1 \
984989
&& { grep -qE '^(ip_tables)\b' /proc/modules \
985990
|| [ -d /sys/module/ip_tables ]; } \
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# Default behavior (iptablesSwitchAtRuntime omitted -> false): switching happens
9+
# at image build time, so docker-init.sh should NOT contain the runtime block.
10+
check "init-script-exists" bash -c "test -f /usr/local/share/docker-init.sh"
11+
check "no-runtime-iptables-block" bash -c "! grep -q 'update-alternatives --set iptables' /usr/local/share/docker-init.sh"
12+
13+
# The build-time switch should have set /etc/alternatives/iptables to one of the
14+
# known backends. With the ip_tables module loaded on the host, legacy is preferred.
15+
check "iptables-alternative-set" bash -c "readlink /etc/alternatives/iptables | grep -E 'iptables-(legacy|nft)$'"
16+
check "iptables works" sudo iptables -L
17+
18+
check "version" docker --version
19+
check "docker-ps" bash -c "docker ps"
20+
21+
# Report result
22+
reportResults
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Optional: Import test library
6+
source dev-container-features-test-lib
7+
8+
# iptablesSwitchAtRuntime=true: switching is deferred to container start, so the
9+
# runtime block MUST have been written into docker-init.sh by install.sh.
10+
check "init-script-exists" bash -c "test -f /usr/local/share/docker-init.sh"
11+
check "runtime-iptables-block-present" bash -c "grep -q 'update-alternatives --set iptables' /usr/local/share/docker-init.sh"
12+
check "runtime-iptables-block-has-legacy-branch" bash -c "grep -q '/usr/sbin/iptables-legacy' /usr/local/share/docker-init.sh"
13+
check "runtime-iptables-block-has-nft-branch" bash -c "grep -q '/usr/sbin/iptables-nft' /usr/local/share/docker-init.sh"
14+
15+
# The runtime block runs as part of docker-init.sh (the feature's entrypoint),
16+
# so by the time these tests execute the alternative must already be set.
17+
check "iptables-alternative-set" bash -c "readlink /etc/alternatives/iptables | grep -E 'iptables-(legacy|nft)$'"
18+
check "iptables works" sudo iptables -L
19+
20+
check "version" docker --version
21+
check "docker-ps" bash -c "docker ps"
22+
23+
# Report result
24+
reportResults

test/docker-in-docker/scenarios.json

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,39 @@
11
{
2-
"docker_without_iptables": {
2+
"docker_iptables_switch_at_install": {
33
"image": "mcr.microsoft.com/devcontainers/base:debian",
44
"features": {
55
"docker-in-docker": {
66
"moby": "false"
77
}
88
},
9+
"initializeCommand": "sudo modprobe ip_tables"
10+
},
11+
"docker_iptables_switch_at_runtime": {
12+
"image": "mcr.microsoft.com/devcontainers/base:debian",
13+
"features": {
14+
"docker-in-docker": {
15+
"moby": "false",
16+
"iptablesSwitchAtRuntime": true
17+
}
18+
},
19+
"initializeCommand": "sudo modprobe ip_tables"
20+
},
21+
"docker_without_iptables": {
22+
"image": "mcr.microsoft.com/devcontainers/base:debian",
23+
"features": {
24+
"docker-in-docker": {
25+
"moby": "false",
26+
"iptablesSwitchAtRuntime": true
27+
}
28+
},
929
"initializeCommand": "sudo modprobe --remove --remove-holders --wait 1000 ip_tables"
1030
},
1131
"docker_with_iptables": {
1232
"image": "mcr.microsoft.com/devcontainers/base:debian",
1333
"features": {
1434
"docker-in-docker": {
15-
"moby": "false"
35+
"moby": "false",
36+
"iptablesSwitchAtRuntime": true
1637
}
1738
},
1839
"initializeCommand": "sudo modprobe ip_tables"
@@ -21,7 +42,8 @@
2142
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
2243
"features": {
2344
"docker-in-docker": {
24-
"moby": "false"
45+
"moby": "false",
46+
"iptablesSwitchAtRuntime": true
2547
}
2648
},
2749
"initializeCommand": "sudo modprobe --remove --remove-holders --wait 1000 ip_tables"
@@ -30,7 +52,8 @@
3052
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
3153
"features": {
3254
"docker-in-docker": {
33-
"moby": "false"
55+
"moby": "false",
56+
"iptablesSwitchAtRuntime": true
3457
}
3558
},
3659
"initializeCommand": "sudo modprobe ip_tables"

0 commit comments

Comments
 (0)