Files
tailscale/Dockerfile
Brad Fitzpatrick c3736ae41a Dockerfile: use our own Go toolchain, not the golang Docker image
The golang:N-alpine Docker image lags behind Go minor releases by a
day or two. When we bump go.mod to a new minor version before the
image catches up, the required "Build Docker image" CI check fails
with "go.mod requires go >= 1.27.1 (running go 1.27.0;
GOTOOLCHAIN=local)" and blocks the toolchain bump from merging.

Instead, base the build stage on plain alpine and download the
Tailscale Go toolchain release for the revision in go.toolchain.rev,
matching how everything else in this repo is built.

Fixes #21072

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I1ccb77fa3c7a49532ea87dbdbf9e3340880ec94e
2026-09-01 15:47:33 -07:00

112 lines
4.0 KiB
Docker

# Copyright (c) Tailscale Inc & contributors
# SPDX-License-Identifier: BSD-3-Clause
# Note that this Dockerfile is currently NOT used to build any of the published
# Tailscale container images and may have drifted from the image build mechanism
# we use.
# Tailscale images are currently built using https://github.com/tailscale/mkctr,
# and the build script can be found in ./build_docker.sh.
#
# If you want to build local images for testing, you can use make.
#
# To build a Tailscale image and push to the local docker registry:
#
# $ REPO=local/tailscale TAGS=v0.0.1 PLATFORM=local make publishdevimage
#
# To build a Tailscale image and push to a remote docker registry:
#
# $ REPO=<your-registry>/<your-repo>/tailscale TAGS=v0.0.1 make publishdevimage
#
# This Dockerfile includes all the tailscale binaries.
#
# To build the Dockerfile:
#
# $ docker build -t tailscale/tailscale .
#
# To run the tailscaled agent:
#
# $ docker run -d --name=tailscaled -v /var/lib:/var/lib -v /dev/net/tun:/dev/net/tun --network=host --privileged tailscale/tailscale tailscaled
#
# To then log in:
#
# $ docker exec tailscaled tailscale up
#
# To see status:
#
# $ docker exec tailscaled tailscale status
# Use Tailscale's Go toolchain (a fork of Go) as specified by the
# go.toolchain.rev file, matching how everything else in this repo is
# built, rather than the golang Docker image. This avoids this
# Dockerfile breaking for a day or two after each Go minor version
# bump, when go.mod requires a Go version that the official golang
# Docker image doesn't yet ship. See
# https://github.com/tailscale/tailscale/issues/21072
FROM alpine:3.22 AS build-env
WORKDIR /go/src/tailscale
RUN apk add --no-cache curl tar
COPY go.toolchain.rev ./
RUN read -r REV <go.toolchain.rev && \
case "$(apk --print-arch)" in \
x86_64) ARCH=amd64 ;; \
aarch64) ARCH=arm64 ;; \
*) echo "unsupported architecture" >&2; exit 1 ;; \
esac && \
curl --retry 3 -f -L -o /tmp/go.tar.gz "https://github.com/tailscale/go/releases/download/build-${REV}/linux-${ARCH}.tar.gz" && \
mkdir -p /usr/local/go && \
tar -C /usr/local/go --strip-components=1 -xzf /tmp/go.tar.gz && \
rm /tmp/go.tar.gz
ENV GOPATH=/go
ENV PATH=/usr/local/go/bin:$GOPATH/bin:$PATH
COPY go.mod go.sum ./
RUN go mod download
# Pre-build some stuff before the following COPY line invalidates the Docker cache.
RUN go install \
github.com/aws/aws-sdk-go-v2/aws \
github.com/aws/aws-sdk-go-v2/config \
gvisor.dev/gvisor/pkg/tcpip/adapters/gonet \
gvisor.dev/gvisor/pkg/tcpip/stack \
golang.org/x/crypto/ssh \
golang.org/x/crypto/acme \
github.com/coder/websocket \
github.com/mdlayher/netlink
COPY . .
# see build_docker.sh
ARG VERSION_LONG=""
ENV VERSION_LONG=$VERSION_LONG
ARG VERSION_SHORT=""
ENV VERSION_SHORT=$VERSION_SHORT
ARG VERSION_GIT_HASH=""
ENV VERSION_GIT_HASH=$VERSION_GIT_HASH
ARG TARGETARCH
RUN GOARCH=$TARGETARCH go install -ldflags="\
-X tailscale.com/version.longStamp=$VERSION_LONG \
-X tailscale.com/version.shortStamp=$VERSION_SHORT \
-X tailscale.com/version.gitCommitStamp=$VERSION_GIT_HASH" \
-v ./cmd/tailscale ./cmd/tailscaled ./cmd/containerboot
FROM alpine:3.22
RUN apk add --no-cache ca-certificates iptables iproute2 ip6tables
# Alpine 3.19 replaced legacy iptables with nftables based implementation.
# Tailscale is used on some hosts that don't support nftables, such as Synology
# NAS, so link iptables back to legacy version. Hosts that don't require legacy
# iptables should be able to use Tailscale in nftables mode. See
# https://github.com/tailscale/tailscale/issues/17854
RUN rm /usr/sbin/iptables && ln -s /usr/sbin/iptables-legacy /usr/sbin/iptables
RUN rm /usr/sbin/ip6tables && ln -s /usr/sbin/ip6tables-legacy /usr/sbin/ip6tables
COPY --from=build-env /go/bin/* /usr/local/bin/
# For compat with the previous run.sh, although ideally you should be
# using build_docker.sh which sets an entrypoint for the image.
RUN mkdir /tailscale && ln -s /usr/local/bin/containerboot /tailscale/run.sh