diff --git a/Makefile b/Makefile index 91213847e84..9eaef2f5805 100644 --- a/Makefile +++ b/Makefile @@ -213,6 +213,67 @@ docker-tools: @$(call print, "Building tools docker image.") docker build -q -t lnd-tools $(TOOLS_DIR) +# Short commit hash of the working tree, with a `-dirty` suffix if there are +# uncommitted changes. Unlike $(COMMIT), this never picks up submodule tags +# like `kvdb/v1.5.1` — `/` is not a valid character in a docker image tag. +# `--match='__no_such_tag__'` forces `git describe` to ignore all tags so +# `--always` falls back to the short hash. +DOCKER_DEV_COMMIT := $(shell git describe --always --dirty --match='__no_such_tag__') + +# Image (name:tag) produced by `docker-dev-build`. Also consumed by +# `docker-dev-lndinit-build` so the lndinit image is always layered on +# whatever `docker-dev-build` just built. Defaults to `lnd-dev:` +# (e.g. `lnd-dev:f5a093c1f` on commit f5a093c1f). +DOCKER_DEV_IMAGE ?= lnd-dev:$(DOCKER_DEV_COMMIT) + +# Repository name for the lndinit dev image; the tag is always +# `lnd-dev-$(DOCKER_DEV_COMMIT)` so it's obvious which docker-dev-build image +# the lndinit image was layered on. +LNDINIT_REPO ?= lndinit + +# Build context (path or git URL with optional #ref) for lndinit's dev.Dockerfile. +# NOTE: `#` is escaped as `\#` so make doesn't treat the ref as a comment. +LNDINIT_CONTEXT ?= https://github.com/lightninglabs/lndinit.git\#main + +# Full lndinit image name:tag, derived from LNDINIT_REPO and DOCKER_DEV_COMMIT. +LNDINIT_IMAGE := $(LNDINIT_REPO):lnd-dev-$(DOCKER_DEV_COMMIT) + +# dev.Dockerfile uses BuildKit cache mounts unconditionally, so these targets +# always go through `docker buildx build`. +#? docker-dev-build: Build a development docker image from dev.Dockerfile (override DOCKER_DEV_IMAGE=) +docker-dev-build: + @$(call print, "Building dev docker image $(DOCKER_DEV_IMAGE).") + docker buildx build -t $(DOCKER_DEV_IMAGE) -f dev.Dockerfile . + +#? docker-dev-lndinit-build: Build an lndinit dev image layered on the docker-dev-build image (override LNDINIT_REPO=, LNDINIT_CONTEXT=) +docker-dev-lndinit-build: docker-dev-build + @$(call print, "Building lndinit docker image $(LNDINIT_IMAGE) on top of $(DOCKER_DEV_IMAGE).") + IMG='$(DOCKER_DEV_IMAGE)'; \ + TAG="$${IMG##*:}"; \ + case "$$IMG" in \ + *:*) case "$$TAG" in */*) HAS_TAG=no ;; *) HAS_TAG=yes ;; esac ;; \ + *) HAS_TAG=no ;; \ + esac; \ + if [ "$$HAS_TAG" != yes ]; then \ + echo "DOCKER_DEV_IMAGE=$$IMG has no tag; set DOCKER_DEV_IMAGE=:" >&2; \ + exit 1; \ + fi; \ + CTX='$(LNDINIT_CONTEXT)'; \ + if [ -d "$$CTX" ]; then \ + DOCKERFILE="$$CTX/dev.Dockerfile"; \ + else \ + DOCKERFILE=dev.Dockerfile; \ + fi; \ + docker buildx build \ + --build-arg BASE_IMAGE="$${IMG%:*}" \ + --build-arg BASE_IMAGE_VERSION="$$TAG" \ + -t $(LNDINIT_IMAGE) -f "$$DOCKERFILE" "$$CTX" + +#? docker-dev-lndinit-build-push: Build the lndinit dev image (via docker-dev-lndinit-build) and push $(LNDINIT_IMAGE). `docker login` to that registry must already be done. +docker-dev-lndinit-build-push: docker-dev-lndinit-build + @$(call print, "Pushing lndinit docker image $(LNDINIT_IMAGE).") + docker push $(LNDINIT_IMAGE) + scratch: build @@ -551,4 +612,7 @@ clean-docker-volumes: android \ mobile \ clean \ - clean-docker-volumes + clean-docker-volumes \ + docker-dev-build \ + docker-dev-lndinit-build \ + docker-dev-lndinit-build-push diff --git a/docs/DOCKER.md b/docs/DOCKER.md index eb1fbd1cbbd..13d79e6d531 100644 --- a/docs/DOCKER.md +++ b/docs/DOCKER.md @@ -10,11 +10,45 @@ There are two flavors of Dockerfiles available: ## Development/testing -To build a standalone development image from the local source directory, use the -following command: +To build a standalone development image from the local source directory: ```shell -$ docker build --tag=myrepository/lnd-dev -f dev.Dockerfile . +$ make docker-dev-build +``` + +The image is tagged `lnd-dev:` by default (with a `-dirty` +suffix if the working tree has uncommitted changes); override with +`make docker-dev-build DOCKER_DEV_IMAGE=myrepository/lnd-dev:mytag`. + +To additionally build an `lndinit` image layered on top of the dev image +(pulling `lndinit`'s `dev.Dockerfile` from upstream main): + +```shell +$ make docker-dev-lndinit-build +``` + +The image is tagged `:lnd-dev-` (e.g. +`lndinit:lnd-dev-f5a093c1f`) so the tag makes it obvious which +`docker-dev-build` image it was layered on. `LNDINIT_REPO` defaults to +`lndinit`; override to push to a registry, e.g. `myrepository/lndinit`. +`LNDINIT_CONTEXT` is the build context that `docker buildx` pulls +`lndinit`'s `dev.Dockerfile` from — defaults to +`https://github.com/lightninglabs/lndinit.git#main`, but can be a local path +(e.g. `../lndinit`) or any other git URL with an optional `#` suffix +(branch, tag, or commit SHA). For example, to build lndinit from a local +checkout under the `myrepository/lndinit` repo name: + +```shell +$ make docker-dev-lndinit-build \ + LNDINIT_REPO=myrepository/lndinit \ + LNDINIT_CONTEXT=../lndinit +``` + +To build the `lndinit` image and push it to a registry you're already logged +into in one step: + +```shell +$ make docker-dev-lndinit-build-push ``` There is also a `docker-compose` setup available for development or testing that diff --git a/docs/release-notes/release-notes-0.22.0.md b/docs/release-notes/release-notes-0.22.0.md index 2f7f0ca1b7e..5a348eb2b78 100644 --- a/docs/release-notes/release-notes-0.22.0.md +++ b/docs/release-notes/release-notes-0.22.0.md @@ -111,6 +111,19 @@ the build context is a remote git repository because COPY layers are more smartly compared to cache. +* [New `make` targets for `dev.Dockerfile`](https://github.com/lightningnetwork/lnd/pull/10912): + `docker-dev-build` builds a development image from `dev.Dockerfile` + (tagged `lnd-dev:` by default; override with + `DOCKER_DEV_IMAGE=`). `docker-dev-lndinit-build` layers an + [`lndinit`](https://github.com/lightninglabs/lndinit) image on top of it + (using `lndinit`'s upstream `dev.Dockerfile`; tagged + `:lnd-dev-` so the tag reflects the underlying + dev image — override the repo name with `LNDINIT_REPO=` and the build + context with `LNDINIT_CONTEXT=`). `docker-dev-lndinit-build-push` builds + and then pushes the lndinit image. All three go through + `docker buildx build` so BuildKit cache mounts are used. See + [`docs/DOCKER.md`](../DOCKER.md) for examples. + # Contributors (Alphabetical Order) * bitromortac