Skip to content

add Dockerfile and GitHub action for building image #63

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .github/workflows/docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: Docker

on:
push:
# push events will publish a new image, so only trigger on main branch or semver tags.
branches: ["main"]
tags: ["v*"]
pull_request:
# Run the workflow on pull_request events to ensure we can still build the image.
# We only publish the image on push events (see if statements in steps below).
branches: ["main"]

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

concurrency:
group: ${{ github.workflow }}-$${{ github.head_ref || github.run_id }}
cancel-in-progress: true

jobs:
build-and-push-image:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
id-token: write

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup Docker buildx
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0

- name: Log into registry ${{ env.REGISTRY }}
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
if: github.event_name == 'push'
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract Docker metadata
id: meta
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=semver,pattern={{major}}

- name: Build and push Docker image
id: build-and-push
uses: docker/build-push-action@14487ce63c7a62a4a324b0bfb37086795e31c6c1 # v6.16.0
with:
context: .
push: ${{ github.event_name == 'push' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64,linux/arm64,linux/arm/v7

# Sign the Docker image
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

- name: Install cosign
if: github.event_name == 'push'
uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb #v3.8.2
- name: Sign the published Docker image
if: github.event_name == 'push'
run: cosign sign --yes ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ steps.build-and-push.outputs.digest }}
45 changes: 45 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
ARG GO_VERSION=1.24
FROM --platform=$BUILDPLATFORM golang:${GO_VERSION}-alpine as build

Check warning on line 2 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-and-push-image

The 'as' keyword should match the case of the 'from' keyword

FromAsCasing: 'as' and 'FROM' keywords' casing do not match More info: https://docs.docker.com/go/dockerfile/rule/from-as-casing/

WORKDIR /work

# Install git so that go build populates the VCS details in build info, which
# is then reported to Tailscale in the node version string.
RUN apk --no-cache add git=2.47.2-r0

COPY go.mod go.sum ./
RUN go mod download

COPY . .
ARG TARGETOS TARGETARCH TARGETVARIANT
RUN \
if [ "${TARGETARCH}" = "arm" ] && [ -n "${TARGETVARIANT}" ]; then \
export GOARM="${TARGETVARIANT#v}"; \
fi; \
GOOS=${TARGETOS} GOARCH=${TARGETARCH} CGO_ENABLED=0 go build -v ./cmd/caddy

# From https://github.com/caddyserver/caddy-docker/blob/master/2.10/alpine/Dockerfile
FROM alpine:3.21

RUN mkdir -p \
/config/caddy \
/data/caddy \
/etc/caddy \
/usr/share/caddy

COPY --from=build /work/caddy /usr/bin/caddy
COPY examples/simple.caddyfile /etc/caddy/Caddyfile

# See https://caddyserver.com/docs/conventions#file-locations for details
ENV XDG_CONFIG_HOME /config

Check warning on line 34 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-and-push-image

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/
ENV XDG_DATA_HOME /data

Check warning on line 35 in Dockerfile

View workflow job for this annotation

GitHub Actions / build-and-push-image

Legacy key/value format with whitespace separator should not be used

LegacyKeyValueFormat: "ENV key=value" should be used instead of legacy "ENV key value" format More info: https://docs.docker.com/go/dockerfile/rule/legacy-key-value-format/

EXPOSE 80
EXPOSE 443
EXPOSE 443/udp
EXPOSE 2019

WORKDIR /srv

CMD ["run", "--config", "/etc/caddy/Caddyfile"]
ENTRYPOINT ["caddy"]
45 changes: 20 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,6 @@ Alternatively, you can build the included `cmd/caddy` package, or create your ow
go build ./cmd/caddy
```

### Docker Builds

Caddy provides [builder docker images] (e.g. `caddy:2.9-builder`) that have xcaddy pre-installed.
These can be used to build caddy-tailscale in a docker container,
but may result in issues with the Go version used for the build due to project release cycles.

The caddy builder images are built with the specific Go version that was used for that Caddy version.
If a new version of Go has been released, that will not be reflected until a future Caddy release.
Tailscale, and by extension the caddy-tailscale plugin, adopts new Go versions much more quickly,
which may result in a caddy-tailscale version requiring a more recent version of Go than is in the caddy builder image.

This can be addressed in two ways:

1. don't use the caddy builder images directly, but install xcaddy in a newer Go build image
as [discussed in this comment].
2. unset the `GOTOOLCHAIN` environment variable so that Go is able to upgrade itself:

```sh
docker run -e GOTOOLCHAIN= -i -t --rm docker.io/caddy:2.9-builder sh -c "xcaddy build --with github.com/tailscale/caddy-tailscale@fd3f49d73216641b9cbe9167bbb05250c0ffc6d6"
```

[builder docker images]: https://hub.docker.com/_/caddy
[discussed in this comment]: https://github.com/tailscale/caddy-tailscale/issues/34#issuecomment-2145764893

### Running examples

Multiple example configurations are provided in the [examples directory].
Expand All @@ -76,12 +52,31 @@ See the comments in the individual files for details.

Run them with:

```
```sh
TS_AUTHKEY=<tskey-auth-XXXXX> ./caddy run -c examples/<file>
```

[examples directory]: ./examples/

### Docker

caddy-tailscale includes a Dockerfile for building a Caddy image with the plugin included.
This can be built manually, or you can use the pre-built image with:

```sh
docker run -it -rm ghcr.io/tailscale/caddy-tailscale
```

Mount a custom Caddyfile to `/etc/caddy/Caddyfile` and optionally mount a volume
to `/config` to persist the default Tailscale state directory:

```sh
docker run -it -rm \
-e TS_AUTHKEY="tskey-auth-XXX" \
-v ./custom.caddyfile:/etc/caddy/Caddyfile -v ./config:config \
ghcr.io/tailscale/caddy-tailscale
```

## Configuration

In a [Caddyfile], use the `tailscale` [global option] to configure your Tailscale nodes.
Expand Down
Loading