jenkinsci / docker

Docker official jenkins repo
https://hub.docker.com/r/jenkins/jenkins
MIT License
6.67k stars 4.52k forks source link

Set JAVA_OPTS only for Jenkins and not for spawned processes #1288

Closed PapaNappa closed 2 years ago

PapaNappa commented 2 years ago

Jenkins and plugins versions report

Environment ```text Jenkins: 2.335 OS: Linux - 5.10.60.1-microsoft-standard-WSL2 --- ace-editor:1.1 antisamy-markup-formatter:2.7 apache-httpcomponents-client-4-api:4.5.13-1.0 bootstrap4-api:4.6.0-3 bootstrap5-api:5.1.3-5 bouncycastle-api:2.25 branch-api:2.7.0 build-timeout:1.20 caffeine-api:2.9.2-29.v717aac953ff3 checks-api:1.7.2 cloudbees-folder:6.18 command-launcher:1.6 credentials:1074.v60e6c29b_b_44b_ credentials-binding:1.27.1 display-url-api:2.3.5 durable-task:493.v195aefbb0ff2 echarts-api:5.3.0-2 font-awesome-api:6.0.0-1 git:4.10.3 git-client:3.11.0 git-server:1.10 gradle:1.38 handlebars:3.0.8 jackson2-api:2.13.1-246.va8a9f3eaf46a javax-activation-api:1.2.0-2 javax-mail-api:1.6.2-5 jaxb:2.3.0.1 jdk-tool:1.5 jquery3-api:3.6.0-2 jsch:0.1.55.2 junit:1.55 lockable-resources:2.14 mailer:408.vd726a_1130320 matrix-project:1.20 momentjs:1.1.1 pipeline-build-step:2.16 pipeline-graph-analysis:188.v3a01e7973f2c pipeline-input-step:446.vf27b_0b_83500e pipeline-milestone-step:100.v60a_03cd446e1 pipeline-model-api:2.2064.v5eef7d0982b_e pipeline-model-definition:2.2064.v5eef7d0982b_e pipeline-model-extensions:2.2064.v5eef7d0982b_e pipeline-rest-api:2.21 pipeline-stage-step:291.vf0a8a7aeeb50 pipeline-stage-tags-metadata:2.2064.v5eef7d0982b_e pipeline-stage-view:2.21 plain-credentials:1.8 plugin-util-api:2.14.0 popper-api:1.16.1-2 popper2-api:2.11.2-1 resource-disposer:0.17 scm-api:595.vd5a_df5eb_0e39 script-security:1131.v8b_b_5eda_c328e snakeyaml-api:1.29.1 ssh-credentials:1.19 sshd:3.1.0 structs:308.v852b473a2b8c timestamper:1.17 token-macro:277.v7c8f82a_d66b_3 trilead-api:1.0.13 workflow-aggregator:2.6 workflow-api:1138.v619fd5201b_2f workflow-basic-steps:937.v7a_b_7579e07a_3 workflow-cps:2656.vf7a_e7b_75a_457 workflow-cps-global-lib:561.va_ce0de3c2d69 workflow-durable-task-step:1121.va_65b_d2701486 workflow-job:1167.v8fe861b_09ef9 workflow-multibranch:707.v71c3f0a_6ccdb_ workflow-scm-step:2.13 workflow-step-api:622.vb_8e7c15b_c95a_ workflow-support:813.vb_d7c3d2984a_0 ws-cleanup:0.40 ```

What Operating System are you using (both controller, and any agents involved in the problem)?

Docker for Windows

Reproduction steps

  1. docker run -e JAVA_OPTS=-Xmx2G -p 8080:8080 -d --name jenkins jenkins/jenkins
  2. Execute e.g. a Gradle build on the master
  3. docker exec -it jenkins bash -c "for f in /proc/*/cmdline; do cat $f | grep -ae gradle; echo; done"

Expected Results

When executing a gradle build, the JVM executing the Gradle build uses the default max heap size (-Xmx64m in my case).

docker exec -it jenkins bash -c "for f in /proc/*/cmdline; do cat $f | grep -ae gradle; echo; done" will output, among others:

/opt/java/openjdk/bin/java-Xmx64m-Xms64m-Dorg.gradle.appname…

Actual Results

The spawned JVM inherits JAVA_OPTS.

docker exec -it jenkins bash -c "for f in /proc/*/cmdline; do cat $f | grep -ae gradle; echo; done" will output, among others:

/opt/java/openjdk/bin/java-Xmx64m-Xms64m -Xmx2G-Dorg.gradle.appname…

Anything else?

JAVA_OPTS should not be the only way to add Java options to the JVM running Jenkins.

For me, the use case is a minimalistic local Jenkins setup for some tests, executing builds on the master node. I want to restrict Jenkins to not use all RAM. While this technically works with JAVA_OPTS, by the nature of it, it also applies to other JAVA tools. This can cause conflicts.

Related: https://github.com/jenkinsci/docker/issues/822

My preferred solution would be something like JENKINS_JAVA_OPTS. Unsetting JAVA_OPTS inside the build is not a viable solution imho, since this makes the projects dependent on the Jenkins installation.

timja commented 2 years ago

You shouldn't be building on the controller image, see https://github.com/jenkinsci/packaging/pull/261#issuecomment-1042011952

PapaNappa commented 2 years ago

While I get the general idea of not running jobs on the controller, I think that’s not really applicable to my use case.

Your linked comment and the controller isolation in the docs talk about production environments, security concerns and privileges. I don’t face any issues with missing privileges. It’s only me who has access to this instance, and it will be thrown away at some point. But until then, this is an annoying issue.

My use case is a local environment for testing/evaluation purposes only. One great thing of docker is to set-up local environments for developing and playing around really quick. And I think this is something Jenkins should also support - and does pretty good already. To be honest, this issue is just a small detail (and easy to fix).

Are there any arguments against supporting something like JENKINS_JAVA_OPTS?

(And yes, for production environments, I totally agree to build only on other nodes.)

timja commented 2 years ago

PR is fine, should probably have the ability to set different JAVA_OPTS for the controller and for the plugin manager script: https://github.com/jenkinsci/docker/blob/master/jenkins-plugin-cli.sh#L7

Needs test coverage as well

PapaNappa commented 2 years ago

👍 I could get around creating a PR this week, if you like.

timja commented 2 years ago

Sure

PapaNappa commented 2 years ago

PR is fine, should probably have the ability to set different JAVA_OPTS for the controller and for the plugin manager script: https://github.com/jenkinsci/docker/blob/master/jenkins-plugin-cli.sh#L7

Do you mean to have a similar function for the plugin-cli (PLUGIN_CLI_JAVA_OPTS)? It seems it is not really spawning new Java processes, thus no pollution of JAVA_OPTS is likely.

My idea was to leave plugin-cli alone, i.e. it still only reads JAVA_OPTS. Only the controller will also read JENKINS_JAVA_OPTS. So plugin-cli is still isolated from JENKINS_JAVA_OPTS.

timja commented 2 years ago

would be good to be able to isolate them and yes that's what I meant. if you set it there won't you have the same problem with it being passed along to gradle?

PapaNappa commented 2 years ago

But does plugin-cli call gradle at any point in time? From what I’ve seen, plugin-cli is always called by the user, e.g. in his own Dockerfile for customisation. But then it’s totally ok to set JAVA_OPTS only for that call, i.e. RUN JAVA_OPTS=… plugin-cli …. You can’t isolate that with the controller, since the controller itself spawns gradle.

I can add it to the plugin-cli anyway, I just felt it’s unnecessary there.

timja commented 2 years ago

True you could isolate it in that way.

Up to you 😄