Docker n8n container permission errors in CI/CD but works on local machine

I’m running into a weird issue with my docker setup. I have a docker compose file that includes an n8n service for our test environment. Everything runs perfectly when I test it on my local machine, but when the same code runs in our CI pipeline, I get this permission error:

Error: EACCES: permission denied, open '/home/node/.n8n/config'

Here’s my docker compose configuration for the automation service:

  automation:
    image: docker.n8n.io/n8nio/n8n
    ports:
      - "5678:5678"
    environment:
      - N8N_HOST=automation:5678
      - N8N_PORT=5678
      - N8N_PROTOCOL=http
      - NODE_ENV=production
      - DB_TYPE=postgresdb
      - DB_TABLE_PREFIX=workflow_
      - DB_POSTGRESDB_DATABASE=workflows
    volumes:
      - ./docker/automation/data:/home/node/.n8n
      - ./docker/automation/files:/files

In my CI setup, I’m trying to fix the permissions like this:

sudo useradd -m node
mkdir -p docker/automation
sudo chmod -R 777 docker/automation
sudo chown -R node:node docker/automation
docker-compose up -d

I’ve tried different permission combinations and ownership settings but nothing seems to work. The container starts locally without any issues but fails in the CI environment. Has anyone encountered similar permission problems with containerized applications in CI pipelines?

Classic user ID mismatch between your local setup and CI runner. The n8n container runs as user node with specific UID/GID, but your CI environment has different user mappings than your local machine. Don’t bother creating a separate node user on the host - just run the container with explicit user mapping. Add this to your docker-compose service:

user: "1000:1000"

Or check what UID the container expects by running docker run --rm docker.n8n.io/n8nio/n8n id and make sure your CI creates the directory with matching ownership before starting the compose stack. I’ve hit the same issue with Jenkins pipelines where workspace ownership didn’t match what was expected. Bottom line: the mounted volume needs the exact same UID/GID that the containerized process expects, not just the username.

Been through this exact headache with several CI environments. Your local Docker daemon runs with your user privileges, but CI runners use a completely isolated user context. Don’t fight with host permissions - use a named volume instead of bind mounting a local directory. Change your volumes section to - n8n_data:/home/node/.n8n and add the volume definition at the bottom of your compose file. Docker handles the permission mapping internally and you skip the host filesystem entirely. If you absolutely need the bind mount for accessing files outside the container, the UID 1000 approach works, but named volumes are way cleaner for CI environments where you don’t need direct host access.

Same issue here with GitLab runners. Your CI probably runs as root or a different user than your local setup. Fix it by creating the volume directories first and setting the right ownership: mkdir -p docker/automation/data && chown 1000:1000 docker/automation/data. Also, chmod 777 is way overkill and won’t solve UID mismatches anyway.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.