Что такое Docker: минимально необходимые знания для новичков в n8n
Самое частое место, где застревает установка n8n — это не сам n8n, а Docker перед ним. Скопируешь пять строк команд по инструкции, container поднимется, в интерфейсе пару раз кликнешь — вроде работает, а на следующий день возвращаешься и обнаруживаешь, что все workflow пропали — причина лишь в том, что в этих пяти строках не хватает одного -v。
Эта статья рассказывает только о той части Docker, которая нужна для установки n8n: image, container, volume, port. Четыре слова. Что касается сетевых режимов, Compose, самостоятельной сборки image — об этом поговорим, когда действительно понадобится, заранее выученное всё равно забудется.
Предварительное условие всего одно: уметь вводить команды в терминале и знать, что такое «port». Если никогда не сталкивался с Docker — это совершенно не мешает.
- Почему n8n в итоге всегда ставят в Docker
- Четыре слова: image, container, volume, port
- Сначала установим Docker
- Запустить n8n — три шага
- Как понять, что установка прошла успешно
- В каком файле на самом деле лежат данные
- Шесть ошибок, которые реально встречаются
- Несколько моментов по безопасности, связанных с n8n
Почему n8n в итоге всегда ставят в Docker
Официальная страница установки предлагает несколько путей: глобальная установка через npm, прямой запуск через npx, Docker, десктопная версия. Первые два — самые лёгкие, одна npm install -g n8n команда и готово, проблема в том, что они намертво привязывают n8n к Node на твоей машине. n8n очень придирчив к версии Node, в документации указан диапазон от 20.19 до 24.x. В один прекрасный день ты ради другого проекта обновишь Node до 26 — и n8n вместе с ним откажется работать, причём сообщение об ошибке не обязательно будет понятным.
Docker подходит иначе: упаковывает n8n и нужные ему Node, системные библиотеки, данные часовых поясов в один пакет, и этот пакет одинаково работает на любой машине. Я специально заглянул в image 2.43.7: Node там 26.7.0, базовый image — Alpine. Всё это совершенно не зависит от того, Node 18 или 26 установлен у тебя на хосте.
Цена тоже понятна. У вас появляется дополнительный слой, который нужно обслуживать: image занимает место на диске (2.43.7 после распаковки — 1.8 GB), при проблемах нужно смотреть ещё один лог, а обновление превращается из «npm update» в «заменить image и перезапустить». Я считаю, что это того стоит — само обновление: поменять tag, удалить container, перезапустить, три минуты, и не нужно думать о версии Node.
Если вы собираетесь поиграться локально пару дней, я не рекомендую Docker, npm быстрее. Если планируете запускать долго или давать коллегам — сразу Docker, не идите окольными путями.
Четыре слова: image, container, volume, port
Image
Image — это готовый read-only пакет, собранный кем-то другим, внутри — полная файловая система, способная запустить n8n.n8nio/n8n — это имя,2.43.7 — это tag. Под одним именем висит куча tag'ов, один tag соответствует одной версии.
Tag пишется latest, что означает «последняя стабильная версия». В production я не рекомендую так писать: в какой-то день container перезапустится, заодно подтянет новый image, поведение изменится, и вы даже не будете знать, откуда искать причину. Пишите версию жёстко, а обновление делайте как отдельную задачу.

docker pull — это то, что вам нужно ввестиContainer
Image — мёртвый.docker run Процесс, который запускается после, и называется container. Container — это image плюс слой для записи, всё, что вы внутри меняете, пишется в этот слой. Удаляете container — этот слой исчезает вместе с ним. Эта фраза — источник всех последующих проблем.
卷
Поэтому данные n8n нельзя хранить внутри container. Volume — это каталог на хосте, которым управляет Docker и который монтируется в определённый путь container. Путь, который признаёт n8n, — это /home/node/.n8n, база данных, ключи шифрования и журналы событий находятся там.
Я посчитал: только что созданный owner-аккаунт, один раз запущенный workflow — .n8n каталог, 5.5 MB. Из них database.sqlite 1.5 MB, плюс есть один файл на 4 MB -wal . Вот и всё это, потеряешь — придётся начинать всё заново.
порт
-p 5678:5678, слева от двоеточия — порт хоста, справа — порт внутри container. n8n в container всегда слушает 5678 (если не изменишь N8N_PORT), хочешь снаружи другой номер — меняй только левую часть:-p 8080:5678。
записать как 127.0.0.1:5678:5678 тогда будет привязано только к локальной машине, снаружи не подключиться. При тестировании я всегда использую такую запись, чтобы не забыть закрыть.
Сначала установи Docker
На Ubuntu / Debian проще всего официальный скрипт:
curl -fsSL https://get.docker.com | sh
Он добавляет официальный репозиторий, устанавливает docker-ce, вместе с плагином compose. Если не нравится «отдавать вывод curl напрямую в sh» — честно иди через официальный репозиторий apt, шаги есть в документации Docker, просто длиннее.
После установки введи две команды для проверки версии:
docker --version
# Docker version 29.1.3, build 29.1.3-0ubuntu3~24.04.2
У меня на этой 232 стоит Ubuntu 24.04 + Docker 29.1.3. Ты можешь использовать 24, 25 — разницы в командах нет.
Docker по умолчанию требует root или sudo. Кто-то говорит, что если добавить пользователя в docker группу, то sudo не нужен — это верно, но равносильно выдаче этому пользователю прав root, причина в разделе о безопасности.
Запустить n8n — три шага
Шаг первый: создать volume
docker volume create n8n_data
# n8n_data
Если в выводе отображается имя volume, значит он создан. Этот шаг можно и не делать,docker run записать в -v n8n_data:/home/node/.n8n создастся автоматически — но если создать один раз заранее, вы убедитесь, что он действительно существует.
Шаг второй: запустить
docker run -d
--name n8n
-p 127.0.0.1:5678:5678
-e TZ=Asia/Shanghai
-e GENERIC_TIMEZONE=Asia/Shanghai
-e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true
-v n8n_data:/home/node/.n8n
n8nio/n8n:2.43.7
По сравнению с исходной командой из официальной документации я изменил два места.
Одно — добавил -d. В документации указано docker run -it --rm, запуск в foreground: как только терминал закрывается или нажимается Ctrl+C, n8n останавливается;--rm заодно удаляется и container. При отладке так очень удобно, но для долгосрочной работы не подходит — добавьте -d чтобы он оставался в фоне.
Другое — перед port добавил 127.0.0.1:. В документации написано -p 5678:5678, это равносильно привязке к 0.0.0.0: если у машины есть публичный IP, любой, кто просканирует 5678, увидит вашу страницу входа. На моей машине 232 порт 5678 занят, фактически используется -p 127.0.0.1:5681:5678, схема маппинга та же.
Нужно задать обе переменные часового пояса.TZ управляет системным временем контейнера,GENERIC_TIMEZONE управляет тем, как n8n считает время сам, Schedule Trigger ориентируется на вторую. Если задать только TZ, задачи по расписанию всё равно идут по UTC, и ваши «9 утра» превратятся в 17:00 по пекинскому времени. В логах при этом не останется ни одной ошибки.
Шаг третий: смотрим логи и ждём запуска
docker logs -f n8n
При первом запуске выполняется несколько десятков миграций базы данных,Starting migration ... 和 Finished migration ... чередуются — это нормально. Ждём появления этих двух строк:
Version: 2.43.7
Editor is now accessible via:
http://localhost:5678
Этот http://localhost:5678 — внутренний адрес контейнера, в браузере его не открыть. Открыть можно http://服务器IP:5678, или на локальной машине http://127.0.0.1:5678. Эта строка обманула многих, включая меня при первом запуске.
При запуске 2.43.7 также выдаёт пять предупреждений deprecation, о N8N_RUNNERS_MODE、N8N_UNVERIFIED_PACKAGES_ENABLED Эти значения по умолчанию позже нужно будет изменить. На использование не влияет, это задел на будущие версии. Кроме того, есть ещё одна строка Failed to start Python task runner in internal mode. because Python 3 is missing from this system.— в image не установлен Python, и если вы используете только Code node на JS, то можете вообще не обращать на это внимания.

После создания учётной записи вы войдёте внутрь. Если этот шаг не записать в volume, он не будет иметь смысла — ниже в разделе проверки будет рассказано, как убедиться, что он действительно сохранён на диск.
Как понять, что установка завершена
Четыре проверки, все выполняются в терминале.
docker psВ поле STATUS —Up, в PORTS есть mapping, IMAGE — тот tag, который вы указали.curl -s http://127.0.0.1:5678/healthzВозвращает{"status":"ok"}. Этот endpoint говорит только о том, что процесс жив.docker exec n8n n8n --version回2.43.7, совпадает с указанным вами tag.docker restart n8n, подождите с десяток секунд и снова откройте страницу — она больше не должна предлагать создать учётную запись.
Пункт 4 легче всего упустить, и он самый ценный. Он одновременно проверяет две вещи: volume смонтирован правильно, и данные действительно находятся вне container.

Когда я делал этот скриншот, я заодно заглянул в container и увидел .n8n, 5.5 MB, совпадает с тем, что сказано выше. Если у вас du -sh получается несколько сотен K, скорее всего данные записались в записываемый слой container, а volume не смонтирован.
В каком именно файле находятся данные
После создания volume фактическое расположение на хосте определяется Docker, проверяется этой командой:
docker volume inspect n8n_data
# [
# {
# "CreatedAt": "2026-11-02T09:28:41+08:00",
# "Driver": "local",
# "Mountpoint": "/var/lib/docker/volumes/n8n_data/_data",
# "Name": "n8n_data",
# "Scope": "local"
# }
# ]
«Mountpoint» — это его реальное расположение на хосте. На этой машине я перенёс корневой каталог данных Docker в /data/docker, поэтому видно /data/docker/volumes/n8n_data/_data; на машине с установкой по умолчанию будет указанный выше /var/lib/docker/.... Ориентируйтесь на вывод вашей машины.
Если зайти в container, выглядит так, как видит n8n:
docker exec n8n ls -la /home/node/.n8n
# -rw-r--r-- 1 node node 1519616 Nov 2 09:29 database.sqlite
# -rw-r--r-- 1 node node 32768 Nov 2 09:38 database.sqlite-shm
# -rw-r--r-- 1 node node 4136512 Nov 2 09:37 database.sqlite-wal
# -rw-r--r-- 1 node node 7972 Nov 2 09:37 n8nEventLog-1.log
# -rw-r--r-- 1 node node 526 Nov 2 09:38 n8nEventLog.log
Workflow, записи выполнений, зашифрованные credentials — всё в database.sqlite . Ключ шифрования для расшифровки credentials находится в том же каталоге, по умолчанию это config файл, автоматически генерируется при первом запуске.
Поэтому резервное копирование n8n — это две вещи: этот каталог и номер версии. Если забэкапить только sqlite без ключа, при восстановлении на другой машине credentials будут сплошной абракадаброй.
Если хотите сменить на свой указанный каталог хоста (например, /data/n8n), то -v n8n_data:/home/node/.n8n Заменить на -v /data/n8n:/home/node/.n8n и всё. Это и есть «bind mount»: каталогом управляете вы, резервное копирование нагляднее, но ценой того, что права придётся разруливать самому — следующий подводный камень именно в этом.
Шесть ошибок, которые реально встретятся
1. Забыли -v — удаление container равносильно удалению базы
Я сделал сравнение на двух container, одна и та же машина, один и тот же image: тот, что с -v n8n_data:/home/node/.n8n , после перезапуска возвращает через интерфейс на «показывать ли первоначальную настройку» — false; другой, без -v , тот же интерфейс возвращает true— он снова превратился в пустой экземпляр.
Весь процесс без ошибок, без предупреждений. Просто однажды открываете и обнаруживаете, что workflow пропали.
Как определить:docker inspect n8n, пролистайте вверх до "Mounts" того фрагмента, если в нём присутствует "Destination": "/home/node/.n8n" — значит, mount выполнен; если весь фрагмент пустой — это опасно.
2. Mount каталога хоста — ошибка EACCES
Хочу использовать bind mount, каталог создан — можно монтировать напрямую, итак:
Error: Failed to load command "start"
Error: EACCES: permission denied, open '/home/node/.n8n/config'
До этого журнал миграции выводился нормально, но внезапно всё зависло здесь. Потому что n8n в image работает не от root, а от пользователя с uid 1000 node(docker exec n8n id Можно увидеть uid=1000(node)), а у вас mkdir созданный каталог принадлежит root, 755, другие писать в него не могут.
Достаточно изменить владельца:
chown -R 1000:1000 /data/n8n
После изменения перезапустите — тот же каталог, та же команда, 200, всё нормально запустилось, и файлы действительно попали в каталог хоста. На хосте неважно, кто такой uid 1000, в container распознаётся именно 1000.
3. port занят
docker: Error response from daemon: failed to set up container networking:
driver failed programming external connectivity on endpoint n8n
(...): failed to bind host port 0.0.0.0:5678/tcp: address already in use
Это означает, что на хосте 5678 уже кем-то используется, к внутренней части container это не имеет никакого отношения. Сначала посмотрите, кто это:
ss -ltnp 'sport = :5678'
Частая ситуация — ваш прежний container n8n всё ещё работает,docker ps Можно увидеть. Или старый container удалён, но не полностью — проще всего сначала запустить на другом port.
4. Доступ по IP + http, после входа снова перебрасывает на страницу входа
Страница открывается, логин и пароль верные, при нажатии входа ошибки нет, затем страница возвращается к форме входа. Выглядит как неверный пароль, но на самом деле проблема в cookie.
Login cookie в n8n имеет Secure флаг (N8N_SECURE_COOKIE По умолчанию это true), браузер разрешает сохранять его только под HTTPS. При доступе по http сервер всё равно возвращает 200, браузер просто выбрасывает этот cookie, и следующий запрос снова без состояния входа.
Два пути: правильный способ — поставить спереди слой Nginx с сертификатом; для временной отладки во внутренней сети добавить -e N8N_SECURE_COOKIE=false, после отладки не забудьте удалить эту строку. Не рассматривайте это как долгосрочную конфигурацию — это равносильно тому, что ваш логин и пароль передаются по открытому каналу.
5. Закрыли терминал — n8n тоже остановился
Запускали по той команде из документации docker run -it --rm , Ctrl+C завершает. Это не фоновый сервис, а foreground-процесс в вашем терминале.
补 -d Перезапустить; если уже запущен,docker start n8n тоже может его вернуть, но тот container уже с --rm если удалён, остаётся только заново docker run— данные в volume, они на месте.
6. Использовали latest, и однажды поведение изменилось
Ни ошибок, ни предупреждений — просто после очередного перезапуска значения по умолчанию у узлов, интерфейс или даже имя какого-то параметра изменились. Причина в том, что вы подтянули новую версию.
Зафиксируйте номер версии и делайте обновление как серьёзную задачу: сначала backup volume, потом смените tag, после запуска прогоните два ключевых workflow и проверьте результат. В самом обновлении нет ничего сложного, вся морока в том, что «неизвестно, что изменилось».
Несколько моментов по безопасности, связанных с n8n
Не выставляйте 5678 напрямую в публичную сеть.У n8n есть страница входа, но это self-hosted приложение, за пределами входа нет дополнительной защиты, сканеры ежедневно ищут такие порты. Размещение на 0.0.0.0 без reverse proxy и без HTTPS равносильно тому, чтобы повесить ключи от дома у входа. В моём тестовом варианте -p 127.0.0.1:5678:5678 уже заблокирован доступ снаружи.
docker Группа равна root.Тот, кто может / смонтировать в container, может изменить любой файл на хосте. Подумайте об этом прежде чем выдавать коллегам права.
К volume относитесь как к секрету.Внутри того database.sqlite хранится зашифрованный текст всех учётных данных, в том же каталоге находится ключ для расшифровки. Кто скопирует оба этих элемента вместе, все токены ваших сторонних аккаунтов окажутся в открытом виде. Где хранить backup — важнее, чем сам backup.
Не пишите пароли в командной строке.docker run -e DB_PASSWORD=xxx Останется в docker inspect выводе, любой, кто выполнит, увидит. Для передачи чувствительных значений используйте env файл или _FILE набор переменных с суффиксом.
Краткое резюме
Достаточно запомнить четыре слова, чтобы всё заработало: image — это пакет, container — это запущенный пакет, volume — это участок снаружи пакета, port — это номер дома.
Единственное место, где установка n8n действительно может пойти не так: volume не смонтирован. Ошибки не будет, и вы не заметите сразу, а когда заметите — workflow уже пропал. Поэтому первое, что нужно сделать после установки — docker restart один раз, проверить, на месте ли данные.
Всё остальное — вопрос навыка. Когда освоитесь, поймёте, что главное преимущество Docker — не «кроссплатформенность», а «при проблеме можно всё удалить и начать заново» — данные в volume, container и так можно выбросить в любой момент.
Предыдущая статья —как проверить ошибки запуска n8n и занятость port, там речь о случаях, когда n8n не стартует. Оглавление всей серии —здесь, материалы по сбоям я отдельно собрал на странице故障排查.
Справочные материалы
- Install with Docker: официальные
docker runкоманды,docker volume create、/home/node/.n8nописание volume и шаги обновления image - Установка с помощью Docker Compose:конфигурация версии compose,
5678:5678В том комментарии написано «единственный порт, который должен быть открыт наружу» - Переменные окружения Deployment:
N8N_PORTпо умолчанию 5678、N8N_LISTEN_ADDRESSпо умолчанию::、N8N_USER_FOLDER与N8N_ENCRYPTION_KEY - Переменные окружения Security:
N8N_SECURE_COOKIEпо умолчаниюtrue、N8N_ENFORCE_SETTINGS_FILE_PERMISSIONSпо умолчаниюfalse - Docker volumes:тома хранятся на хосте
/var/lib/docker/volumes/<名字>/_data, а также его отличие от bind mount - Список тегов n8nio/n8n:один tag на каждую версию, можно узнать digest образа и сжатый размер
- Install Docker Engine on Ubuntu:полные шаги для официального репозитория apt, используйте этот путь, если не хотите применять однострочный скрипт
Последнее обновление: 2 ноября 2026 г., использовалась версия n8n 2.43.7.

