Enforce environment variable configuration for Docker entrypoint
CI / Go Tests (push) Successful in 12s
CI / Build (push) Successful in 11s
Format / gofmt (push) Successful in 6s
Release Artifacts / Validate release tag (push) Successful in 2s
Release Artifacts / Build and release executables (push) Successful in 16s
Release Artifacts / Build and release Docker image (push) Successful in 26s

- Updated `docker-entrypoint.sh` to disallow custom command-line arguments, requiring configuration through `SCRATCHBOX_*` environment variables.
- Modified `README.md` to clarify that custom container commands are not supported and to reflect the new entrypoint behavior.
- Enhanced `main_test.go` to validate failure when required environment variables are not set.
- Added a function in `server.go` to print startup environment variables, ensuring visibility of configuration during server initialization.
This commit is contained in:
2026-06-01 05:06:57 -05:00
parent 0dc1df2ded
commit 4579443d09
5 changed files with 57 additions and 13 deletions
-1
View File
@@ -42,5 +42,4 @@ fmt:
clean:
rm -rf web/static
rm -rf $(CONFIG)
rm -rf $(BIN_DIR)
+1 -4
View File
@@ -51,14 +51,11 @@ Use the included Compose example:
Inside the container, the default command is:
- `scratchbox server --env`
- Custom container command/args are not supported; configure behavior via `SCRATCHBOX_*` env vars.
- The image forces `SCRATCHBOX_STORAGE_DATA_DIR=/data`.
- The image forces `SCRATCHBOX_SERVER_LISTEN_ADDR=:8080`.
- The image forces `SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH` to empty.
To run with a YAML config instead, pass `--config` explicitly (mutually exclusive with `--env`):
- `docker run --rm -p 8080:8080 -v "$(pwd)/docker-data:/data" -v "$(pwd)/docker-config:/config" scratchbox:dev server --config /config/config.yaml`
Storage encryption key behavior:
- The key file is always stored at `storage.data_dir/metadata.key` (next to `metadata`).
+26 -1
View File
@@ -139,9 +139,30 @@ func TestMainProcessEnvSuccess(t *testing.T) {
"SCRATCHBOX_STORAGE_DATA_DIR="+filepath.Join(tmp, "data"),
"SCRATCHBOX_SECURITY_ALLOWED_IPS=",
)
if out, err := cmd.CombinedOutput(); err != nil {
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("helper process failed: %v, output=%s", err, string(out))
}
if !strings.Contains(string(out), "[scratchbox] --env startup variables:") {
t.Fatalf("helper output missing env startup header, output=%q", string(out))
}
if !strings.Contains(string(out), "SCRATCHBOX_SERVER_LISTEN_ADDR=127.0.0.1:0") {
t.Fatalf("helper output missing expected env var, output=%q", string(out))
}
}
func TestMainProcessEnvWithoutScratchboxVarsFails(t *testing.T) {
t.Parallel()
cmd := exec.Command(os.Args[0], "-test.run=TestMainHelperProcess")
cmd.Dir = repoRoot(t)
cmd.Env = []string{
"GO_WANT_MAIN_HELPER=1",
"MAIN_HELPER_MODE=env-no-vars",
}
if err := cmd.Run(); err == nil {
t.Fatalf("expected helper process failure when --env has no SCRATCHBOX_* vars")
}
}
func TestServerConfigAndEnvMutuallyExclusive(t *testing.T) {
@@ -256,6 +277,10 @@ func TestMainHelperProcess(t *testing.T) {
os.Args = []string{"scratchbox", "server", "--env"}
main()
os.Exit(0)
case "env-no-vars":
os.Args = []string{"scratchbox", "server", "--env"}
main()
os.Exit(0)
case "storage-fail":
cfgPath := os.Getenv("MAIN_HELPER_CONFIG")
os.Args = []string{"scratchbox", "server", "--config", cfgPath}
+25
View File
@@ -9,6 +9,7 @@ import (
"os"
"os/signal"
"path/filepath"
"sort"
"strings"
"syscall"
"time"
@@ -45,6 +46,10 @@ func run(configPath string, useEnv bool) error {
err error
)
if useEnv {
envCount := printEnvStartup()
if envCount == 0 {
return errors.New("no SCRATCHBOX_* environment variables set for --env mode")
}
cfg, err = config.LoadFromEnv()
} else {
generated, err := ensureConfigFile(configPath)
@@ -123,6 +128,26 @@ func run(configPath string, useEnv bool) error {
return nil
}
func printEnvStartup() int {
entries := make([]string, 0)
for _, item := range os.Environ() {
if strings.HasPrefix(item, "SCRATCHBOX_") {
entries = append(entries, item)
}
}
sort.Strings(entries)
fmt.Fprintln(os.Stdout, "[scratchbox] --env startup variables:")
if len(entries) == 0 {
fmt.Fprintln(os.Stdout, "[scratchbox] (no SCRATCHBOX_* variables set)")
return 0
}
for _, item := range entries {
fmt.Fprintf(os.Stdout, "[scratchbox] %s\n", item)
}
return len(entries)
}
func ensureConfigFile(configPath string) (bool, error) {
path := strings.TrimSpace(configPath)
if path == "" {
+5 -7
View File
@@ -13,12 +13,10 @@ export SCRATCHBOX_SERVER_LISTEN_ADDR
SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH=
export SCRATCHBOX_SERVER_ACCESS_LOG_FILE_PATH
# Default to running the server from SCRATCHBOX_* env vars.
if [ "$#" -eq 0 ]; then
set -- server --env
elif [ "${1#-}" != "$1" ]; then
# Allow passing server flags directly, e.g. `docker run ... --env`.
set -- server --env "$@"
# Entrypoint is fixed for Docker deployments; custom args are not supported.
if [ "$#" -ne 0 ]; then
echo "custom entrypoint arguments are not supported; configure via SCRATCHBOX_* env vars" >&2
exit 2
fi
exec scratchbox "$@"
exec scratchbox server --env