Skip to content

Container Image (Dockerfile) Reference

Reference documentation for the multi-stage Dockerfile at deploy/docker/Dockerfile, which builds the plexd container image.

Base Images

StageImagePurpose
Buildergolang:1.24-alpineGo toolchain for compiling plexd (matches go.mod Go version)
Runtimegcr.io/distroless/static-debian12Minimal runtime with no shell, no package manager, includes CA certificates

Build Command

From the repository root:

bash
docker build -f deploy/docker/Dockerfile .

Or using the Makefile target (injects version metadata from git):

bash
make docker-build

The Makefile target produces the image tagged as ghcr.io/plexsphere/plexd:dev.

Build Arguments

ArgumentDefaultDescription
VERSIONdevVersion string injected via -X main.version ldflags
COMMITnoneGit commit hash injected via -X main.commit ldflags
DATEunknownBuild date injected via -X main.date ldflags
TARGETOSlinuxTarget operating system for cross-compilation (GOOS)
TARGETARCHamd64Target architecture for cross-compilation (GOARCH)

Example with explicit version metadata:

bash
docker build -f deploy/docker/Dockerfile \
    --build-arg VERSION=1.0.0 \
    --build-arg COMMIT=$(git rev-parse --short HEAD) \
    --build-arg DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ) \
    -t ghcr.io/plexsphere/plexd:1.0.0 .

The VERSION, COMMIT, and DATE values are passed to go build -ldflags targeting the variables in cmd/plexd/main.go:

go
var (
    version = "dev"
    commit  = "none"
    date    = "unknown"
)

Multi-Platform Builds

The Dockerfile supports building for linux/amd64 and linux/arm64 using Docker BuildKit's automatic TARGETOS and TARGETARCH arguments.

Build for a single platform:

bash
docker buildx build -f deploy/docker/Dockerfile --platform linux/arm64 -t ghcr.io/plexsphere/plexd:dev .

Build and push a multi-arch manifest:

bash
docker buildx build -f deploy/docker/Dockerfile \
    --platform linux/amd64,linux/arm64 \
    -t ghcr.io/plexsphere/plexd:latest \
    --push .

Exposed Ports

PortProtocolPurpose
9100TCPHTTP health checks (/healthz, /readyz) and local node API
51820UDPWireGuard mesh traffic

These match the liveness/readiness probes in deploy/kubernetes/daemonset.yaml and the default wireguard.listen_port in the configuration.

Runtime User

The container runs as non-root user 65534:65534 (nobody). This can be overridden at runtime for privileged deployments that require NET_ADMIN capability (e.g., Kubernetes DaemonSet with securityContext).

Directory Layout

DirectoryPurpose
/usr/local/bin/plexdStatically compiled plexd binary
/var/lib/plexdPersistent data (state cache, node state)
/var/run/plexdRuntime files (Unix socket, PID)
/var/log/plexdLog files (startup log)
/etc/plexdConfiguration files

All directories are created during the build with ownership set to 65534:65534. In Kubernetes, these paths are typically backed by volume mounts (see deploy/kubernetes/daemonset.yaml).

Entrypoint

The entrypoint is set to the binary in exec form:

dockerfile
ENTRYPOINT ["/usr/local/bin/plexd"]

Pass any subcommand as arguments: up, join, status, etc. Use --version flag to display version information.

Build Optimizations

  • Module cache layer: go.mod and go.sum are copied and modules downloaded before the full source tree is copied. Source-only changes reuse the cached module layer.
  • Static binary: Built with CGO_ENABLED=0 and ldflags -s -w (stripped debug info and DWARF tables) for minimal binary size.
  • Distroless base: The runtime image contains no shell, package manager, or unnecessary utilities — only the binary and CA certificates.

.dockerignore

The .dockerignore file at the repository root excludes non-essential files from the Docker build context:

PatternReason
.git/Git history not needed for build
.github/CI workflows not needed for build
.planwerk/, .claude/, .serena/Tooling directories
docs/Documentation not needed for build
deploy/systemd/, deploy/kubernetes/, deploy/cloud-init/Deploy manifests not needed for build
deploy/install.sh, deploy/install_test.shInstall scripts not needed for build
*_test.go, *_test.shTest files not needed for build
*.mdMarkdown files not needed for build
LICENSELicense file not needed for build

The build context includes: go.mod, go.sum, cmd/, internal/, Makefile, and deploy/docker/Dockerfile.

Testing

Run the Dockerfile validation tests (requires Docker):

bash
sh deploy/docker/test_dockerfile.sh

The test script validates: hadolint compliance, successful build, version argument injection, non-root user, static binary, exposed ports, entrypoint, image size (< 30 MB), directory existence, and .dockerignore exclusions.