Elm-format: problem using elm-format in Alpine docker image

Created on 4 Jan 2019  路  19Comments  路  Source: avh4/elm-format

We recently replaced our Ubuntu-based docker images used in the CI pipeline with Alpine-based images. Unfortunately, running elm-format 0.8.1 in those images results in this error:

bash-4.4# elm-format
events.js:165
      throw er; // Unhandled 'error' event
      ^

Error: spawn /usr/local/share/.config/yarn/global/node_modules/elm-format/unpacked_bin/elm-format ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:201:19)
    at onErrorNT (internal/child_process.js:379:16)
    at process._tickCallback (internal/process/next_tick.js:178:19)
    at Function.Module.runMain (internal/modules/cjs/loader.js:697:11)
    at startup (internal/bootstrap/node.js:201:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)
Emitted 'error' event at:
    at Process.ChildProcess._handle.onexit (internal/child_process.js:207:12)
    at onErrorNT (internal/child_process.js:379:16)
    [... lines matching original stack trace ...]
    at bootstrapNodeJSCore (internal/bootstrap/node.js:516:3)
bash-4.4# node -v
v9.11.1

bash-4.4# yarn -v
1.7.0

Does anybody know what the problem could be?

packaging Linux

Most helpful comment

I have a minimal example for reproducing:

docker run -it node:12 /bin/sh -c "npm i elm-format && node_modules/.bin/elm-format --help" # works
docker run -it node:12-alpine /bin/sh -c "npm i elm-format && node_modules/.bin/elm-format --help" # errors

All 19 comments

Does /usr/local/share/.config/yarn/global/node_modules/elm-format/unpacked_bin/elm-format after getting that error? If so, is the file there able to be executed by the current user?

(Also, if someone could post repro steps using a public alpine-based docker image, that would be useful)

Here's a minimal example with instructions: https://gitlab.com/woylie/elmformat_alpine

I'm having the same exact issue.

Is there any solution?

Same error here using node:8.16-alpine (https://hub.docker.com/_/node).

$ docker-compose exec frontend elm-format
events.js:183
      throw er; // Unhandled 'error' event
      ^

Error: spawn /usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:190:19)
    at onErrorNT (internal/child_process.js:362:16)
    at _combinedTickCallback (internal/process/next_tick.js:139:11)
    at process._tickCallback (internal/process/next_tick.js:181:9)
    at Function.Module.runMain (module.js:696:11)
    at startup (bootstrap_node.js:204:16)
    at bootstrap_node.js:625:3

installed in the container using:

RUN apk add --update git; \
    npm -g config set user root; \
    npm install -g create-elm-app @dillonkearns/elm-graphql elm-format

I'm having a different issue (might be related in the background though).

I'm using Alpine as my main distribution (not inside container).

I've installed elm-format via yarn.

When I run it with yarn elm-format src/ it throws __strdup: symbol not found.

These kind of issues are very common on Alpine, since it doesn't ship with glibc.

Note to self: here are the instructions for publishing an alpine apk: https://wiki.alpinelinux.org/wiki/Creating_an_Alpine_package

Notes about publishing haskell binaries for alpine:

This same error happens on my env. After I install elm-format with the command npm i -g --unsafe elm-format I try to run a simple elm-format --help to see if everything is working but this is what happens

bash-5.0# elm-format --help
events.js:200
      throw er; // Unhandled 'error' event
      ^

Error: spawn /usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:264:19)
    at onErrorNT (internal/child_process.js:456:16)
    at processTicksAndRejections (internal/process/task_queues.js:81:21)
Emitted 'error' event on ChildProcess instance at:
    at Process.ChildProcess._handle.onexit (internal/child_process.js:270:12)
    at onErrorNT (internal/child_process.js:456:16)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  errno: 'ENOENT',
  code: 'ENOENT',
  syscall: 'spawn /usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format',
  path: '/usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format',
  spawnargs: [ '--help' ]
}

The error message is not very clear but, after some digging, I suspect that this happens because the elm-format binary file is not compatible with Alpine. To reach this conclusion I tried to run the binary directly

# Using a dot in the beginning of the command
bash-5.0# ./usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format  --help
bash: ./usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format: No such file or directory

# No dots
bash-5.0# /usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format  --help
bash: /usr/local/lib/node_modules/elm-format/unpacked_bin/elm-format: No such file or directory

Alpine simply doesn't recognise the command. When I run elm-format --help outside the container all works fine

dan@dan:~/lab/elm/blog0$ elm-format --help
elm-format 0.8.2

Usage: elm-format [INPUT] [--output FILE] [--yes] [--validate] [--stdin]
                  [--elm-version VERSION] [--upgrade]
  Format Elm source files.

Available options:
  -h,--help                Show this help text
  --output FILE            Write output to FILE instead of overwriting the given
                           source file.
  --yes                    Reply 'yes' to all automated prompts.
  --validate               Check if files are formatted without changing them.
  --stdin                  Read from stdin, output to stdout.
  --elm-version VERSION    The Elm version of the source files being formatted.
                           Valid values: 0.18, 0.19. Default: auto
  --upgrade                Upgrade older Elm files to Elm 0.19 syntax

Examples:
  elm-format Main.elm                     # formats Main.elm
  elm-format Main.elm --output Main2.elm  # formats Main.elm as Main2.elm
  elm-format src/                         # format all *.elm files in the src directory

Full guide to using elm-format at <https://github.com/avh4/elm-format>

Its a shame since Alpine seems to be one of the smaller and most secure options

Is there an update on this? Anything I can do to help?

I have a minimal example for reproducing:

docker run -it node:12 /bin/sh -c "npm i elm-format && node_modules/.bin/elm-format --help" # works
docker run -it node:12-alpine /bin/sh -c "npm i elm-format && node_modules/.bin/elm-format --help" # errors

I tried compiling a static linux binary, but got this error requires dynamic R_X86_64_32 reloc against '__TMC_END__' which may overflow at runtime; recompile with -fPIC, but adding -fPIC to the gcc options didn't fix it. I think this is going to take quite a bit more work to figure out, so I'm not gonna block the 0.8.4 release on it.

Makes sense not to block the release.
Just posting this for future reference. Not sure if this helps but the elm compiler seems to do this for linux.
https://github.com/elm/compiler/blob/master/installers/linux/Dockerfile#L22+L36

oh, great, thanks for the link. I tried that ghc option earlier and got /usr/bin/ld.gold: error: /usr/lib/gcc/x86_64-linux-gnu/9/crtbeginT.o: requires dynamic R_X86_64_32 reloc against '__TMC_END__' which may overflow at runtime; recompile with -fPIC but looking at that docker file you linked to, I'm realizing the fix for that is to build it from an alpine image that has all the c libs prepped for static linking.

Cool, glad that it helped clear that up, :-) I knew it was something that has been solved before with the elm compiler.

Hi, I just ran into this issue and thought I would share how I unblocked myself 馃槃
Building the image below and then running docker cp to extract the binary should give an elm-format binary that can then be added to other alpine images during build!

I've pushed a prebuilt image to ghcr.io/bissy-io/elm-format-alpine:0.8.4, so if people want to avoid having to build from source themselves:

CONTAINER=$(docker create ghcr.io/bissy-io/elm-format-alpine:0.8.4)
docker cp ${CONTAINER}:/elm-format .
docker rm ${CONTAINER}


Dockerfile.elm-format-alpine

FROM alpine:3.12 as builder

RUN apk add --no-cache \
      git \
      curl \
      gcc \
      g++ \
      gmp-dev \
      ncurses-dev \
      libffi-dev \
      make \
      xz \
      tar \
      perl \
      bash

ENV BOOTSTRAP_HASKELL_NONINTERACTIVE=1
RUN curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh

ENV PATH="/root/.ghcup/bin:$PATH"

RUN ghcup install ghc 8.8.4
RUN ghcup set ghc 8.8.4

RUN git clone --depth 1 --branch 0.8.4 https://github.com/avh4/elm-format.git

WORKDIR /elm-format

RUN mkdir /output
RUN ./build.sh -- build
RUN cp ./_build/elm-format /output/elm-format

FROM alpine:3.12

LABEL org.opencontainers.image.source https://github.com/bissy-io/code

COPY --from=builder /output/elm-format /elm-format

I think this should be fixed by https://github.com/avh4/elm-format/pull/711 (building a linux static binary in alpine). I'll try releasing that in elm-format 0.8.5.

I'm testing the next release, and docker run -it node:14-alpine /bin/sh -c "npm i [email protected] && node_modules/.bin/elm-format --help" appears to work, so this should be fixed once 0.8.5 gets released (which will happen as soon as #722 is confirmed to be working)

[email protected] should work on alpine linux

Awesome, thx :-D

Was this page helpful?
0 / 5 - 0 ratings

Related issues

amitaibu picture amitaibu  路  6Comments

rtfeldman picture rtfeldman  路  7Comments

Janiczek picture Janiczek  路  5Comments

pdamoc picture pdamoc  路  8Comments

avh4 picture avh4  路  5Comments