Skip to content

Commit 5523f09

Browse files
konardclaude
andcommitted
fix(shell): auto-repair DNS resolution at container startup
Docker's internal DNS resolver (127.0.0.11) intermittently loses its upstream nameservers, breaking domain resolution inside containers. - Add dns-repair step to entrypoint: probes github.com at startup, appends fallback nameservers (8.8.8.8, 8.8.4.4, 1.1.1.1) to /etc/resolv.conf when resolution fails - Add explicit dns configuration to docker-compose template for both main service and browser sidecar - Update example docker-compose.yml and entrypoint.sh Fixes #168 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 1185d9b commit 5523f09

5 files changed

Lines changed: 96 additions & 1 deletion

File tree

docker-compose.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ services:
99
CODEX_HOME: "/home/dev/.codex"
1010
ports:
1111
- "127.0.0.1:2222:22"
12+
dns:
13+
- 8.8.8.8
14+
- 8.8.4.4
15+
- 1.1.1.1
1216
volumes:
1317
- dev_home:/home/dev
1418
- ./authorized_keys:/authorized_keys:ro

entrypoint.sh

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,42 @@
1111
# COMPLEXITY: O(network + repo_size)
1212
set -euo pipefail
1313

14+
# 0) Ensure DNS resolution works; repair /etc/resolv.conf if Docker DNS is broken
15+
docker_git_repair_dns() {
16+
local test_domain="github.com"
17+
local resolv="/etc/resolv.conf"
18+
local fallback_dns="8.8.8.8 8.8.4.4 1.1.1.1"
19+
20+
if getent hosts "$test_domain" >/dev/null 2>&1; then
21+
return 0
22+
fi
23+
24+
echo "[dns-repair] DNS resolution failed for $test_domain; attempting repair..."
25+
26+
local has_external=0
27+
for ns in $fallback_dns; do
28+
if grep -q "nameserver $ns" "$resolv" 2>/dev/null; then
29+
has_external=1
30+
fi
31+
done
32+
33+
if [[ "$has_external" -eq 0 ]]; then
34+
for ns in $fallback_dns; do
35+
printf "nameserver %s\n" "$ns" >> "$resolv"
36+
done
37+
echo "[dns-repair] appended fallback nameservers to $resolv"
38+
fi
39+
40+
if getent hosts "$test_domain" >/dev/null 2>&1; then
41+
echo "[dns-repair] DNS resolution restored"
42+
return 0
43+
fi
44+
45+
echo "[dns-repair] WARNING: DNS resolution still failing after repair attempt"
46+
return 1
47+
}
48+
docker_git_repair_dns || true
49+
1450
REPO_URL="${REPO_URL:-}"
1551
REPO_REF="${REPO_REF:-}"
1652
TARGET_DIR="${TARGET_DIR:-/work/app}"

packages/lib/src/core/templates-entrypoint.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
renderEntrypointZshShell,
1212
renderEntrypointZshUserRc
1313
} from "./templates-entrypoint/base.js"
14+
import { renderEntrypointDnsRepair } from "./templates-entrypoint/dns-repair.js"
1415
import { renderEntrypointClaudeConfig } from "./templates-entrypoint/claude.js"
1516
import {
1617
renderEntrypointAgentsNotice,
@@ -34,6 +35,7 @@ import {
3435
export const renderEntrypoint = (config: TemplateConfig): string =>
3536
[
3637
renderEntrypointHeader(config),
38+
renderEntrypointDnsRepair(),
3739
renderEntrypointPackageCache(config),
3840
renderEntrypointAuthorizedKeys(config),
3941
renderEntrypointCodexHome(config),
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// CHANGE: add automatic DNS repair at container startup
2+
// WHY: Docker internal DNS (127.0.0.11) intermittently loses external nameservers,
3+
// causing domain resolution to fail inside containers
4+
// QUOTE(ТЗ): "При запуске контейнера он всегда исправляет интернет соединение потому что оно время от времени ложится"
5+
// REF: issue-168
6+
// SOURCE: n/a
7+
// FORMAT THEOREM: ∀container: startup(container) → dns_healthy(container) ∨ dns_repaired(container)
8+
// PURITY: SHELL
9+
// EFFECT: Effect<void, DnsRepairError, Env>
10+
// INVARIANT: after execution, at least one nameserver in /etc/resolv.conf resolves external domains
11+
// COMPLEXITY: O(1) per probe attempt, O(max_attempts) worst case
12+
export const renderEntrypointDnsRepair = (): string =>
13+
`# 0) Ensure DNS resolution works; repair /etc/resolv.conf if Docker DNS is broken
14+
docker_git_repair_dns() {
15+
local test_domain="github.com"
16+
local resolv="/etc/resolv.conf"
17+
local fallback_dns="8.8.8.8 8.8.4.4 1.1.1.1"
18+
19+
if getent hosts "$test_domain" >/dev/null 2>&1; then
20+
return 0
21+
fi
22+
23+
echo "[dns-repair] DNS resolution failed for $test_domain; attempting repair..."
24+
25+
# Preserve Docker internal resolver but append external fallbacks
26+
local has_external=0
27+
for ns in $fallback_dns; do
28+
if grep -q "nameserver $ns" "$resolv" 2>/dev/null; then
29+
has_external=1
30+
fi
31+
done
32+
33+
if [[ "$has_external" -eq 0 ]]; then
34+
for ns in $fallback_dns; do
35+
printf "nameserver %s\\n" "$ns" >> "$resolv"
36+
done
37+
echo "[dns-repair] appended fallback nameservers to $resolv"
38+
fi
39+
40+
# Verify fix
41+
if getent hosts "$test_domain" >/dev/null 2>&1; then
42+
echo "[dns-repair] DNS resolution restored"
43+
return 0
44+
fi
45+
46+
echo "[dns-repair] WARNING: DNS resolution still failing after repair attempt"
47+
return 1
48+
}
49+
docker_git_repair_dns || true`

packages/lib/src/core/templates/docker-compose.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ const buildPlaywrightFragments = (
8484
maybeBrowserService:
8585
`\n ${browserServiceName}:\n build:\n context: .\n dockerfile: ${browserDockerfile}\n container_name: ${browserContainerName}\n restart: unless-stopped\n${
8686
renderResourceLimits(resourceLimits)
87-
} environment:\n VNC_NOPW: "1"\n shm_size: "2gb"\n expose:\n - "9223"\n volumes:\n - ${browserVolumeName}:/data\n networks:\n - ${networkName}\n`,
87+
} environment:\n VNC_NOPW: "1"\n shm_size: "2gb"\n expose:\n - "9223"\n dns:\n - 8.8.8.8\n - 8.8.4.4\n - 1.1.1.1\n volumes:\n - ${browserVolumeName}:/data\n networks:\n - ${networkName}\n`,
8888
maybeBrowserVolume: ` ${browserVolumeName}:\n`
8989
}
9090
}
@@ -153,6 +153,10 @@ ${renderResourceLimits(resourceLimits)} volumes:
153153
- ${config.codexAuthPath}:${config.codexHome}
154154
- ${renderSharedCodexHostMount(config.dockerGitPath)}:${config.codexHome}-shared
155155
- /var/run/docker.sock:/var/run/docker.sock
156+
dns:
157+
- 8.8.8.8
158+
- 8.8.4.4
159+
- 1.1.1.1
156160
networks:
157161
- ${fragments.networkName}
158162
${fragments.maybeBrowserService}`

0 commit comments

Comments
 (0)