> ## Content Index
> Fetch the complete content index at: https://qilinora.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Docker Compose：让 n8n命令变成菜单。
- URL: https://qilinora.com/docker-compose-rang-n8nming-ling-bian-cheng-cai-dan/
- Published: 2026-08-24T01:03:55.000Z
- Updated: 2026-08-24T01:03:55.000Z
- Author: Liyaoming
- Tags: Docker, 部署, n8n

你有没有过这种经历？

第一次部署 n8n 时，照着教程在终端里敲了一大串命令。里面有端口、密码、挂载路径、网络、重启策略。最后它确实跑起来了。

过了两周，电脑重启。你想重新启动 n8n，却发现自己完全忘记当时写过什么。

你开始翻聊天记录、翻浏览器历史、翻收藏夹。终于找到那条命令，又不确定自己有没有改过端口、有没有挂过数据卷、密码是不是同一个。

这不是你记性不好。是因为“把一套应用的所有规则，塞进一条很长的命令”，本来就不适合长期使用。

Docker Compose 就是为了解决这件事。

> **它让你把 n8n、数据库、端口、数据、网络和启动规则，统一写进一份清单。以后启动不靠回忆，只需要一句命令。**

今天我们不追求一口气背完 YAML。我们只做一件事：**像给一栋小楼写物业清单那样，把 n8n 和它需要的数据库安排清楚。**

---

## 先看你最终会得到什么

完成后，你会拥有一个文件夹。里面最重要的是两份文件：

```
n8n-docker/
├── compose.yaml
└── .env

```

- `compose.yaml`：公开的物业清单，写着“有哪些房间、怎么连接、数据放哪”。
- `.env`：私密的小信封，写着密码和加密密钥。

以后你只要进入这个文件夹，运行：

```bash
docker compose up -d

```

n8n 和 PostgreSQL 数据库会一起启动。

它们各住一间房、各有自己的数据柜、通过内部电话线通信；浏览器只能打开 n8n，不能直接敲数据库的门。

这就是一个对小白来说很重要的“安全边界”：**你能用 n8n，但不需要把数据库暴露到外面。**

---

## Docker Compose 到底是什么？别把它想复杂

把 Docker Compose 想成一张写得很清楚的物业清单。

假设你要管理两间房：

1. 一间叫 n8n，负责自动化。
2. 一间叫 PostgreSQL，负责保存数据。

你需要告诉物业：

- 每间房用什么装修模板。
- 谁先开门，谁后开门。
- 哪间房可以对外接待。
- 哪些资料需要放进独立储物柜。
- 两间房如何在楼内打电话。

Docker Compose 就是把这些事写下来。Docker 官方对它的说明是：用一份 YAML 文件来定义、配置和运行多个容器服务。[Docker 官方指南](https://docs.docker.com/guides/docker-compose/?ref=qilinora.com)

你不需要把 YAML 当成编程语言。它更像“有严格缩进的清单”。只要层级对齐，它就能读懂你的安排。

---

## 第 1 步：创建一个专门的文件夹

先在电脑上找一个你方便管理的位置，例如桌面或文稿目录。

新建文件夹：

```
n8n-docker

```

接下来所有和 n8n 有关的文件都放在这里。不要今天把 Compose 文件放桌面，明天把密码放下载目录，后天又不知道数据卷从哪来的。

把这个文件夹想成“这栋 n8n 小楼的物业办公室”。

---

## 第 2 步：先做 `.env`，把敏感内容放进小信封

在 `n8n-docker` 文件夹中，新建一个文件，文件名必须是：

```
.env

```

注意两点：前面有英文句点；后面没有 `.txt`。

把下面内容复制进去：

```
POSTGRES_USER=n8n
POSTGRES_PASSWORD=请替换成一个你自己设置的强密码
POSTGRES_DB=n8n
N8N_ENCRYPTION_KEY=请替换成一长串随机字符并安全保存

```

每一行都不要急着跳过。

| 这一行                      | 它在生活中像什么     | 它实际决定什么                   |
| ------------------------ | ------------ | ------------------------- |
| POSTGRES\_USER=n8n       | 数据库房间的工作人员名字 | n8n 连接 PostgreSQL 时使用的账号。 |
| POSTGRES\_PASSWORD=...   | 数据库房间的门禁密码   | 防止其他人随意进入数据库。             |
| POSTGRES\_DB=n8n         | 这个资料室的名称     | PostgreSQL 启动时创建的数据库名。    |
| N8N\_ENCRYPTION\_KEY=... | 保险柜主钥匙       | n8n 用它保护凭据等敏感信息；以后不要随便换。  |

你现在只要知道一件事：**这个文件不应该公开。**

如果未来你把 `compose.yaml` 放到 GitHub，`.env` 不要一起上传。就像物业清单可以让合作伙伴看，主钥匙不能贴在门口。

---

## 第 3 步：复制这一份完整配置，不要先自己拼

在同一个 `n8n-docker` 文件夹中，新建：

```
compose.yaml

```

然后完整复制下面的内容：

```yaml
services:
  postgres:
    image: postgres:16
    container_name: n8n-postgres
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - automation-net
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 10

  n8n:
    image: n8nio/n8n:latest
    container_name: n8n
    restart: unless-stopped
    ports:
      - "127.0.0.1:5678:5678"
    environment:
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      DB_POSTGRESDB_PORT: 5432
      DB_POSTGRESDB_DATABASE: ${POSTGRES_DB}
      DB_POSTGRESDB_USER: ${POSTGRES_USER}
      DB_POSTGRESDB_PASSWORD: ${POSTGRES_PASSWORD}
      N8N_ENCRYPTION_KEY: ${N8N_ENCRYPTION_KEY}
      GENERIC_TIMEZONE: Asia/Shanghai
      TZ: Asia/Shanghai
    volumes:
      - n8n_data:/home/node/.n8n
    networks:
      - automation-net
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  n8n_data:
  postgres_data:

networks:
  automation-net:
    driver: bridge

```

现在先别被这么多行吓到。你不需要一次性理解全部。下面我会像带你参观楼层一样，一段一段讲。

---

## 第 4 步：先认识最外层的 `services`

配置开头是：

```yaml
services:

```

它的意思是：**这栋楼里有哪些正在营业的房间。**

在它下面，你看到了两个名字：

```yaml
postgres:
n8n:

```

一个是数据库房间，一个是自动化房间。

这里的名字很重要。以后 n8n 想找数据库，不是去找 `localhost`，而是直接拨打内部电话簿里的 `postgres`。

你可以理解成：

```
n8n 房间 —— 内部电话线 —— postgres 房间

```

---

## 第 5 步：先看 PostgreSQL 房间，它负责“记住”

这一段：

```yaml
postgres:
  image: postgres:16

```

意思很简单：请 Docker 用 PostgreSQL 16 的标准装修模板，建一间叫 `postgres` 的数据库房间。

### 它的密码从哪里来？

看这里：

```yaml
environment:
  POSTGRES_USER: ${POSTGRES_USER}
  POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
  POSTGRES_DB: ${POSTGRES_DB}

```

`${POSTGRES_PASSWORD}` 的意思不是把密码写在这里，而是：**请去同一个文件夹的 `.env` 小信封里，取出这个值。**

这样做的好处是，配置结构和真实密码分开。以后改密码，你只改 `.env`；以后分享配置给朋友，也不会不小心把真实密码一起发出去。

### 这行为什么不能少？

```yaml
volumes:
  - postgres_data:/var/lib/postgresql/data

```

数据库是最不应该“住临时房”的东西。

这行的意思是：把 `postgres_data` 这只储物柜，接到数据库真正保存资料的位置。这样你重建 PostgreSQL 容器时，数据库内容不会一起消失。

### `healthcheck` 又是什么？

你会看到：

```yaml
healthcheck:
  test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]

```

你可以把它理解成物业在开门前打一通测试电话：**数据库不只是房门开了，而是真的已经能接电话、能回答问题。**

为什么要做这个检查？因为容器“已经启动”不等于数据库“已经准备完成”。Docker 官方也特别说明，服务启动顺序和服务真正可用是两件事；需要健康检查才能更可靠地等待服务 ready。[Docker 官方说明](https://docs.docker.com/guides/docker-compose/?ref=qilinora.com)

---

## 第 6 步：再看 n8n 房间，它负责“干活”

这部分最常让新手困惑的是：

```yaml
DB_POSTGRESDB_HOST: postgres
DB_POSTGRESDB_PORT: 5432

```

为什么不是：

```yaml
DB_POSTGRESDB_HOST: localhost

```

因为你现在不是在电脑浏览器里访问数据库，而是让 **n8n 这个容器** 去找 PostgreSQL 容器。

在 n8n 房间里，`localhost` 的意思是“n8n 房间自己”。n8n 如果拨 `localhost:5432`，其实是在问自己：你这里有没有数据库？当然通常没有。

真正正确的方式，是拨内部电话簿：

```yaml
DB_POSTGRESDB_HOST: postgres

```

这里的 `postgres` 就是前面定义的服务名。它像房间名，也是内部网络里的联系电话。

`5432` 则是 PostgreSQL 房间内部的接待窗口号码。

> **记住：浏览器访问 n8n 时，看 `localhost:5678`；n8n 访问 PostgreSQL 时，看 `postgres:5432`。前者是从楼外进来，后者是楼内房间打电话。**

---

## 第 7 步：为什么只有 n8n 有 `ports`？

n8n 部分有：

```yaml
ports:
  - "127.0.0.1:5678:5678"

```

它的意思是：让这台电脑的浏览器可以通过 `http://localhost:5678` 打开 n8n 。

而 PostgreSQL 没有 `ports`。

这是故意的，不是漏写。

数据库不需要给浏览器直接打开，它只需要在楼内接 n8n 的电话即可。少开一扇对外的门，就少一份不必要的暴露。

左边的 `127.0.0.1` 表示先只允许本机访问。对于刚开始学习 Docker 的人，这是一个稳妥的起点。

---

## 第 8 步：`n8n_data` 和 `postgres_data`，为什么要两只储物柜？

配置底部有：

```yaml
volumes:
  n8n_data:
  postgres_data:

```

这表示两只独立储物柜。

| 储物柜            | 保存谁的资料            | 为什么分开更好                      |
| -------------- | ----------------- | ---------------------------- |
| n8n\_data      | n8n 自己的配置、工作流相关数据 | 方便独立维护、检查与迁移。                |
| postgres\_data | PostgreSQL 的数据库文件 | 数据库有自己的保存规则，不应该和 n8n 文件混在一起。 |

这就像办公室和财务室各有自己的上锁柜。分开不只是“看起来整洁”，而是为了以后备份、恢复和排查时更清楚。

---

## 第 9 步：启动前，先让 Docker 帮你检查配置

不要复制完就直接启动。先在 `n8n-docker` 文件夹中打开终端，运行：

```bash
docker compose config

```

它像物业在施工前把整份清单重新念一遍。

如果 YAML 缩进错了、变量没找到、冒号写漏了，这一步通常会直接告诉你。比起启动失败后盲猜，先做这一步能省很多时间。

没有明显错误后，再运行：

```bash
docker compose up -d

```

`-d` 的意思是让它在后台运行。你关掉终端，n8n 也不会因此停止。

接着运行：

```bash
docker compose ps

```

你想看到的不是一大串技术文字，而是两个服务都处于 `running` 或 `Up` 状态。

如果 PostgreSQL 还在 `starting`，给它几十秒准备时间。n8n 设定了等待健康检查，它会在数据库真正准备好之后再继续。

---

## 第 10 步：打开 n8n，完成第一次验证

浏览器打开：

```
http://localhost:5678

```

如果看到 n8n 初始化页面 ，说明：

- n8n 房间已经建好；
- 大楼外的 5678 门牌已经接通；
- 数据库房间已经准备好；
- n8n 已经拿到内部电话簿并能连接数据库。

请先创建管理员账号，再新建一个测试工作流。然后不要急着做复杂自动化，先让这一套结构稳定运行一天。真正能跑稳的基础，比一次性堆很多节点更重要。

---

## 如果你卡住了，先只看这 4 个问题

### 1\. `docker compose up -d` 直接报错

先运行：

```bash
docker compose config

```

最常见的问题是 YAML 缩进。YAML 对空格很敏感，请统一使用空格，不使用 Tab。

### 2\. n8n 不断重启

运行：

```bash
docker compose logs -f n8n

```

从最早一条 ERROR 开始读。很多问题是 `.env` 变量没填、数据库地址写错、或者密钥为空。

### 3\. n8n 显示数据库连接失败

先检查：

```bash
docker compose logs -f postgres

```

然后确认 n8n 配置里是否写了：

```yaml
DB_POSTGRESDB_HOST: postgres

```

不要写 `localhost`。

### 4\. 浏览器打不开 `localhost:5678`

运行：

```bash
docker compose ps

```

确认 n8n 服务是否真的在运行，以及端口是否显示为 `127.0.0.1:5678->5678/tcp`。如果显示端口被占用，改左边的 5678，例如改为 18080，再访问 `http://localhost:18080` 。

---

## 你现在不需要背住全部配置

你只需要真正记住四句话：

> `compose.yaml` 是整套应用的物业清单。`.env` 是放密码和密钥的小信封。`postgres` 是 n8n 在楼内拨打的数据库房间名。数据卷让你重建容器时，不会丢掉成果。

只要这四句话清楚，后面不管你增加 Redis、反向代理、备份工具还是其他应用，都是在这套结构上加新的房间和规则，而不是重新学习一门完全陌生的技术。

下一篇我们解决最后一个让人最焦虑的问题：当 Docker 提示端口冲突、数据库连不上、容器一直重启、数据好像没了时，到底应该先看哪里，才能不靠重装碰运气。