jibmaven-jib

Google Jib - Is it possible to run a linux command at container startup using CMD/ENTRYPOINT?


Is it possible to run a linux command whenever container starts from jib image using cmd or entrypoint or any other mechanism in jib maven plugin and then start the java process ?

In my case i want to run this command:

echo "127.0.0.1 $HOSTNAME" >> /etc/hosts

Solution

  • You can always set a custom entrypoint using <container><entrypoint>. You can start a shell script, run a different program, etc. Sometimes, you may want to use the <extraDirectories> feature to copy a script (and give executable permissions to it).

    See here for some ideas to run a shell script:

    Another option is to define your own <entrypoint> to use a shell. (Therefore, you need a base image that includes a shell binary (such as /bin/bash). Note that the default base image prior to Jib 3.0 was Distroless and did not include a shell program. OTOH, Jib 3.0+ doesn't use Distroless.) In this method, you'll need to know the right Java runtime classpath and the main class to use in your JVM launch command. To help this, starting with Jib >= 3.1, Jib creates two JVM argument files inside a built image; they will hold, respectively, the classpath and the main class inside a built image.

    Knowing the entrypoint, you can write a shell script (my-entrypoint.sh):

    #!/bin/sh
    
    # Assumes `java` is on PATH in the base image.
    exec java $JAVA_OPTS \
      -cp $( cat /app/jib-classpath-file ) \
      $( cat /app/jib-main-class-file )
    

    Alternatively, if you are on Java 9+, you can leverage the @-argument file:

    exec java $JAVA_OPTS -cp @/app/jib-classpath-file @/app/jib-main-class-file
    

    Place my-entrypoint.sh under <project root>/src/main/jib. This is the default directory for Jib's <extraDirectories> feature, and Jib will place src/main/jib/my-entrypoint.sh at the root directory in the container image. Then set the default <entrypoint> to this script:

    <container>
      <!-- Assumes you have /bin/sh as specified at the top of /my-entrypoint.sh. -->
      <entrypoint>/my-entrypoint.sh</entrypoint>
    </container>
    <!-- You also need to make the script executable. -->
    <extraDirectories>
      <permissions>
        <permission>
          <file>/my-entrypoint.sh</file>
          <mode>755</mode>
        </permission>
      </permissions>
    </extraDirectories>
    

    Alternatively, if you invoke /bin/sh as below, you don't have to configure <extraDirectories> to make the file executable. This may not look customary; you would normally make the script executable and run it directly. But this is perfectly valid, and there is no difference in terms of actual execution (as long as the shebang of /entrypoint.sh is the same #!/bin/sh).

    <container>
      <entrypoint>
        <arg>/bin/sh</arg>
        <arg>/my-entrypoint.sh</arg>
      </entrypoint>
    </container>
    

    It's also possible to do this without creating a script (basically embedding the entire script in pom.xml and passing it to a shell program). In this case, you don't need to configure <extraDirectories>.

              <container>
                <entrypoint>
                  <arg>/bin/sh</arg>
                  <arg>-c</arg>
                  <arg>exec java $JAVA_OPTS -cp $( cat /app/jib-classpath-file ) $( cat /app/jib-main-class-file )</arg>
                </entrypoint>
              </container>