Home > Software design >  Why does docker miss permissions in git?
Why does docker miss permissions in git?

Time:10-13

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" "$@"

CodePudding user response:

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 apply chown recursively.

Docker won't recursively chown the full parent path, because this may be an existing path. If you need that path to be owned by foo:bar, make sure to create it upfront, and giving it the correct permissions instead of relying on COPY to create the path.

Good luck!

CodePudding user response:

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:

FROM quay.io/quarkus/ubi-quarkus-native-image:21.3.1-java11 AS build
COPY --chown=quarkus:quarkus mvnw /code/mvnw
COPY --chown=quarkus:quarkus .mvn /code/.mvn
COPY --chown=quarkus:quarkus pom.xml /code/
USER quarkus
WORKDIR /code
RUN chmod  x ./mvnw
RUN ./mvnw -B org.apache.maven.plugins:maven-dependency-plugin:3.1.2:go-offline
COPY src /code/src
RUN ./mvnw package -Pnative
  • Related