6

So I can't seem to figure this out, but I'm getting error code 127 when running a Dockerfile. What causes this error?

My Dockerfile:

FROM composer as comp

FROM php:7.4-fpm-alpine
COPY --from=comp /usr/bin/composer /usr/bin/composer
COPY ./docker/install-deps.sh /tmp/install-deps.sh
RUN echo $(ls /tmp)
RUN /tmp/install-deps.sh
COPY . /var/www
WORKDIR /var/www
RUN composer install -o --no-dev

The results after building the Dockerfile:

Building php
Step 1/9 : FROM composer as comp
 ---> 433420023b60
Step 2/9 : FROM php:7.4-fpm-alpine
 ---> 78e945602ecc
Step 3/9 : COPY --from=comp /usr/bin/composer /usr/bin/composer
 ---> 46117e22b4de
Step 4/9 : COPY ./docker/install-deps.sh /tmp/install-deps.sh
 ---> 7e46a2ee759c
Step 5/9 : RUN echo $(ls /tmp)
 ---> Running in aa1f900032f9
install-deps.sh
Removing intermediate container aa1f900032f9
 ---> eb455e78b7f6
Step 6/9 : RUN /tmp/install-deps.sh
 ---> Running in 6402a15cccb2
/bin/sh: /tmp/install-deps.sh: not found
ERROR: Service 'php' failed to build: The command '/bin/sh -c /tmp/install-deps.sh' returned a non-zero code: 127

The install-deps.sh:

#!/bin/sh

set -e

apk add --update --no-cache \
    postgresql-dev \
    mysql-client \
    yaml-dev \
    git \
    openssl

docker-php-ext-install pcntl pdo_mysql pdo_pgsql

# yaml
apk add --no-cache --virtual .build-deps g++ make autoconf
pecl channel-update pecl.php.net
pecl install yaml
docker-php-ext-enable yaml
apk del --purge .build-deps
4
  • Can you try RUN sh /tmp/install-deps.sh Commented Jun 15, 2020 at 15:25
  • Is the script file executable? Why echo $(...) instead of just running the command directly? (RUN ls -l /tmp/install-deps.sh without the echo wrapper.) Commented Jun 15, 2020 at 15:26
  • Running it with the sh gave an illegal option error. Yes, it is executable, and I use the echo because I tried just an ls and I wasn't seeing the results when I ran docker-compose build --no-cache Commented Jun 16, 2020 at 10:12
  • We'd need to know more about that "illegal option" error. If the illegal option is a carriage return, f/e, that implies that you need to run dos2unix on the script. Commented Jan 21, 2024 at 18:46

2 Answers 2

7

Docker is executing the install-deps.sh script. The issue is with a command inside install-deps.sh that is not recognized when docker attempts to run the script.

As you can see the script returns an error code of 127 meaning that a command within the file does not exist.

For instance - try this:

touch test.sh
echo "not-a-command" >> test.sh
chmod 755 test.sh
/bin/sh -c "./test.sh"

Output:

/root/test.sh: line 1: not-a-command: command not found

Now check the exit code:

echo $?
127

I would suggest running the script inside an interactive environment to identify/install the command that is not found.

Sign up to request clarification or add additional context in comments.

2 Comments

Yeah, you are right, if I make the file blank it works. I think it has something to do with the #!/bin/sh. I should be able to figure it out from here, when I find out what it is I'll comment on this question and then mark it as correct, thanks!
Is there any nice way of getting docker to spit out the output of the shell script it's trying to execute to make debugging a little easier?
0

I was building an Alpine Linux image which had a bash script called in the Dockerfile that was failing with the dreaded "127" error.

Short Answer:

Using the troubleshooting procedure later described, I discovered that there were actually (2) faults causing the 127 error:

Fault 1 Fix: Missing Package: In the Dockerfile I hadn't included bash with the other Alpine packages.

RUN apk add --no-cache --update bash app1 app2

Fault 2 Fix: docker buildx build command had a syntax error. I had added a bunch of tags and my local context (the "dot") ended up between them. I moved it to the end of the build command and with the other fix, all was happy:

time docker buildx build --no-cache --platform linux/arm64 \
-t f1linux/testrepo:test1 -t f1linux/testrepo:test2 -t \ 
f1linux/testrepo:test3 -f Dockerfile.COPY . --progress=plain

The 127 error feedback had me chasing a solution for the part of the Dockerfile calling the script when the error was actually consequential from a missing package and a syntax error in the build command.

Below follows how I isolated this compound fault

Troubleshooting Procedure:

Since the part of the Dockerfile calling the bash script was found to be CORRECT, showing changes to correct code only serves to confuse. As such, I won't cover this territory, but limit review to steps taken to isolate where the fault really lived.

Exclude Line Endings Issues:

After making no progress clearing the error in the part of the Dockerfile which downloads & executes the script, I began investigating non-obvious potential causes: non-printing characters.

Check Line Endings: Compare file encodings & line endings of the script being called in your Dockerfile and failing with scripts known to execute correctly in other Dockerfiles:

file -k script-Not-WORKING.sh
file -k script-WORKING.sh

Fix Line Ending Issues: Compare output of git status before and after git normalize to see if anything changed. If anything has, commit those changes.

git status
git add --renormalize .
git status

In my case renormalize made no changes and thereby excluded issues with Line Endings as being causal.

Reduce Complexity:

So I tried tweaks to how the script was called in the Dockerfile without success and neither could I see issues with encodings or line endings. I had to reduce complexity as much as possible.

Dockerfile: I copied & trimmed my Dockerfile down to the fewest lines and made (2) changes to the stripped-down version:

Change 1: I added a line which listed did an ls to validated it was both present and executable in --progress=plain feedback during the build

Change 2: I commented-out the name of the failing script and changed it to testscript.sh

FROM docker.io/alpine:latest
LABEL com.F1Linux.image.version="001.000.000"
RUN apk add --no-cache --update app1 app2

COPY --chmod=755 scripts-config /root/scripts-config/

RUN ls -al /root/scripts-config/

#RUN /root/scripts-config/realscript.sh
RUN /root/scripts-config/testscript.sh

Script: Next I created testscript.sh to prove in principle that a script could be executed successfully and this would help exclude any issues with the script itself (excluding the she-bang) being causal of the fault:

#!/bin/bash
echo "Hello World"

After creating it I chmod 777 the short test script

NOTE: chmod 777 is dangerous and should never EVER be used on a live production system. After you're done testing delete this file.

Docker buildx build: I simplified this by removing --build-arg and BUILDVAR= parameters, as all but 1 tag:

time docker buildx build --no-cache --platform linux/arm64 \
-t f1linux/testrepo:test1 . -f Dockerfile.COPY --progress=plain

Remark the --no-cache as a parameter: this ensures we start with a clean slate each build.

Execution:

Executing the simplified docker buildx build command still failed, but slightly differently this time. The local context "dot" was now no longer sandwhiched between tags, so the test script was failing with an error 2. Although an error, it wasn't the 127 error, so progress was made by identifying the fault in the build command.

A bit of Googling and I found a Stack post about adding the bash package. I executed the simplified build command again with the additional package and the test script was now successfully executing.

Armed with the knowledge gained in my reduced complexity test environment, I was able to fix the failing Dockerfile and the build command.

Conclusion:

Hope both the short answer and how I arrived at it helps others stuck. I also wanted to ensure I wrote this down in case I ever get into this kind of pain again...

2 Comments

chmod 777 should be eliminated, permanently, from everyone's debugging toolbox. Making anything both world-writable and executable concurrently is throwing away the UNIX permissions model absent very specific targeted mitigating circumstances; it means that any compromise to the container or system, even to a completely unprivileged user, can reach into any account that touches the filesystem content with permissions so modified.
Hi @CharlesDuffy I just needed to ensure I could get it to work in principle- I definitely never do such a thing on a production system. The `chmod' was on the test script and it was immediately deleted after I figured out how things were breaking. Appreciate your feedback and I'll add your note to my answer. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.