puter icon indicating copy to clipboard operation
puter copied to clipboard

Missing linux/arm64 docker build

Open PalRist opened this issue 1 year ago • 12 comments

Issue Description Docker log: exec /usr/local/bin/docker-entrypoint.sh: no such file or directory

Steps to Reproduce Portainer running this stack:


version: "3.8" services: puter: image: ghcr.io/heyputer/puter:latest container_name: puter build: ./ ports: - 4100:4100 restart: unless-stopped

Tooling

  • Portainer running on raspbian, RPi5

PalRist avatar Apr 02 '24 13:04 PalRist

Try:

version: "3.8"
services:
  puter:
    container_name: puter
    image: ghcr.io/heyputer/puter:latest
    pull_policy: always
    # build: ./
    restart: unless-stopped
    ports:
      - '4100:4100'
    environment:
      # TZ: Europe/Paris
      # CONFIG_PATH: /etc/puter
      PUID: 1000
      PGID: 1000
    volumes:
      - ./puter/config:/etc/puter
      - ./puter/data:/var/puter
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://puter.localhost:4100/test || exit 1
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 30s

zarevskaya avatar Apr 02 '24 13:04 zarevskaya

Thanks for the proposal! However, i still get the same message (after purging any remains from my last attempt): exec /usr/local/bin/docker-entrypoint.sh: no such file or directory

PalRist avatar Apr 02 '24 17:04 PalRist

I have never used portainer before - does it have specific requirements of the image contents to successfully load? (i.e. do we need to provide a docker-entrypoint.sh file to be compatible with portainer?) - I ask because this filename is not familiar to me. The entrypoint for our docker container is npm start.

Also, very cool that you're trying this on a Raspberry Pi! I'm curious to find out how this goes.

KernelDeimos avatar Apr 02 '24 22:04 KernelDeimos

@KernelDeimos i am not sure how to check, but perhaps you know; Is the image built for ARM64 devices?

PalRist avatar Apr 03 '24 11:04 PalRist

@KernelDeimos i am not sure how to check, but perhaps you know; Is the image built for ARM64 devices?

No, The official image does not get built for arm64. I would suggest adding

platforms: linux/amd64,linux/arm64

to the build logic in GitHub action

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          context: .
		  platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

or you can build it youself (you can do this in portainer by cloning puter repo so that Dockerfile and src files are in the context) and use this docker-compose.yml version

version: "3.8"
services:
  puter:
    container_name: puter
    pull_policy: always
    build: ./
    restart: unless-stopped
    ports:
      - '4100:4100'
    environment:
      # TZ: Europe/Paris
      # CONFIG_PATH: /etc/puter
      PUID: 1000
      PGID: 1000
    volumes:
      - ./puter/config:/etc/puter
      - ./puter/data:/var/puter
    healthcheck:
      test: wget --no-verbose --tries=1 --spider http://puter.localhost:4100/test || exit 1
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 30s

MohamedElashri avatar Apr 03 '24 16:04 MohamedElashri

I just updated the file with several platforms added - I don't know which ones will work, but I also don't know what the rationale is of the software blocking people from attempting to run this on specific platforms based on a non-optional includes list. This seems like a violation of separation of concerns to me; we depend on node, so Puter will run on whatever platforms node runs on; it's weird that I have to care what platforms node runs on (in this specific context).

KernelDeimos avatar Apr 04 '24 17:04 KernelDeimos

I just updated the file with several platforms added - I don't know which ones will work, but I also don't know what the rationale is of the software blocking people from attempting to run this on specific platforms based on a non-optional includes list. This seems like a violation of separation of concerns to me; we depend on node, so Puter will run on whatever platforms node runs on; it's weird that I have to care what platforms node runs on (in this specific context).

There is a problem with this action. It seems that docker/build-push-action@v5 don't add buildx by default. This is why we get this error

ERROR: Multi-platform build is not supported for the docker driver.
Switch to a different driver, or turn on the containerd image store, and try again.
Learn more at https://docs.docker.com/go/build-multi-platform/
Error: buildx failed with: Learn more at https://docs.docker.com/go/build-multi-platform/

So we will need to add that before using this action. Sorry my suggestion was incomplete. This should be the reference

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

This should be before that. One example could be

name: Docker Image CI

on:
  push:
    branches: ['main']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Log in to GitHub Package Container registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Set up QEMU 
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v2

      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=schedule
            type=ref,event=branch
            type=ref,event=pr
            type=semver,pattern={{version}}
            type=semver,pattern={{major}}.{{minor}}
            type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }}
            type=sha
            type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }}

      - name: Build and push Docker image
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/386,linux/arm64,linux/arm/v7,linux/arm/v6,linux/ppc64le,linux/s390x
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

Regarding all these platforms. I'm not sure if all of them will work but definitely if you want to build for all of these you will need QEMU to emulate the instructions needed for the build

      - name: Set up QEMU 
        uses: docker/setup-qemu-action@v3

Which I added in the example above. Would you give it a try ?

And actually the problem is not with node version or anything. The problem is how the docker image are built and how docker engine interpret and convert code to instruction on each CPU arch is different.

MohamedElashri avatar Apr 04 '24 18:04 MohamedElashri

Thanks @MohamedElashri . Have you tested these changes? If you have can you submit a PR to update the action? It should be possible because it was originally added from this PR by @shuguet (who I'm also tagging here so they're aware of this issue)

KernelDeimos avatar Apr 04 '24 20:04 KernelDeimos

Thanks @MohamedElashri . Have you tested these changes? If you have can you submit a PR to update the action? It should be possible because it was originally added from this PR by @shuguet (who I'm also tagging here so they're aware of this issue)

I did test building the image on an arm machine but did not test the GitHub action because it will need to be run on GitHub runners. Also, the current Action does not get triggered on PR which is fine because you combine CI test of building the docker image from publishing on GitHub registry (And it is tag by SHA hashes not project tags which will need to be addressed)

Anyway, let's move with this PR #227 and see how can we address these problems.

MohamedElashri avatar Apr 04 '24 21:04 MohamedElashri

The choice of removing the PR as a trigger event for the action was a deliberate one, as you can see in the config of the metadata extraction, it would actually be able to handle it (it would create images like puter:pr-XYZ).

The reason I removed it from the PR I proposed initially is that Puter is a very busy repo and as such all those builds and images would eat up in the GHAction budget and packages/images space limits. But if that's not a concern, go for it! From a security standpoint though, make sure you disable automatic builds on PR made from external repos. Too easy to keep pushing new commits in a branch refered in a PR, and keep eating away at resources because those would trigger builds too.

Also, you can test the action by simply forking it and running it from your own fork (that's how I built it/tested it for my PRs originally).

Last point regarding the multi-platform: That wasn't a requirement for me, so again, in order to save on resources, test & build time, I simply removed it. And to @KernelDeimos 's question about why there's a need to build multiple images: That's because node is bundled into the image itself. And even if your code is pure JS, and only needs Node, Node itself is built for a specific OS+CPU Architecture, so essentially you need an image per target OS+CPUArch. You could start with the basic ones (amd64, arm v6 & v7 should take care of most people either on regular desktops, Apple M{1-3} devices and Raspberry Pi and clones. Someone might be running something more exotic like a MIPS or an (Open)RISC, but you can always test/add those as they get requested to cut down on build time & potential costs (depending on what type of GitHub subscription the organization has).

Hope that helps!

shuguet avatar Apr 04 '24 21:04 shuguet

The choice of removing the PR as a trigger event for the action was a deliberate one, as you can see in the config of the metadata extraction, it would actually be able to handle it (it would create images like puter:pr-XYZ).

I understand that, It would be better to handle the images in versioned way (not a priority though).

Last point regarding the multi-platform: That wasn't a requirement for me, so again, in order to save on resources, test & build time, I simply removed it.

I always assume that public repositories have no limit on actions total time, but puter lives inside HeyPuter organization which has limited free resources and pay after that. That would be a reasonable choice then.

You could start with the basic ones (amd64, arm v6 & v7 should take care of most people either on regular desktops, Apple M{1-3} devices and Raspberry Pi and clones.

I agree that this is what we should go for. It will save resources and time of build. Allow us maybe to separate actions to releasing the image and testing changes (which can allow us to add PR trigger for simply testing if it builds).

Can we move this discussion to #227 ?

Also, you can test the action by simply forking it and running it from your own fork (that's how I built it/tested it for my PRs originally).

You can test it like that, but it will fail when reaching login to GitHub registry part as expected (you don't have credentials in your fork). That's another reason I advocate for a separate CI action other than the one used for publishing.

MohamedElashri avatar Apr 04 '24 21:04 MohamedElashri

@PalRist Can you give the new image a try now? It should be suitable for arm64.

MohamedElashri avatar Apr 13 '24 21:04 MohamedElashri