I have a docker file containing the following:
FROM quay.io/quarkus/ubi-quarkus-native-image:21.3.1-java11 AS build
COPY --chown=quarkus:quarkus gradlew /code/gradlew
COPY --chown=quarkus:quarkus gradle /code/gradle
COPY --chown=quarkus:quarkus build.gradle /code/
COPY --chown=quarkus:quarkus settings.gradle /code/
COPY --chown=quarkus:quarkus gradle.properties /code/
USER quarkus
WORKDIR /code
COPY src /code/src
RUN ./gradlew -b /code/build.gradle buildNative
If I run this on my local machine the ouput is the following:
=> => transferring context: 2.92kB 0.0s
=> CACHED [stage-2 2/4] WORKDIR /work/ 0.0s
=> [upx 2/4] RUN apk add upx 1.3s
=> [build 2/9] COPY --chown=quarkus:quarkus gradlew /code/gradlew 0.1s
=> [build 3/9] COPY --chown=quarkus:quarkus gradle /code/gradle 0.1s
=> [build 4/9] COPY --chown=quarkus:quarkus build.gradle /code/ 0.1s
=> [build 5/9] COPY --chown=quarkus:quarkus settings.gradle /code/ 0.1s
=> [build 6/9] COPY --chown=quarkus:quarkus gradle.properties /code/ 0.1s
=> [build 7/9] WORKDIR /code 0.1s
=> [build 8/9] COPY src /code/src 0.1s
=> [build 9/9] RUN ./gradlew -b /code/build.gradle buildNative 3.2s
=> => # Downloading https://services.gradle.org/distributions/grad
It then continues to run properly. While running the same script on our gitlab runner I get the following Output log:
---> 66dd5c97837d
Step 2/20 : COPY --chown=quarkus:quarkus gradlew /code/gradlew
---> 92ad903588b2
Step 3/20 : COPY --chown=quarkus:quarkus gradle /code/gradle
---> f67582214dec
Step 4/20 : COPY --chown=quarkus:quarkus build.gradle /code/
---> 25fdaf96a20a
Step 5/20 : COPY --chown=quarkus:quarkus settings.gradle /code/
---> d63cba46f07c
Step 6/20 : COPY --chown=quarkus:quarkus gradle.properties /code/
---> 6d0cc0364064
Step 7/20 : USER quarkus
---> Running in ab3bc02ff8db
Removing intermediate container ab3bc02ff8db
---> 93fa8ab3ccfa
Step 8/20 : WORKDIR /code
---> Running in 44c374cbff29
Removing intermediate container 44c374cbff29
---> 2ad2b4116dc1
Step 9/20 : COPY src /code/src
---> b126f09c4e4d
Step 10/20 : RUN ./gradlew -b /code/build.gradle buildNative
---> Running in 8e9a2d47749c
/bin/sh: ./gradlew: Permission denied
The command '/bin/sh -c ./gradlew -b /code/build.gradle buildNative' returned a non-zero code: 126
And afterwards it of course exits. I have no clue why the permissions inside the docker container would differ from machine to machine so any help would be appreciated
Gradlew file content as requested, although I don’t think it matters:
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> (.*)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname "$PRG"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS "-Xdock:name=$APP_NAME" "-Xdock:icon=$APP_HOME/media/gradle.icns""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`=""$arg""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\n "$i" | sed "s/'/'\\''/g;1s/^/'/;$s/$/' \\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS ""-Dorg.gradle.appname=$APP_BASE_NAME"" -classpath ""$CLASSPATH"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
2
Answers
So no matter what I did I couldn't fix the bug. Jamies idea to check the permissions in the docker container from his answer was not possible for me, as this was a multistage docker file and the container was destroyed before the end of the pipeline.
My solution now was to convert to maven using this guide from baeldung. Note that I had to redo the Pom more or less entirely, as the converter seems to not work properly with Quarkus. For some reason this fixed the issue entirely. Might be an issue with how the gradlew file was created on my system vs in the repository or something along those lines. (The beginning of) my new dockerfile would then look like this:
Try removing the Gradle build step, so Docker successfully creates the Image, then run it and SSH in, to double-check the permissions yourself.
I wonder if it is an issue with the file permissions inside the copied
gradle/
folder? Per this Docker issue, COPY does not applychown
recursively.Good luck!