# How to Install n8n on Docker

- Tool: n8n
- Difficulty: Intermediate
- Time required: 10-20 minutes
- Compatibility: Docker 20+, Docker Compose v2+, all platforms (Linux, macOS, Windows)
- Last updated: March 2026

## TL;DR

Install n8n on Docker with a single docker run command for quick testing, or use Docker Compose for production with persistent data, environment variables, and automatic restarts. Mount a volume for the .n8n directory to persist workflows and credentials across container restarts. Set N8N_ENCRYPTION_KEY to protect stored credentials.

## Running n8n with Docker

Docker is the recommended way to run n8n in production. It provides a consistent environment, easy updates, and simple deployment. You can start with a single docker run command for testing, then move to Docker Compose when you need persistent data, environment variables, and integration with other services like PostgreSQL and Redis. This tutorial covers both approaches, from quick start to production-ready configuration.

## Before you start

- Docker installed on your system (Docker Desktop for macOS/Windows, or Docker Engine for Linux)
- Docker Compose v2 (included with Docker Desktop, or install separately on Linux)
- Basic familiarity with the command line
- Port 5678 available on the host machine

## Step-by-step guide

### 1. Run n8n with a quick-start Docker command

The fastest way to try n8n is a single docker run command. This pulls the official n8n image and starts the container with port 5678 exposed. The --rm flag removes the container when you stop it, and -it enables interactive mode so you can see the logs. This setup is for testing only — data is lost when the container stops.

```
docker run -it --rm \
  --name n8n \
  -p 5678:5678 \
  docker.n8n.io/n8nio/n8n
```

**Expected result:** n8n starts and the editor is accessible at http://localhost:5678 in your browser.

### 2. Add a persistent volume for data storage

To keep your workflows, credentials, and execution data across container restarts, mount a Docker volume to /home/node/.n8n inside the container. This directory contains n8n's SQLite database, encryption keys, and configuration. Use a named volume for Docker-managed storage, or a bind mount for a specific directory on the host.

```
docker run -d \
  --name n8n \
  --restart always \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  docker.n8n.io/n8nio/n8n
```

**Expected result:** n8n starts in the background with persistent storage. Workflows and credentials survive container restarts.

### 3. Set essential environment variables

Configure n8n with environment variables using the -e flag. At minimum, set N8N_ENCRYPTION_KEY to a random 32-character hex string. This key encrypts stored credentials. Without it, n8n generates a random key on first start, but if the key is lost (e.g., the container is recreated without the volume), credentials become unreadable. Also set WEBHOOK_URL if n8n is behind a reverse proxy.

```
# Generate an encryption key
openssl rand -hex 32

# Run n8n with environment variables
docker run -d \
  --name n8n \
  --restart always \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e N8N_ENCRYPTION_KEY=your_generated_key_here \
  -e WEBHOOK_URL=https://n8n.yourdomain.com \
  -e GENERIC_TIMEZONE=America/New_York \
  -e TZ=America/New_York \
  docker.n8n.io/n8nio/n8n
```

**Expected result:** n8n starts with a fixed encryption key and correct timezone. Credentials are encrypted and recoverable.

### 4. Create a Docker Compose file for production

For production deployments, use a docker-compose.yml file to define your n8n service along with any dependencies. Docker Compose makes it easy to manage environment variables, volumes, networking, and multi-service setups. Create a docker-compose.yml file in your project directory with the n8n service definition.

```
version: '3.8'

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    ports:
      - '5678:5678'
    environment:
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      - WEBHOOK_URL=${WEBHOOK_URL:-http://localhost:5678}
      - GENERIC_TIMEZONE=${TIMEZONE:-UTC}
      - TZ=${TIMEZONE:-UTC}
      - N8N_PORT=5678
    volumes:
      - n8n_data:/home/node/.n8n

volumes:
  n8n_data:
```

**Expected result:** Running docker compose up -d starts n8n with all configuration defined in the Compose file.

### 5. Start n8n with Docker Compose

Navigate to the directory containing your docker-compose.yml file. Create a .env file with your secrets. Then run docker compose up -d to start n8n in the background. Use docker compose logs -f n8n to follow the logs and verify n8n starts successfully.

```
# Create .env file
echo 'N8N_ENCRYPTION_KEY=your_generated_key_here' > .env
echo 'WEBHOOK_URL=https://n8n.yourdomain.com' >> .env
echo 'TIMEZONE=America/New_York' >> .env

# Start n8n
docker compose up -d

# Check logs
docker compose logs -f n8n
```

**Expected result:** n8n starts in the background. The logs show 'n8n ready on port 5678' and the editor is accessible.

### 6. Update n8n to the latest version

To update n8n, pull the latest image and recreate the container. Docker Compose makes this simple with two commands. Your data is preserved in the named volume. Always back up your data before updating, especially across major version changes.

```
# With Docker Compose
docker compose pull
docker compose up -d

# With plain Docker
docker stop n8n
docker rm n8n
docker pull docker.n8n.io/n8nio/n8n
docker run -d --name n8n --restart always \
  -p 5678:5678 \
  -v n8n_data:/home/node/.n8n \
  -e N8N_ENCRYPTION_KEY=your_key \
  docker.n8n.io/n8nio/n8n
```

**Expected result:** n8n restarts with the latest version. Existing workflows and credentials are preserved.

## Complete code example

File: `docker-compose.yml`

```yaml
version: '3.8'

# Production-ready n8n Docker Compose configuration
# Usage:
#   1. Create a .env file with N8N_ENCRYPTION_KEY and WEBHOOK_URL
#   2. Run: docker compose up -d
#   3. Access: http://localhost:5678

services:
  n8n:
    image: docker.n8n.io/n8nio/n8n
    restart: always
    ports:
      - '5678:5678'
    environment:
      # Required: encryption key for stored credentials
      - N8N_ENCRYPTION_KEY=${N8N_ENCRYPTION_KEY}
      # Required if behind reverse proxy
      - WEBHOOK_URL=${WEBHOOK_URL:-http://localhost:5678}
      # Timezone
      - GENERIC_TIMEZONE=${TIMEZONE:-UTC}
      - TZ=${TIMEZONE:-UTC}
      # Port (default 5678)
      - N8N_PORT=5678
      # Execution data pruning
      - EXECUTIONS_DATA_PRUNE=true
      - EXECUTIONS_DATA_MAX_AGE=168
      # Disable telemetry (optional)
      # - N8N_DIAGNOSTICS_ENABLED=false
    volumes:
      - n8n_data:/home/node/.n8n
    healthcheck:
      test: ['CMD-SHELL', 'wget -qO- http://localhost:5678/healthz || exit 1']
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s

volumes:
  n8n_data:
```

## Common mistakes

- **Running n8n without a persistent volume, losing all data on container restart** — undefined Fix: Always mount a volume to /home/node/.n8n: -v n8n_data:/home/node/.n8n
- **Not setting N8N_ENCRYPTION_KEY, then losing credentials when the container is recreated** — undefined Fix: Generate a key with openssl rand -hex 32 and pass it as an environment variable on every run.
- **Using the latest tag in production, causing unexpected breaking changes after docker pull** — undefined Fix: Pin to a specific version tag like docker.n8n.io/n8nio/n8n:1.30.0.
- **Exposing port 5678 to the public internet without authentication** — undefined Fix: Put n8n behind a reverse proxy (Nginx, Caddy, Traefik) with HTTPS and set up n8n's built-in basic authentication.

## Best practices

- Always set N8N_ENCRYPTION_KEY explicitly and store it securely — losing it makes credentials unrecoverable
- Use named Docker volumes instead of bind mounts for cleaner management
- Set --restart always so n8n recovers from host reboots automatically
- Pin to a specific image tag in production (e.g., n8n:1.30.0) to avoid unexpected breaking changes
- Use a .env file for secrets instead of hardcoding them in docker-compose.yml
- Set EXECUTIONS_DATA_PRUNE=true and EXECUTIONS_DATA_MAX_AGE=168 to prevent disk space issues
- Add a health check so Docker can detect and restart unhealthy containers
- Back up the n8n_data volume before major version updates

## Frequently asked questions

### What is the official Docker image for n8n?

The official image is docker.n8n.io/n8nio/n8n. Pull it with docker pull docker.n8n.io/n8nio/n8n. Do not use unofficial images from Docker Hub.

### Can I run n8n on Docker Desktop for macOS or Windows?

Yes. Docker Desktop works on macOS and Windows. The same docker run and docker compose commands work on all platforms.

### How do I access the n8n editor after starting the container?

Open http://localhost:5678 in your browser. If you changed the port with N8N_PORT or -p, use that port instead.

### How much memory does n8n need in Docker?

n8n works with 256 MB minimum for light workloads. For production with multiple concurrent workflows, allocate 1-2 GB. Monitor memory usage with docker stats.

### Can I run multiple n8n containers on the same host?

Yes. Use different ports (-p 5679:5678) and different volume names for each instance. For scaling, consider queue mode instead of running independent instances.

### Can RapidDev help deploy n8n on Docker in production?

Yes. RapidDev can set up a production n8n deployment on Docker with PostgreSQL, Redis, reverse proxy, SSL, monitoring, and automated backups.

---

Source: https://www.rapidevelopers.com/n8n-tutorial/how-to-install-n8n-on-docker
© RapidDev — https://www.rapidevelopers.com/n8n-tutorial/how-to-install-n8n-on-docker
