Docker built containers won't work on Mikrotik

I am attempting to run a small container on a RB5009UG+S+ running ROS 7.16.2 (have also tried on ROS 7.17rc3). When I add the container:

/container add file=usb2/myimage.tar root-dir=usb2/myimage interface=veth3

I get these results in the log:

importing tar archived image: myimage.tar
error getting layer file
failed to load next entry
import finished but no image found

I can successfully pull remote images from Docker hub and run them on RB5009 with results as expected, so I’m fairly confident I have the device (and veth’s and bridges, etc.) set up correctly. I can successfully build and run my Docker container on my desktop. But the image won’t extract or load properly on the RB5009 from a .tar that I supply.

My Dockerfile (below) is very simple and I don’t suspect the binary I’m using is the culprit as it’s very small. I’ve even tried a “blank” alpine image (a little trickier because the container needs something to run) and I always get the same extraction error on loading.

FROM arm64v8/alpine:latest
COPY mybinary /mybinary

EXPOSE 1234/tcp

CMD ["/mybinary", "-v"]

I’m using this command to build:

docker buildx build --no-cache --platform linux/arm64 -t myimage .

And then I export with this command:

docker save myimage > myimage.tar

Any suggestions? Does anyone else have success building arm64 images on a Windows machine with Docker desktop and then running on a Mikrotik device?

Why not try first some examples from the doc.
And maybe you missed the –output options to output docker image.

https://help.mikrotik.com/docs/spaces/ROS/pages/84901929/Container#Container-c)buildanimageonPC

Thanks, I’ve been using the docs to get started. I updated my build command to:

docker buildx build --no-cache --platform linux/arm64 --output=type=docker -t myimage .

But the results are the same, error getting layer file and no image found as soon as it’s added. Every remote image I pull from docker hub runs fine on my Mikrotik. Every local image I build myself runs fine locally on Windows (emulating arm64 just fine).

Just stumped getting a local build to run on the RB5009. :frowning:

Comparing what you’ve done to my successful Makefile, I see a few possible explanations:


  • Use of “buildx” instead of “build”. The distinctions are collapsing as BuildKit becomes the default, but in this instance you don’t need any of the advanced features of the old BuildKit, in particular multi-platform builds.
  • Single-step build-and-save. Try doing without the --output flag, building into the local image cache and then doing a separate “docker image save” step.
  • OCI vs legacy Docker tarball format. They don’t document the format of “docker image save”, but I would have guessed “oci” these days, not “docker” as you have it. A single-step build-and-save might work if you switch to type=oci.

I haven’t tried breaking my build to find out which of these actually matters. I leave that as an exercise for the student. :face_with_tongue: Please do report back once you discover the culprit, for our mutual enlightenment.

Failing all this, passing the tarball through Skopeo per my “limitations” guide might fix your tarball. I’ve seen this succeed more than once.

(And a complete reading of the guide should prove enlightening, if tangential to this thread’s purpose.)

Thanks for weighing in tangent. I tried a few variations as below, starting with building and exporting all at once as a .tar:

docker buildx build --no-cache --platform linux/arm64 --output=type=tar,dest=myimage.tar -t myimage .

This produces a .tar file with a flat directory structure: \bin, \dev, \etc, \home. I didn’t expect this would work as there was no place any additional metadata could be stored such as the command to run on launch. As expected, when I tried the /container add command, it immediately shot back with “failure: could not import”. The log also showed “error: could not find image manifest in archive”

Next I tried building and exporting as type=oci:

docker buildx build --no-cache --platform linux/arm64 --output=type=oci,dest=myimage.tar -t myimage .

This produces a .tar file containing just oci-layout, index.json, and a blobs folder. The results were the same as above with the exact same errors. Lack of a manifest in the root of the .tar is immediately catastrophic.

Last I tried building and exporting as type=docker:

docker buildx build --no-cache --platform linux/arm64 --output=type=docker,dest=myimage.tar -t myimage .

This produces a .tar file containing oci-layout, index.json, manifest.json, and a blobs folder. This seems to get a little closer, but the failures are the same as I reported in my first post: log lines indicating there’s an error getting the layer file and no image to be found. Doesn’t seem to have gotten me any closer yet.

That leaves you with two further options, then: the separate build+save method, optionally coupled with a Skopeo pass.

Now that I’ve had time to think about it, the second option is feeling more likely to result in success.

There’s a third option: push to Docker Hub, then have ROS pull the image remotely. container.npk is designed around this path, which is why everyone else’s builds work while your local-only ones don’t.

The skopeo tip seems to have worked. I had to get into WSL and install it (apk add skopeo) first. It produces a .tar file approximately double in size that is structured in a much more complicated manner inside, but when the archive file gets transferred to Mikrotik, it does import and works!

I have some more testing to do to make sure I have a repeatable process and that I understand all the moving pieces. Many thanks for the pointer, I would never have been able to figure out that by default Docker produces images incompatible with Mikrotik containers.

I have been through this issue before. The problem might be with how the image is saved or extracted on the RB5009. Try using docker save myimage -o myimage.tar instead of docker save myimage > myimage.tar. Also, make sure the USB drive is correctly mounted and has enough space. You can check by running disk print in RouterOS. Another thing to try is loading the image manually by extracting it on your desktop first, then copying the layers to the RB5009. Let me know if this helps.

hi mbrad,

can you help me with doing this?

I want to run container on my mik ROS 7.17.2 with alpine:latest.

I have saved it as normal .tar but mik says no image found. im not that clued up on how you did yours with "skopeo"

I haven't tested this in a while, but you may need to create a builder first.

TAG=myimage
BUILDX_PLATFORMS=linux/arm64
BUILDX_BUILDER_NAME=routeros-platforms-builder
docker buildx create --platform=$BUILDX_PLATFORMS --name $BUILDX_BUILDER_NAME 
docker buildx build --builder $BUILDX_BUILDER_NAME  --platform=$BUILDX_PLATFORMS --output "type=oci,dest=$TAG.tar" --tag $TAG .

I have a more complete example of this in my netinstall container project. See netinstall/examples/builder at master · tikoci/netinstall · GitHub

Works with the old builder as well, you just have to specify the platform:

docker build --platform linux/arm64 --tag $TAG .
docker save $TAG > $TAG.tar

Not sure how to build it properly from another platfrom, I have just installed Docker on a raspberry and built container there.

And that's why you need to use docker buildx - not plain "build" - if you want to cross-compile for another platform.

Hi all,

I already have a working pihole (v5) container on a RB5009, just wanted to update it to v6 so tryied the old working procedure.

First of all I encoutered the all new SSL certificate issue, I read a lot about it, tried importing the certificates without success.

So decided to use another method that worked in the past, just downloaded the docker image into my pc and then copied into the usb disk and when adding the container Ihave the same errors: “error getting layer file” and “failed to load next entry”

What I did:

  1. docker pull pihole/pihole --platform linux/arm64
  2. docker save pihole/pihole -o pihole_2025.11.1_6.3_FTL-6.4.1_Web-6.4_arm64.tar --platform linux/arm64

then from the terminal:

/container add comment=Pi-Hole file=usb2/images/pihole_2025.11.1_6.3_FTL-6.4.1_Web-6.4_arm64.tar interface=veth1 envlist=pihole_envs2 mounts=pihole_etc2,pihole_dnsmasq2 root-dir=usb2/containers/pihole hostname="Pi-Hole-Mikrotik" logging=yes start-on-boot=yes

any ideas?

thank you

different directory structures

for RoS 7.20 and below, use docker-ce 28,
for example, for Debian, it will look like this

apt install docker-ce=5:28.5.2-1~debian.12~bookworm

for RoS 7.21 and above, you can use the current stable version docker-ce(29.1.2),

apt install docker-ce

Hi, didn’t understand if you were answering to me, but just in case. I’m using docker on windows, the last version available. My RB5009 is on 7.20.2

About “different directory structures”, are you talking about docker or pihole?

If I understand correctly using a previous version of docker could fix the issue? or just have to update the router to 7.21+ (which, for my understanding is in testing)?

I think you should try to use docker buildx, as discussed, since that has reliably built images for me. While plain docker build has had mixed results across various versions over the years.

I’m not particularly skilled with docker (just able to do 2 or 3 things). After pulling a (I suppose already) built image I could build it again?

Why just create container from ROS using remote image? If it was issue with SSL as stated above, I guess then check certificate was enabled when adding container and ROS built-in certificates was not trusted.

Assuming in ROS is set Docker registry for containers (https://registry-1.docker.io), there is no need to import any certificate for fetching images (unless requests are intercepted by some transparent MITM proxy which intercepts HTTPS and replaces SSL certificate), unset Check Certificate when creating container (if GUI is used) or add check-certificate=no param to add command (if CLI is used); or better just trust built-in ROS certificates with command /certificate/settings/set builtin-trust-anchors=trusted (ROS 7.20.x, on ROS 7.21 this command is slightly changed) and there will be no issues with SSL cert. validation.

Yes, I answered both of you. This error is due to different build approaches in different Docker versions.
Sorry, I haven't dealt with the Windows version, WSL, so I can't tell you what to do.

But for Debian, for example, you'll have the following:

If you're using RoS 7.20 or earlier, then according to the instructions at https://docs.docker.com/engine/install/debian/, you should install them as follows:
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

but you need to use Docker-CE version 28 or earlier, so before installing, we'll look at a list of all available Docker-CE packages and install only the necessary ones:
apt-cache madison docker-ce
apt install docker-ce=5:28.5.2-1~debian.12~bookworm

after that, you can install the remaining necessary packages:
apt install docker-ce-cli=5:28.5.2-1~debian.12~bookworm
apt install containerd.io docker-compose-plugin

and only after that can you build Docker, and it will work on RoS 7.20 and below,

docker buildx build\
--no-cache\
--progress=plain \
--platform linux/amd64 \
--output=type=docker \
--tag docker-test:latest . &&
docker save docker-test:latest > docker-test-amd64.tar

If we want to build for arm64, then
docker run --privileged --rm tonistiigi/binfmt --install all
apt-get update && apt-get install -y qemu-user-static
docker buildx create --name mybuilder --driver docker-container --platform linux/amd64,linux/arm64,linux/arm/v7
docker buildx use mybuilder
docker buildx inspect --bootstrap
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
docker buildx ls

and after that, you can build, for example, for

docker buildx build
--no-cache
--progress=plain
--platform linux/arm64
--output=type=docker
--tag docker-test:latest . &&
docker save docker-test:latest > docker-test-arm64.tar

Sorry if I missed a detailed description of the steps and what they're for; frankly, I'm too lazy. For that, you can consult with deepseek, grok, etc. :slight_smile:

And in general, I think Mikrotik should clarify that they updated the container system in 7.21beta.

I think (and red something about that) something changed on the certificates management side, because I added my container a lot of time ago (kinda 18months) and had no issues, both adding a remote image or a downloaded one.

I’ll try your solution of the check-certificate=no or to trust built-in ROS certificates, because I already had https://registry-1.docker.io in the config and only now gives that error. I also give a chance to https://lscr.io, https://hub.docker.com and https://registry.hub.docker.com and still ask for their certificates (which I imported with no success).