Install

Build from source

Build the single binary with the admin console from source, and why the build flags are what they are.

Prerequisites

ToolVersionUsed for
GoThe version in the go directive of go.mod, or newerCompiling the server
Node.js22Building the admin console front end
pnpmThe packageManager field of web/package.json; after corepack enable that version is used automaticallyFront-end dependencies and build
Task3Build entry point; task --list lists every task
GitAnyGetting the source; the Go toolchain derives the version from Git when building

That is all you need to build. Tools for contributing (linters and so on) are listed in the repository's CONTRIBUTING.en.md.

Build and run

Terminal
git clone https://github.com/x-haose/imgyoung.git
cd imgyoung
task build
./imgyoung

task build first builds the front end (pnpm install --frozen-lockfile and pnpm build in web/, output in web/dist), then compiles imgyoung into the repository root. task run builds and then runs it.

Open http://localhost:8721/ and sign in with admin / imgyoung123. Data goes to data/ under the current directory, just like with a release archive, and supervising and upgrading work the same way.

The version shown by ./imgyoung -version is derived from Git by the Go toolchain: the tag when the checkout sits on one, a pseudo-version otherwise, with a dirty marker when the working tree has uncommitted changes. The build time is written in only by the release pipeline and the Dockerfile; binaries from task build leave it empty.

Build flags

The Taskfile sets two environment variables at the top level, and build tasks such as task build and task run run under them (only the race detector in task test turns cgo on, on Linux / Windows):

Taskfile.yml (excerpt)
env:
  CGO_ENABLED: '0'
  GOFLAGS: -tags=nodynamic

Without Task, the equivalent manual steps are:

Terminal
(cd web && pnpm install --frozen-lockfile && pnpm build)
CGO_ENABLED=0 go build -trimpath -tags nodynamic -o imgyoung ./cmd/imgyoung
  • CGO_ENABLED=0: pure Go throughout. The SQLite driver and image codecs are pure Go or WASM, so no C toolchain is needed; Linux binaries do not depend on libc, cross-compile directly (e.g. with GOOS=linux GOARCH=arm64), and run in minimal images without libc such as distroless/static.
  • -tags nodynamic: by default the WebP codec library tries to load the system's libwebp shared library at runtime, which makes the Linux binary depend on the system's dynamic linker, so it cannot even start in minimal images such as distroless/static. With this tag it uses only its bundled WASM implementation; the result is a truly static binary whose behavior does not depend on whether the host has libwebp installed.
  • -trimpath: strips local source paths from the binary.

The release pipeline (.goreleaser.yaml) and the image build (Dockerfile) use the same flags.

Build the front end first

The admin console's front end is compiled into the binary with go:embed, but the build output is not committed; web/dist in the repository holds only a placeholder file. If you skip the front end and run go build directly, compilation still succeeds and the API works, but there is no console: / returns 404, and the startup log contains a warning:

level=WARN msg="前端产物缺少 index.html,后台页面不可用(API 不受影响)"

(The message says the front-end build is missing index.html, so the console is unavailable while the API is unaffected.) When you see it, run task web (or the two pnpm steps above) and compile again. This is also why ImgYoung does not offer go install as an installation method.

Building an image with Docker

If you have Docker but neither Go nor Node.js, build with the multi-stage Dockerfile in the repository root; both the front end and the Go binary are compiled inside build containers:

Terminal
task docker

It is equivalent to the command below and produces the local image imgyoung:dev:

Terminal
docker build \
  --build-arg VERSION=$(git describe --tags --always --dirty) \
  --build-arg COMMIT=$(git rev-parse HEAD) \
  -t imgyoung:dev .

The build context excludes .git, so the version and commit can only come in through --build-arg; without them the version shows as devel. The image is used exactly like the released one; see Docker image.

On this page