fix: ensure data paths are set correctly in docker, fixes #958 (#959)

This commit is contained in:
Stavros
2026-07-01 16:12:46 +03:00
committed by GitHub
parent ffafb5bff5
commit a6c716c4e2
8 changed files with 109 additions and 35 deletions
+7 -5
View File
@@ -52,15 +52,17 @@ WORKDIR /tinyauth
COPY --from=builder /tinyauth/tinyauth ./ COPY --from=builder /tinyauth/tinyauth ./
RUN mkdir -p /data
EXPOSE 3000 EXPOSE 3000
# Make the data directory with a non-root user
RUN addgroup tinyauth && adduser -DH tinyauth -G tinyauth
RUN mkdir -p /data/resources /data/oidc /data/tailscale
RUN chown -R tinyauth:tinyauth /data
VOLUME ["/data"] VOLUME ["/data"]
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db # Tell tinyauth that it's running in a container and where to find the data directory
ENV RUNTIME_ENV=docker
ENV TINYAUTH_RESOURCES_PATH=/data/resources
ENV PATH=$PATH:/tinyauth ENV PATH=$PATH:/tinyauth
+8 -6
View File
@@ -40,13 +40,16 @@ COPY ./cmd ./cmd
COPY ./internal ./internal COPY ./internal ./internal
COPY --from=frontend-builder /frontend/dist ./internal/assets/dist COPY --from=frontend-builder /frontend/dist ./internal/assets/dist
RUN mkdir -p data
RUN CGO_ENABLED=0 go build -ldflags "${LDFLAGS} \ RUN CGO_ENABLED=0 go build -ldflags "${LDFLAGS} \
-X github.com/tinyauthapp/tinyauth/internal/model.Version=${VERSION} \ -X github.com/tinyauthapp/tinyauth/internal/model.Version=${VERSION} \
-X github.com/tinyauthapp/tinyauth/internal/model.CommitHash=${COMMIT_HASH} \ -X github.com/tinyauthapp/tinyauth/internal/model.CommitHash=${COMMIT_HASH} \
-X github.com/tinyauthapp/tinyauth/internal/model.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth -X github.com/tinyauthapp/tinyauth/internal/model.BuildTimestamp=${BUILD_TIMESTAMP}" ./cmd/tinyauth
# Make the data directory with a non-root user
RUN addgroup tinyauth && adduser -DH tinyauth -G tinyauth
RUN mkdir -p /data/resources /data/oidc /data/tailscale
RUN chown -R tinyauth:tinyauth /data
# Runner # Runner
FROM gcr.io/distroless/static-debian12:latest AS runner FROM gcr.io/distroless/static-debian12:latest AS runner
@@ -55,15 +58,14 @@ WORKDIR /tinyauth
COPY --from=builder /tinyauth/tinyauth ./ COPY --from=builder /tinyauth/tinyauth ./
# Since it's distroless, we need to copy the data directory from the builder stage # Since it's distroless, we need to copy the data directory from the builder stage
COPY --from=builder /tinyauth/data /data COPY --from=builder /data /data
EXPOSE 3000 EXPOSE 3000
VOLUME ["/data"] VOLUME ["/data"]
ENV TINYAUTH_DATABASE_PATH=/data/tinyauth.db # Tell tinyauth that it's running in a container and where to find the data directory
ENV RUNTIME_ENV=docker
ENV TINYAUTH_RESOURCES_PATH=/data/resources
ENV PATH=$PATH:/tinyauth ENV PATH=$PATH:/tinyauth
+10 -3
View File
@@ -16,6 +16,8 @@ PROD_COMPOSE := $(shell test -f "docker-compose.test.prod.yml" && echo "docker-c
.DEFAULT_GOAL := binary .DEFAULT_GOAL := binary
.PHONY: deps clean-data clean-webui webui binary binary-linux-amd64 binary-linux-arm64 test vet test-race dev dev-infisical prod prod-infisical sql generate docker docker-distroless
# Deps # Deps
deps: deps:
cd frontend && pnpm ci cd frontend && pnpm ci
@@ -58,12 +60,10 @@ binary-linux-arm64:
$(MAKE) binary $(MAKE) binary
# Go test # Go test
.PHONY: test
test: test:
go test -v ./... go test -v ./...
# Go vet # Go vet
.PHONY: vet
vet: vet:
go vet ./... go vet ./...
@@ -88,7 +88,6 @@ prod-infisical:
infisical run --env=dev -- docker compose -f $(PROD_COMPOSE) up --force-recreate --pull=always --remove-orphans infisical run --env=dev -- docker compose -f $(PROD_COMPOSE) up --force-recreate --pull=always --remove-orphans
# SQL # SQL
.PHONY: sql
sql: sql:
sqlc generate sqlc generate
@@ -96,3 +95,11 @@ sql:
generate: generate:
go run ./gen go run ./gen
go generate ./internal/repository/... go generate ./internal/repository/...
# Docker image
docker:
docker buildx build -t tinyauthapp/tinyauth:dev --build-arg=VERSION=$(TAG_NAME) --build-arg=COMMIT_HASH=$(COMMIT_HASH) --build-arg=BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) -f Dockerfile .
# Docker image distroless
docker-distroless:
docker buildx build -t tinyauthapp/tinyauth:dev-distroless --build-arg=VERSION=$(TAG_NAME) --build-arg=COMMIT_HASH=$(COMMIT_HASH) --build-arg=BUILD_TIMESTAMP=$(BUILD_TIMESTAMP) -f Dockerfile.distroless .
+26
View File
@@ -0,0 +1,26 @@
package main
import (
"encoding/json"
"fmt"
"github.com/tinyauthapp/paerser/cli"
"github.com/tinyauthapp/tinyauth/internal/model"
)
func configCmd(tconfig *model.Config, loaders []cli.ResourceLoader) *cli.Command {
return &cli.Command{
Name: "config",
Description: "Print the configuration of Tinyauth",
Configuration: tconfig,
Resources: loaders,
Run: func(_ []string) error {
jsonBytes, err := json.MarshalIndent(tconfig, "", " ")
if err != nil {
return fmt.Errorf("failed to marshal configuration: %w", err)
}
fmt.Println(string(jsonBytes))
return nil
},
}
}
+8 -1
View File
@@ -13,7 +13,8 @@ import (
) )
func main() { func main() {
tConfig := model.NewDefaultConfiguration() env := model.DetectRuntimeEnv()
tConfig := model.NewDefaultConfiguration(env)
loaders := []cli.ResourceLoader{ loaders := []cli.ResourceLoader{
&loaders.FileLoader{}, &loaders.FileLoader{},
@@ -52,6 +53,12 @@ func main() {
log.Fatal().Err(err).Msg("Failed to add version command") log.Fatal().Err(err).Msg("Failed to add version command")
} }
err = cmdTinyauth.AddCommand(configCmd(tConfig, loaders))
if err != nil {
log.Fatal().Err(err).Msg("Failed to add config command")
}
err = cmdUser.AddCommand(verifyUserCmd()) err = cmdUser.AddCommand(verifyUserCmd())
if err != nil { if err != nil {
+1 -1
View File
@@ -20,7 +20,7 @@ type EnvEntry struct {
} }
func generateExampleEnv() { func generateExampleEnv() {
cfg := model.NewDefaultConfiguration() cfg := model.NewDefaultConfiguration(model.RuntimeEnvUnknown)
entries := make([]EnvEntry, 0) entries := make([]EnvEntry, 0)
root := reflect.TypeOf(cfg).Elem() root := reflect.TypeOf(cfg).Elem()
+1 -1
View File
@@ -21,7 +21,7 @@ type MarkdownEntry struct {
} }
func generateMarkdown() { func generateMarkdown() {
cfg := model.NewDefaultConfiguration() cfg := model.NewDefaultConfiguration(model.RuntimeEnvUnknown)
entries := make([]MarkdownEntry, 0) entries := make([]MarkdownEntry, 0)
root := reflect.TypeOf(cfg).Elem() root := reflect.TypeOf(cfg).Elem()
+48 -18
View File
@@ -1,8 +1,27 @@
package model package model
import "os"
type RuntimeEnv int
const (
RuntimeEnvUnknown RuntimeEnv = iota
RuntimeEnvDocker
)
func DetectRuntimeEnv() RuntimeEnv {
env := os.Getenv("RUNTIME_ENV")
switch env {
case "docker":
return RuntimeEnvDocker
default:
return RuntimeEnvUnknown
}
}
// Default configuration // Default configuration
func NewDefaultConfiguration() *Config { func NewDefaultConfiguration(runtimeEnv RuntimeEnv) *Config {
return &Config{ cfg := &Config{
Database: DatabaseConfig{ Database: DatabaseConfig{
Driver: "sqlite", Driver: "sqlite",
Path: "./tinyauth.db", Path: "./tinyauth.db",
@@ -67,25 +86,36 @@ func NewDefaultConfiguration() *Config {
}, },
LabelProvider: "auto", LabelProvider: "auto",
} }
// apply path overrides for docker runtime
if runtimeEnv == RuntimeEnvDocker {
cfg.Database.Path = "/data/tinyauth.db"
cfg.Resources.Path = "/data/resources"
cfg.OIDC.PrivateKeyPath = "/data/oidc/key.pem"
cfg.OIDC.PublicKeyPath = "/data/oidc/key.pub"
cfg.Tailscale.Dir = "/data/tailscale"
}
return cfg
} }
type Config struct { type Config struct {
AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"` AppURL string `description:"The base URL where the app is hosted." yaml:"appUrl"`
Database DatabaseConfig `description:"Database configuration." yaml:"database"` Database DatabaseConfig `description:"Database configuration." yaml:"database"`
Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"` Analytics AnalyticsConfig `description:"Analytics configuration." yaml:"analytics"`
Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"` Resources ResourcesConfig `description:"Resources configuration." yaml:"resources"`
Server ServerConfig `description:"Server configuration." yaml:"server"` Server ServerConfig `description:"Server configuration." yaml:"server"`
Auth AuthConfig `description:"Authentication configuration." yaml:"auth"` Auth AuthConfig `description:"Authentication configuration." yaml:"auth"`
Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"` Apps map[string]App `description:"Application ACLs configuration." yaml:"apps"`
OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"` OAuth OAuthConfig `description:"OAuth configuration." yaml:"oauth"`
OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"` OIDC OIDCConfig `description:"OIDC configuration." yaml:"oidc"`
UI UIConfig `description:"UI customization." yaml:"ui"` UI UIConfig `description:"UI customization." yaml:"ui"`
LDAP LDAPConfig `description:"LDAP configuration." yaml:"ldap"` LDAP LDAPConfig `description:"LDAP configuration." yaml:"ldap"`
Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"` // Experimental ExperimentalConfig `description:"Experimental features, use with caution." yaml:"experimental"`
LabelProvider string `description:"Label provider to use for ACLs (auto, docker, kubernetes or none to disable). auto detects the environment." yaml:"labelProvider"` LabelProvider string `description:"Label provider to use for ACLs (auto, docker, kubernetes or none to disable). auto detects the environment." yaml:"labelProvider"`
Log LogConfig `description:"Logging configuration." yaml:"log"` Log LogConfig `description:"Logging configuration." yaml:"log"`
Tailscale TailscaleConfig `description:"Tailscale configuration." yaml:"tailscale"` Tailscale TailscaleConfig `description:"Tailscale configuration." yaml:"tailscale"`
ConfigFile string `description:"Path to config file." yaml:"-"` ConfigFile string `description:"Path to config file." yaml:"-"`
} }
type DatabaseConfig struct { type DatabaseConfig struct {