Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nicosaporiti/buda-lightning-invoice/llms.txt

Use this file to discover all available pages before exploring further.

The project includes a multi-stage Dockerfile based on Node.js 20.18.0 slim, making it straightforward to run Buda Lightning Invoice in any environment that supports Docker — whether that is your local machine, a VPS, or a container orchestration platform. This is the same image that Fly.io builds when you run fly deploy, so the behaviour is identical across environments.

Dockerfile overview

The Dockerfile uses a two-stage build to keep the final image lean by separating the compilation environment from the runtime image.

base stage

ARG NODE_VERSION=20.18.0
FROM node:${NODE_VERSION}-slim AS base

LABEL fly_launch_runtime="Node.js"

WORKDIR /app
ENV NODE_ENV="production"
  • Starts from the official node:20.18.0-slim image, which omits unnecessary system packages.
  • Sets the working directory to /app.
  • Sets NODE_ENV=production permanently — this affects how Express and other packages behave and also controls some application-level logic.

build stage

FROM base AS build

RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3

COPY package-lock.json package.json ./
RUN npm ci

COPY . .
  • Extends base with native build tools (build-essential, node-gyp, pkg-config, python-is-python3) needed to compile any native Node.js addons.
  • Installs exact dependency versions from package-lock.json using npm ci — reproducible and audit-friendly.
  • Copies all application source files into the image.

Final stage

FROM base

COPY --from=build /app /app

EXPOSE 3000
CMD [ "npm", "run", "start" ]
  • Starts fresh from the lean base image (no build tools).
  • Copies the fully-built application from the build stage.
  • Exposes port 3000 in the image metadata (the actual listening port is controlled by the PORT environment variable, which defaults to 8080).
  • Starts the server with npm run start (node index.js).

Full Dockerfile

# syntax = docker/dockerfile:1

# Adjust NODE_VERSION as desired
ARG NODE_VERSION=20.18.0
FROM node:${NODE_VERSION}-slim AS base

LABEL fly_launch_runtime="Node.js"

# Node.js app lives here
WORKDIR /app

# Set production environment
ENV NODE_ENV="production"


# Throw-away build stage to reduce size of final image
FROM base AS build

# Install packages needed to build node modules
RUN apt-get update -qq && \
    apt-get install --no-install-recommends -y build-essential node-gyp pkg-config python-is-python3

# Install node modules
COPY package-lock.json package.json ./
RUN npm ci

# Copy application code
COPY . .


# Final stage for app image
FROM base

# Copy built application
COPY --from=build /app /app

# Start the server by default, this can be overwritten at runtime
EXPOSE 3000
CMD [ "npm", "run", "start" ]
NODE_ENV is set to production inside the Dockerfile. This value is baked into the image at build time and will be active at runtime even if you do not pass it as an environment variable. Some code paths in index.js behave differently in production mode (for example, test-mode server skips are disabled), so ensure your credentials and configuration are correct before running the container.

Build and run

1

Build the Docker image

From the repository root (where the Dockerfile lives), build the image and tag it:
docker build -t buda-lightning-invoice .
The build will pull the base image, install build tools, run npm ci, and produce a final slim image. This typically takes 1–3 minutes on first build; subsequent builds use the layer cache and are much faster.
2

Run the container with environment variables

Start the container in detached mode, passing your credentials and domain as environment variables:
docker run -d \
  -p 3001:8080 \
  -e BUDA_API_KEY=your_key \
  -e BUDA_API_SECRET=your_secret \
  -e DOMAIN=your-domain.com \
  --name buda-lightning \
  buda-lightning-invoice
This maps host port 3001 to container port 8080 (the default PORT). Adjust the host-side port (3001) to any free port on your machine.
3

Verify the container started

Check the container logs to confirm the server is listening:
docker logs buda-lightning
You should see output similar to:
Listening at port 8080
You can also confirm the container is running with:
docker ps --filter name=buda-lightning
4

Test the API

Send a test invoice creation request to the running container:
curl -X POST http://localhost:3001/newinvoice \
  -H 'Content-Type: application/json' \
  -d '{"amount": 1000, "msg": "test"}'
A successful response looks like:
{
  "invoice": "lnbc10...",
  "amount": 1000,
  "msg": "test"
}
If you receive a 400 error, double-check that BUDA_API_KEY and BUDA_API_SECRET are correct and that your Buda.com account has Lightning enabled.

Environment variable injection

Credentials must be provided at runtime — never baked into the image. There are two common approaches: Inline -e flags (shown above) — suitable for quick testing:
docker run -d \
  -p 3001:8080 \
  -e BUDA_API_KEY=your_key \
  -e BUDA_API_SECRET=your_secret \
  -e DOMAIN=your-domain.com \
  --name buda-lightning \
  buda-lightning-invoice
--env-file option — recommended for anything beyond a quick test, keeps secrets out of your shell history:
docker run -d \
  -p 3001:8080 \
  --env-file .env \
  --name buda-lightning \
  buda-lightning-invoice
Your .env file should follow the format from the README:
PORT=8080
BUDA_API_KEY=your_buda_api_key
BUDA_API_SECRET=your_buda_api_secret
DOMAIN=your-domain.com
The .dockerignore file excludes node_modules, .env, .dockerignore, Dockerfile, fly.toml, and .git from the build context. This means your local .env file is never copied into the image, even if you forget to add a COPY exclusion. Secrets must always be injected at docker run time.

Port mapping

The container listens on the port specified by the PORT environment variable. If PORT is not set, the application defaults to 8080. The -p <host_port>:<container_port> flag in docker run maps a port on your host machine to a port inside the container:
FlagHost portContainer portWhen to change
-p 3001:808030018080Change host side if 3001 is already in use
-p 80:8080808080Expose directly on standard HTTP for a reverse proxy
-p 8080:808080808080Avoid if host already uses port 8080
If you set a custom PORT via -e PORT=3000, update the container-side port in your -p mapping to match:
docker run -d \
  -p 3001:3000 \
  -e PORT=3000 \
  -e BUDA_API_KEY=your_key \
  -e BUDA_API_SECRET=your_secret \
  --name buda-lightning \
  buda-lightning-invoice
The EXPOSE 3000 directive in the Dockerfile is documentation only — it does not publish any port to the host. Port publishing is always controlled by the -p flag at docker run time.
To stop and remove the container when you are done, run docker stop buda-lightning && docker rm buda-lightning. To also remove the built image, run docker rmi buda-lightning-invoice.

Build docs developers (and LLMs) love