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

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

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>

Related

Run node module in guest executable

I've got a global npm package installed, TileServer, that I run as service through command line. I'd like to convert this to a guest executable in service fabric, but I'm having trouble implementing.
Pre-Guest executable, I would invoke the following command in cmd:
tileserver-gl-light --port=8788 map.mbtiles
My configuration for my guest executable is:
<ExeHost>
<Program>tileserver-gl-light</Program>
<Arguments>--port=8788 c:\maptiles.mbtiles</Arguments>
<WorkingFolder>Work</WorkingFolder>
</ExeHost>
Unfortunately, the error I get when trying to run the service just says "There were deployment errors. Continue?"
Any ideas on how to get this working?
Thanks!
Can you check to see if that application package validates on your local machine by calling Test-ServiceFabricApplicationPackage?
Usually SF expects the file to be
Present in the application package and
Some sort of executable file that the OS understands (for windows .bat, .exe, etc.)
In this case I think what you're saying is that the tileserver bits are actually outside the package (wherever your node packages are), and you're actually trying to use node to start it (since the tileserver-gl packages aren't natively executable by Windows).
If that's the case your program should probably be something like a batch file that just says "tileserver-gl-light" and then your command line args in it.
Include that batch file in your code package and reference that as your program (and straighten out how you want to pass the args) and you should be good to go.
As #masnider pointed out, the files must be present in the application package, and we must call the executable as something the OS understands. This presents particular challenges for node modules as:
They must be wrapped in a .bat
They can't be called using the global command
They need parameters
They files, node_modules, often has issues with file path length issues
My end service had the following file structure:
- ApplicationPackageRoot
- MyService.ServicePkg
- Code
- 7za.exe
- node.exe
- npm.7z
- start.bat
My ServiceManifest.xml had these values in it:
<SetupEntryPoint>
<ExeHost>
<Program>7za.exe</Program>
<Arguments>x npm.7z<Arguments>
<WorkingFolder>CodeBase</WorkingFolder>
</ExeHost>
</SetupEntryPoint>
<EntryPoint>
<ExeHost>
<Program>start.bat</Program>
<Arguments><Arguments>
<WorkingFolder>CodeBase</WorkingFolder>
</ExeHost>
<EnvironmentVariables>
<EnvironmentVariable Name="Port" Value="8788"/>
<EnvironmentVariable Name="TilePath" Value="mytiles.mbtiles"/>
</EnvironmentVariables>
</EntryPoint>
And finally, my start.bat was comprised of the following line:
.\node.exe npm/node_modules/tileserver-gl-light/sc/main.js --port=%Port% %TilePath%
So how did this work? The npm.7z in the Code consisted of my node_modules, pre-zipped. The 7za was the portable version of 7zip which allows use to get around the file path length issues present on windows. 7za is called in the SetupEntryPoint.
Then the SF calls start.bat, which reads in the environmental variables of Port and TilePath. This has to called the exactly .js file called by the normal tileserver-gl-light command.
Doing this results in a properly working node application in a service fabric guest executable.

Wildlfy Swarm YAML properites file

i'm trying to run swarm with custom parameters, when I pass the properties options on command line, the server detects these options and runs properly, for example when I run this command :
java -jar test.jar -Dswarm.https.certificate.generate=true
it generates a certificate and starts https on a specific port.
Now according to swarm documentation it's better to use a yaml config file, so I have created one with the properites I wanted. However when I specifiy the path to my yaml file in the command line :
java -jar test.jar -S C:\Users\x17\test\modules\wsserver\project-default.yml
in this case, the file containing the properties is ignored, and the server starts with a default configuration.
Should the project-default file be in a specific folder in my project ? does anybody have an idea how to solve this issue ?
Thanks
There's a difference between -s and -S. The -S option, that you're trying to use, is used for selecting a project-*.yml file that's packaged together with the application, inside the uberjar. For example,
java -jar app-swarm.jar -S local
means that the file project-local.yml packaged inside the application is used.
If you want to set a full path to the YAML file, you need to use -s:
java -jar app-swarm.jar -s .../path/to/project-defaults.yml
See the documentation for more info: http://docs.wildfly-swarm.io/2018.1.0/#configuring-an-application-using-yaml
https://github.com/thorntail/thorntail-examples/blob/master/config-options/cdi-injection/src/main/java/org/wildfly/swarm/examples/jaxrs/cdi/Controller.java
Can help you to figure out the issue.
#Inject
#ConfigurationValue("some.string.property")
String stringProperty;
is valid CDI injection solution.

Run Play application in production mode using dist taks

I am using 'dist' task to generate a distribution of my play application. But if I unzip the generated artifact, in the bin/ directory I have access to the bash file generated by the 'dist' task. The last line of the script is : run "$#"
I saw in the official Play Framework documentation that 'run' command should not be used in production mode, and the recommended way is to generated a distribution with task 'dist'
Why 'dist' is generating a bash script which is using 'run' commmand if it is not recommended in production mode?
I am asking this, because when I deploy my application in production, the first request is slow...it seems the development behavior. But I am using the 'dist' command.
I would appreciate any help.
Thank you.
You are mixing two different things.
The run command stated in the Play documentation is a SBT command, that will start your app in dev mode. So to use that command you have to use activator or sbt (ex: ./activator run).
The run you see in that script is a bash function (defined a little above), that will start your app in production mode. A little snippet from that function:
# Actually runs the script.
run() {
# TODO - check for sane environment
# process the combined args, then reset "$#" to the residuals
# (...)
execRunner "$java_cmd" \
${java_opts[#]} \
"${java_args[#]}" \
-cp "$(fix_classpath "$app_classpath")" \
"${mainclass[#]}" \
"${app_commands[#]}" \
"${residual_args[#]}"
(...)
}
So, if you use this script to run your app, it will start in production mode.

In Rundeck: how can you set the working directory for command execution?

No matter what I try, executing pwd always prints /var/log/rundeck. I'd like to configure this as a global or even project-wide setting as all my scripts and commands will be relative to a specific directory on the file system.
/home/jobs for example.
There is no setting on Rundeck can set working directory.
Each command is running in separate context, you can chain them together.
As an improvement to the above answer by "Yang" you can edit rundeck "resources.xml" file and add a attribute called "nodepwd" with your node location like below.
<node name="localhost" nodepwd="/your/pwd/location" .... />
Then you can change your path to that and execute the commands.
In my case, I have to run "cd $RD_NODE_NODEPWD" in my inline scripts to change the current working directory.

Executable file to run java on CentOS 5

I'm trying to make a simple file so I can call it in SSH and it will start my minecraft server.
I tried making a batch file called start.bat with this code:
java -Xmx512M -Xmx512M -jar craftbukkit-1.2.5-R1.0.jar nogui
However, when I run it in SSH:
$ cd /Minecraft/server_1/
$ start.bat
The SSH returns that it is an invalid or unknown command. Is there any other way I can make a quick command/file to start my server? What file extensions would I use to get this working? It works if I paste that java command in SSH and run it, but I'd rather have a file.
The current working directory is not included in your PATH by default because it is a security risk on multiuser systems. (And a potential annoyance even on machines that are single user.) You would use ./start.bat to start the program.
Since you're using Windows naming conventions, I presume you also forgot to set the execution mode bit -- and you probably also forgot the shebang line at the top of the file.
Try this:
#!/bin/sh
java -Xmx512M -Xmx512M -jar craftbukkit-1.2.5-R1.0.jar nogui
Run chmod 500 on this file. (Strictly speaking, 555 could also work, if you didn't mind other people on the machine executing the file. But they don't need to, so don't let them.) See the chmod(1) manpage for more details on the modes -- 1 bits mean executable, 2 bits means writable, and 4 bits means readable -- thus, 5 is executable and readable.
Then, when you want to run the script, run it like this:
cd /Minecraft/server_1
./start.bat
Note the ./ -- that means the shell should start the search for the executable program in the current working directory. (It could be ./bin/start.bat if your current working directory had a bin subdirectory with a start.bat executable file.)
Is start.bat executable? Make sure you have #!/bin/sh as the first line of the file. Also the directory is probably not in in the path, so try this:
$ chmod 555 start.bat
$ ./start.bat