Tyler
Tyler

Reputation: 3813

Docker: Error code 127 when executing shell script

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

Upvotes: 6

Views: 24953

Answers (2)

F1Linux
F1Linux

Reputation: 4373

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...

Upvotes: 0

Sean Ziegler
Sean Ziegler

Reputation: 143

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.

Upvotes: 7

Related Questions