hostinfo,build_docker.sh,tailcfg: more reliably detect being in a container (#13826)

Our existing container-detection tricks did not work on Kubernetes,
where Docker is no longer used as a container runtime. Extends the
existing go build tags for containers to the other container packages
and uses that to reliably detect builds that were created by Tailscale
for use in a container. Unfortunately this doesn't necessarily improve
detection for users' custom builds, but that's a separate issue.

Updates #13825

Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
This commit is contained in:
Tom Proctor 2024-10-15 19:38:11 +01:00 committed by GitHub
parent a8f9c0d6e4
commit 5f22f72636
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 37 additions and 4 deletions

View File

@ -56,6 +56,7 @@ case "$TARGET" in
-X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \ -X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \
--base="${BASE}" \ --base="${BASE}" \
--tags="${TAGS}" \ --tags="${TAGS}" \
--gotags="ts_kube,ts_package_container" \
--repos="${REPOS}" \ --repos="${REPOS}" \
--push="${PUSH}" \ --push="${PUSH}" \
--target="${PLATFORM}" \ --target="${PLATFORM}" \
@ -72,6 +73,7 @@ case "$TARGET" in
-X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \ -X tailscale.com/version.gitCommitStamp=${VERSION_GIT_HASH}" \
--base="${BASE}" \ --base="${BASE}" \
--tags="${TAGS}" \ --tags="${TAGS}" \
--gotags="ts_kube,ts_package_container" \
--repos="${REPOS}" \ --repos="${REPOS}" \
--push="${PUSH}" \ --push="${PUSH}" \
--target="${PLATFORM}" \ --target="${PLATFORM}" \

View File

@ -280,13 +280,22 @@ func getEnvType() EnvType {
return "" return ""
} }
// inContainer reports whether we're running in a container. // inContainer reports whether we're running in a container. Best-effort only,
// there's no foolproof way to detect this, but the build tag should catch all
// official builds from 1.78.0.
func inContainer() opt.Bool { func inContainer() opt.Bool {
if runtime.GOOS != "linux" { if runtime.GOOS != "linux" {
return "" return ""
} }
var ret opt.Bool var ret opt.Bool
ret.Set(false) ret.Set(false)
if packageType != nil && packageType() == "container" {
// Go build tag ts_package_container was set during build.
ret.Set(true)
return ret
}
// Only set if using docker's container runtime. Not guaranteed by
// documentation, but it's been in place for a long time.
if _, err := os.Stat("/.dockerenv"); err == nil { if _, err := os.Stat("/.dockerenv"); err == nil {
ret.Set(true) ret.Set(true)
return ret return ret
@ -362,7 +371,7 @@ func inFlyDotIo() bool {
} }
func inReplit() bool { func inReplit() bool {
// https://docs.replit.com/programming-ide/getting-repl-metadata // https://docs.replit.com/replit-workspace/configuring-repl#environment-variables
if os.Getenv("REPL_OWNER") != "" && os.Getenv("REPL_SLUG") != "" { if os.Getenv("REPL_OWNER") != "" && os.Getenv("REPL_SLUG") != "" {
return true return true
} }

View File

@ -0,0 +1,16 @@
// Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause
//go:build linux && !android && ts_package_container
package hostinfo
import (
"testing"
)
func TestInContainer(t *testing.T) {
if got := inContainer(); !got.EqualBool(true) {
t.Errorf("inContainer = %v; want true due to ts_package_container build tag", got)
}
}

View File

@ -1,7 +1,7 @@
// Copyright (c) Tailscale Inc & AUTHORS // Copyright (c) Tailscale Inc & AUTHORS
// SPDX-License-Identifier: BSD-3-Clause // SPDX-License-Identifier: BSD-3-Clause
//go:build linux && !android //go:build linux && !android && !ts_package_container
package hostinfo package hostinfo
@ -34,3 +34,9 @@ func TestQnap(t *testing.T) {
t.Errorf("got %q; want %q", got, want) t.Errorf("got %q; want %q", got, want)
} }
} }
func TestInContainer(t *testing.T) {
if got := inContainer(); !got.EqualBool(false) {
t.Errorf("inContainer = %v; want false due to absence of ts_package_container build tag", got)
}
}

View File

@ -771,7 +771,7 @@ type Hostinfo struct {
// "5.10.0-17-amd64". // "5.10.0-17-amd64".
OSVersion string `json:",omitempty"` OSVersion string `json:",omitempty"`
Container opt.Bool `json:",omitempty"` // whether the client is running in a container Container opt.Bool `json:",omitempty"` // best-effort whether the client is running in a container
Env string `json:",omitempty"` // a hostinfo.EnvType in string form Env string `json:",omitempty"` // a hostinfo.EnvType in string form
Distro string `json:",omitempty"` // "debian", "ubuntu", "nixos", ... Distro string `json:",omitempty"` // "debian", "ubuntu", "nixos", ...
DistroVersion string `json:",omitempty"` // "20.04", ... DistroVersion string `json:",omitempty"` // "20.04", ...