n8ndockerffmpeg

n8n's Distroless Image Broke Your FFmpeg Dockerfile: Two Fixes

·Javid Jamae·9 min read
n8n's Distroless Image Broke Your FFmpeg Dockerfile: Two Fixes

You added USER root and RUN apk add --no-cache ffmpeg on top of the official n8n image, exactly like every tutorial says, and the build died on apk: not found. Your Dockerfile isn't wrong. The base image underneath it changed, and every install-ffmpeg-in-n8n answer written before June 2026 is now stale.

Quick answer: The official docker.n8n.io/n8nio/n8n image is distroless, so it ships with no apk and no apt, and USER root; RUN apk add --no-cache ffmpeg fails outright. The two working n8n distroless ffmpeg fixes are a multi-stage Dockerfile that transplants a package manager (or a static FFmpeg binary) into the distroless base, which you re-verify on every n8n release, or leaving the stock image untouched and sending the encode to a video API over HTTP, which is what FFmpeg Micro does in one call with no binary in your container at all.

Why apk add stopped working inside the n8n image

Conventional wisdom says installing FFmpeg in self-hosted n8n is a three-line Dockerfile: extend the official image, switch to root, install the package. That was true for years, and it's what threads 101937, 183559, 204259, and the 261143 feature request asking n8n to just bundle FFmpeg all describe. It stopped being true when the base image lost its package manager.

Distroless images contain the application and its runtime and nothing else. No apk, no apt, usually no shell, no busybox, no coreutils. There's nothing for RUN apk add to call, so the build fails before it ever reaches a package index. On community.n8n.io thread 298633, filed June 8, 2026, the accepted answer is blunt about it: if you want to use FFmpeg on a distroless image, you need to build your own custom image for that.

Two related constraints matter before you pick a fix. n8n Cloud never let you swap the image, so a custom Dockerfile is a self-host-only answer. And the Execute Command node is disabled by default in n8n v2.0 and later because arbitrary shell execution is a security problem on shared instances, so even a perfectly built image may need that node explicitly re-enabled before a workflow can call ffmpeg at all.

Fix 1: build a custom n8n Docker image with FFmpeg

Building your own image is the only way to run the FFmpeg binary inside the n8n container, and it works. The question is how you get a binary into a base that has no installer.

The apk transplant

The approach from thread 298633 copies Alpine's package manager into the distroless base, then uses it:

FROM alpine:3.21 AS pkg

FROM docker.n8n.io/n8nio/n8n:1.108.0
USER root
COPY --from=pkg /sbin/apk /sbin/apk
COPY --from=pkg /lib/libapk.so.* /lib/
COPY --from=pkg /etc/apk /etc/apk
COPY --from=pkg /bin/busybox /bin/busybox
RUN ["/bin/busybox", "sh", "-c", "ln -sf /bin/busybox /bin/sh && apk add --no-cache ffmpeg && rm -rf /var/cache/apk/*"]
USER node

The busybox copy and the exec-form RUN are there for a reason: shell-form RUN needs /bin/sh, and a distroless base doesn't have one. That's the error most people hit second, right after apk: not found.

The static binary version

If all you need is the ffmpeg executable, skip the package manager entirely and copy a statically linked build. Nothing to link against means nothing to break when n8n changes its base:

FROM alpine:3.21 AS build
RUN apk add --no-cache curl xz \
 && curl -sL https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz \
    | tar -xJ --strip-components=1 -C /tmp

FROM docker.n8n.io/n8nio/n8n:1.108.0
USER root
COPY --from=build /tmp/ffmpeg /usr/local/bin/ffmpeg
COPY --from=build /tmp/ffprobe /usr/local/bin/ffprobe
USER node

That's one binary around 80 MB, no shell required in the final stage, and no apk state left behind. Pin the n8n tag rather than using latest, or your image silently rebuilds on a base you never tested.

What the custom image actually costs

n8n ships minor releases roughly weekly, and each one is a new base image you have to rebuild and re-test, because the transplant depends on internal paths that n8n never promised to keep. Expect the image to grow by roughly 100 MB with the Alpine FFmpeg package and its dependencies. You're also adding a root-owned layer to a base whose whole point was removing attack surface, and you're on the hook for FFmpeg CVE patching yourself.

The part that surprises people: none of this fixes memory. A container with FFmpeg still pulls the video through n8n's binary data buffer, and a 1 GB file will take the instance down whether or not the encoder is present. That failure has its own architecture, covered in how to fix n8n running out of memory on large video files.

Fix 2: keep the stock image and move the encode off-box

The other fix is to stop trying to put an encoder in the automation container. Run the official distroless image exactly as published, and make the video step an HTTP Request node that hands a URL to a service that already has FFmpeg installed, tuned, and scaled.

Here's the same job both ways. Downscaling a clip to 1080p on your own box:

ffmpeg -i input.mp4 -vf "scale=-2:1080" \
  -c:v libx264 -crf 23 -preset veryfast \
  -c:a aac -b:a 128k -movflags +faststart output.mp4

The API version is one node: POST the source URL and the operation to FFmpeg Micro, take the webhook when the job finishes, and pass the output URL to your upload node. No binary in your container, no root layer, no rebuild when n8n releases, and the bytes never enter n8n's memory. There's a free tier to start, and the request shapes for each job type are in the docs. Passing URLs instead of file data is the same pattern that fixes Google Drive video automation in n8n.

The trade is real: you're adding a network dependency and a per-job cost you didn't have before. What you get back is a stock image that upgrades cleanly.

Which fix fits your setup

Pick on how much Docker maintenance you're willing to own, not on which is technically purer. Self-hosters with a dedicated ops person and lots of small files do fine with a custom image. Everyone else pays the rebuild tax forever.

Custom distroless imageOff-box HTTP call
Works on n8n CloudNoYes
Rebuild on n8n releaseEvery release, roughly weeklyNever
Image size added~80-100 MB0
Large-file memory riskUnchangedRemoved, bytes bypass n8n
Per-job costYour serverUsage-based, free tier
Who patches FFmpeg CVEsYouThe service

Common pitfalls

Most failed builds here fall into a handful of shapes, and the error text points at the wrong thing in almost all of them.

  • apk: not found means the base has no package manager, not a broken PATH. Adding USER root doesn't create one.
  • /bin/sh: no such file or directory means shell-form RUN can't execute. Use exec-form RUN ["/bin/busybox", "sh", "-c", "..."] or do the work in a builder stage.
  • Building FROM docker.n8n.io/n8nio/n8n:latest makes every rebuild a coin flip. Pin the exact version tag and bump it deliberately.
  • Forgetting USER node at the end leaves n8n running as root, which is worse than the problem you started with.
  • The workflow still says ffmpeg: not found after a successful build, because the Execute Command node is disabled by default in n8n v2.0+ and needs N8N_ENABLE_COMMUNITY_COMMAND_EXECUTION style opt-in on your instance.
  • An apk-based build that worked last month fails today. That's the transplant breaking on a new base, and it's the maintenance cost, not a bug you can fix once.

When building the image is the right call

A custom image genuinely wins when your files are small, your volume is high, and your data can't leave the box. Batch-probing a few thousand short clips with ffprobe over a local volume is faster and cheaper in-container than any network round trip, and a compliance rule that forbids sending media to third parties settles the question on its own.

Running a self-hosted media container alongside n8n is the middle path, and it's a real option, though the operating cost is higher than the "free" label suggests. We wrote about that trade in the NCA Toolkit is free, self-hosting it isn't cheap.

FAQ

Why does apk add ffmpeg fail in the n8n Docker image?

apk add ffmpeg fails because the official n8n image is distroless and contains no package manager. The apk binary, its libapk shared library, and the /etc/apk repository config were all removed from the base, so there's nothing to execute.

Can I install FFmpeg on n8n Cloud?

You can't install FFmpeg on n8n Cloud, because Cloud runs n8n's managed image and gives you no way to supply a Dockerfile. Cloud users have to call an external video API over the HTTP Request node.

Does n8n plan to ship FFmpeg in the official image?

n8n has not bundled FFmpeg, and community.n8n.io thread 261143 asked for exactly that. The distroless move points the other way, toward a smaller base rather than a larger one, so treat the request as unlikely to land.

Will a custom image with FFmpeg fix my out-of-memory crashes?

A custom image with FFmpeg won't fix out-of-memory crashes. The encoder's presence has nothing to do with n8n loading the whole file into binary data, which is what actually kills the instance on large videos. Keep the file out of n8n by passing URLs between steps.

How big does the n8n image get with FFmpeg installed?

Installing FFmpeg through Alpine's package adds roughly 100 MB to the n8n image once dependencies are pulled in, and a single static FFmpeg binary is about 80 MB on its own.

If you'd rather ship the stock n8n image and keep your video step to a single HTTP node, sign up free and point one workflow at the API before your next n8n upgrade breaks the Dockerfile again. The first job takes about as long as reading this took.

About Javid Jamae

Founder & CEO at FFmpeg Micro

Javid is a software engineer, author, and entrepreneur with over 25 years of professional software development experience across enterprise, startup, and consulting environments. He founded FFmpeg Micro to make video processing accessible to developers through a simple, automation-first REST API.

Software EngineeringVideo ProcessingFFmpegCloud ArchitectureAPI DesignAutomation

Ready to process videos at scale?

Start using FFmpeg Micro's simple API today. No infrastructure required.

Get Started Free