Build a Local Automation Enviroment: Self-Hosted n8n + Node.js API with Docker Compose ๐Ÿณ
DEV Community

Build a Local Automation Enviroment: Self-Hosted n8n + Node.js API with Docker Compose ๐Ÿณ

When it comes to workflow automation, n8n is one of the most powerful open-source tools available. However, relying exclusively on third-party APIs or cloud instances can introduce latency, strict rate limits, and data privacy concerns.

The solution? A self-hosted, cloud-native architecture. In this tutorial, I will show you how to spin up a local development environment that orchestrates an n8n container and a custom Node.js REST API, communicating securely through an internal Docker bridge network.

The Architecture

Instead of exposing our database or API to the public internet for n8n to consume, we will encapsulate both services within a Docker bridge network.

This provides two main benefits:

  • Security: Services can communicate with each other internally, but you maintain full control over which ports are exposed to the host machine.
  • Portability: You can take this exact boilerplate and deploy it to a VPS (like Civo, DigitalOcean, or AWS) in seconds.

Step 1: Building the Node.js API

First, we need a backend service for n8n to interact with. We will use Express for its simplicity.

In the project root, create a subdirectory called API with an index.js file:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.use(express.json());

// Endpoint de prueba que n8n va a consumir
app.get('/API/data', (req, res) => {
  res.json({
    success: true,
    message: "Hi from your API!",
    data: {
      id: 1,
      status: "active",
      timestamp: new Date()
    }
  });
});

app.listen(PORT, () => {
  console.log('API de NODE.js running on port ${PORT}');
});

To containerize this, we add a lightweight Dockerfile based on the Node Alpine image:

# Usar una imagen oficial y ligera de Node.js
FROM node:18-alpine

# Crear y establecer el directorio de trabajo dentro del contenedor
WORKDIR /usrc/app

# Copiar los archivos de dependencias
COPY package*.json ./

# Copiar el resto de código de la API
COPY . .

# Exponer el puerto que une la API
EXPOSE 3000

# Comando para iniciar la aplicación
CMD ["node", "index.js"]

Step 2: The Docker Compose Magic

This is where everything comes together.

In the root of our project, we create our docker-compose.yml file. This acts as the blueprint for our infrastructure.

services:
  my-api-node:
    build: ./API
    container_name: api_nodejs
    ports:
      - "3000:3000"
    networks:
      - n8n-network
    restart: unless-stopped

  n8n:
    image: docker.n8n.io/n8nio/n8n
    container_name: n8n_autoalojado
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=localhost
      - N8N_PORT=5678
      - N8N_PROTOCOL=http
      - NODE_ENV=production
      - WEBHOOK_URL=http://localhost:5678/
      - GENERIC_TIMEZONE=America/Argentina/Buenos_Aires
    volumes:
      - n8n_data:/home/node/.n8n
    networks:
      - n8n-network
    restart: unless-stopped
    depends_on:
      - my-api-node

networks:
  n8n-network:
    driver: bridge

volumes:
  n8n_data:

Key takeaways from this configuration:

  • Shared Network: Both services are tied to n8n-network. Inside n8n, instead of calling localhost:3000, we can make HTTP requests directly to https://api_nodejs:3000. Docker handles the DNS resolution automatically.
  • Data Persistence: The n8n_data volume ensures that even if you tear down the container, your workflows remain safely stored on your local machine.

Step 3: Spin Up the Environment

With Docker running on your machine, open your terminal in the project root and execute:

docker compose up -d --build

The -d (detached) flag runs the services in the background, while the --build flag ensures our custom Node.js image is compiled with the latest changes.

That's it! Navigate to https://localhost:5678 to access your n8n dashboard. Navigate to https://localhost:3000/api/data to test your backend.

Conclusion

Setting up a local containerized environment saves you from dealing with cross-platform configuration issues, broken global dependencies, and Node.js version conflicts.

You can check out the complete source code for this boilerplate on my GitHub Repository: https://github.com/WhoIsMarce/proyecto-n8n-nodejs.git

Have you used n8n with local APIs before? Let me know in the comments what kind of automations you would build with this setup!

I'm Marcela Zapata Vanegas. Technical Writer & Full Stack Developer.

I am passionate about simplifying cloud architecture and automating workflows.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.