Issues Deploying Docker Images to Synology Container Manager

I upgraded my 2019 MacBook Pro Intel Core i7 to the newer 2024 MacBook Pro M4 Max. Before upgrading I was building Docker images in my Intel Mac and deploying a Next.js app and a .NET Core API without any issues to my Synology NAS. However, after getting the new Apple Silicon Mac, I started having Issues deploying the Next.js Docker Image to Synology Container Manager.

I naively built the Docker image on my new Apple Silicon Mac the same way as I did on my Intel Mac. Pushed the image to Docker Hub and when it came time to download the image from Synology Container Manager, I was getting the following notification:

Unable to download image docker.io/user/image.name. Go to Container Manager for more information.

Then looking at Synology Container Manager, logging showed the following entry:

Failed to pull image [no matching manifest for linux/amd64 in the manifest list entries].

I was really confused.

Building Docker Images for Multi-platform

I realized I was building the image on an ARM computer, whereas the Synology NAS is x64 (AMD64) architecture.

After some googling I reached the Docker Docs on building images for multi-platform deployment (https://docs.docker.com/build/building/multi-platform/). This basically lets you build images that are able to run on multiple hosts platforms; Linux, Windows and ARM powered devices.

The docker docs show the following command to build images to target multi-platform:

docker buildx build --platform linux/amd64,linux/arm64 .

By adding the --platform flag, we tell the Docker engine to build the image for Linux x64 and Linux ARM64.

However, I am using Docker Compose to build and manage the images. In this case, I needed to add the platforms: section under the build: section, like so

# Next.js app

services:
  app.fe:
    image: image/app.fe:latest
    container_name: container.fe
    build:
      context: .
      dockerfile: Dockerfile
      platforms: # To build an image for multi-platform
        - 'linux/amd64'
        - 'linux/arm64'
    ports:
      - '3050:3050'
    extra_hosts:
      - 'host.docker.internal:host-gateway'

# .NET Core API

services:
  api:
    image: image/api:latest
    container_name: container.api
    build:
      context: .
      dockerfile: src/Api/Dockerfile
      platforms: # To build an image for multi-platform
        - "linux/amd64"
        - "linux/arm64"
    environment:
      - ASPNETCORE_ENVIRONMENT=Release
      - ASPNETCORE_URLS=http://+:5068
      - ASPNETCORE_HTTP_PORTS=5068
      - DOTNET_GENERATE_ASPNET_CERTIFICATE=false
    ports:
      - "5068:5068"
      - "5069:5069"
    depends_on:
      - db        

My Second Mistake

My second mistake was with the Next.js app Docker image.

After adding the platforms section, Docker was getting stuck while building for the AMD64 platform. The ARM64 platform was finishing building correctly, however, since the AMD64 was getting stuck, the entire build was not completing.

In trying to follow those docs, there is a section detailing where you can pin the FROM instruction to the native platform of the builder, in my case to ARM64. You do so by adding the --platform=$BUILDPLATFORM option in the Dockerfile.

FROM --platform=$BUILDPLATFORM node:23.7.0-alpine AS base
...

After adding this new piece of instruction, Docker was able to build for both AMD64 and ARM64 platforms. The next step was to push the image to Docker Hub and from there, the Synology Container Manager was successfully downloading the image and creating the container. Big win!! Or so I thought.

However, the Next.js container was crashing right after starting with the following log message:

exec /usr/local/bin/docker-entrypoint.sh: exec format error

Back to the drawing board. Long story short, this error means the container is trying to run on the wrong host platform.

While inspecting the images in Docker Hub, I noticed the two OS architectures were correct. However, the image itself was still built for with ARM architecture.

Click image to get larger resolution

Now, about the .NET Core API. Just by adding the platform section to the Docker compose file, the image was able to build successfully. After pushing to Docker Hub, the Synology Container Manager was successfully downloading the image, creating the container and running it without any issue.

The difference between the .NET Core API and the Next.js images? Well, the .NET Core API successfully built for the correct platforms and architecture.

Click image to get larger resolution

Fixing it all

After much dabbling and reading with different ways of building the Next.js image, the answer lies with how Docker running on ARM machines builds the AMD images using emulation.

Click image to get larger resolution

Docker by default uses the Apple Virtualization Framework and Rosetta for x86_64/amd64 emulation. With this combination, the .NET Core API builds successfully. And that is the reason this image built correctly at first try.

However, attempting to build the Next.js image with this default combination, the build hangs. To fix it, all I had to do was uncheck Rosetta for x86_64/amd64 emulation, and voilĂ , the build finishes successfully.

The AMD build is a bit slow, ~2 min. In comparison with the ARM counterpart, which only takes ~20 sec.

And this is inspecting the Next.as app image in Docker Hub.

Click image to get larger resolution

The Synology Container Manager is now able to download the image, create the container and run it successfully!

And by the way, I removed the --platform=$BUILDPLATFORM from the Next.js Dockerfile and only instructing to build for multi-platform in the Docker Compose file.

Closing thoughts

This was quite the learning journey for me. I’m glad now I ran into the issue, but at the moment, I was getting really frustrated.

I hope you got to learn something from this writing!


If you liked this reading, share it on your social media and you can follow me on Twitter or LinkedIn.


Consider giving back by getting me a coffee (or a couple) by clicking the following button:

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.