Installing Custom Nodes from a Private NPM Registry in n8n Using pnpm Inside a Custom Docker Image
Introduction
Hey everyone,
At our company, we use n8n with a paid license and actively contribute to its development through PRs on the GitHub repo. However, we also have proprietary nodes that we publish on a private NPM registry and need to integrate them properly into our self-hosted n8n environment.
Since we’re deploying n8n using Docker Compose, we decided that the best approach would be to create a custom Docker image to version and manage these nodes efficiently.
What We Tried
After researching best practices in the n8n community, we found some relevant discussions and documentation:
- Installing Private Nodes in Docker
- How to Add New Nodes in a Production Setup
- Definitive Guide to Custom NPM Modules for Self-Hosted Instances
- Using External CLI Tools in n8n
Following these recommendations, we created a custom Dockerfile like this:
FROM docker.n8n.io/n8nio/n8n:latest@sha256:2c41c31d5becfd3466e2f15ae34ecc75024b8aac061abb44623c52e7a0fe3afb
COPY .npmrc ./
USER root
RUN pnpm install @mycompany/n8n-nodes-custom
USER node
After building and running the container, we verified that a package.json
file was generated inside the /home/node
directory, confirming that the package installation was successful.
However, despite this, n8n does not recognize the custom node, and it does not appear in the UI.
We also tried adding the following environment variable to docker-compose.yml
to ensure external dependencies are allowed:
environment:
- NODE_FUNCTION_ALLOW_EXTERNAL=*
The Problem
The issue is that n8n doesn’t seem to detect our custom node, even though it is installed inside the container. We suspect this is due to the way n8n loads nodes internally.
We cannot use the .n8n/custom
directory (which is the recommended approach for development) because this folder is mounted as a volume in our Docker Compose setup to persist stateful data.
What’s the Correct Way to Install Custom Nodes in Docker?
Given our setup, what is the proper way to install and register private custom nodes inside a Docker container so that n8n can detect them correctly?
Should we use a global flag when using the installation step in the Dockerfile ?
Or should we use a specific path that you recomment ?
Any insights or best practices would be greatly appreciated!
Debug Info
Core
- n8n Version: 1.81.4
- Platform: Docker (self-hosted)
- Node.js Version: 20.18.3
- Database: PostgreSQL
- Execution Mode: Scaling
- Concurrency: -1
- License: Community
- Consumer ID: Unknown
Storage
- Success: All
- Error: All
- Progress: False
- Manual: True
- Binary Mode: Memory
Pruning
- Enabled: True
- Max Age: 336 hours
- Max Count: 10,000 executions