docker
docker copied to clipboard
Preventing plugin setup wizard
if I use
FROM jenkins:2.7.1
RUN echo 2.7.1 > /usr/share/jenkins/ref/jenkins.install.UpgradeWizard.state
RUN echo 2.7.1 > /usr/share/jenkins/ref/jenkins.install.InstallUtil.lastExecVersion
then I can avoid the wizard, but the admin password is not printed in the logs
Is there a way to just prevent the plugin setup?
Not sure. @kzantow do you know?
If the initial admin user is actually created, it should print to the logs, see: https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/install/SetupWizard.java#L91-L153
You may also want to pass -Djenkins.install.runSetupWizard=false
to skip the initial setup altogether.
Optionally, you could cat $JENKINS_HOME/secrets/initialAdminPassword
.
If you actually just want to prevent the plugin setup, but you DO want the initial security setup, you can implement your own InstallStateFilter
to alter the flow. You would need a plugin installed at boot time or to inject a class file into the war distribution, though. See: https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/jenkins/install/UpgradeWizard.java#L154 for a simple example.
The problem with -Djenkins.install.runSetupWizard=false
is that it is a runtime flag, not build time, vs. burning a file in the image
I'd say the typical flow is to build the image with some preconfigured plugins, then not ask for plugin setup at startup. Creating the admin user may be ok.
Hm, is there any way to provide a properties file or set system properties at boot time? Maybe hook into this somehow? https://github.com/jenkinsci/extras-executable-war/blob/master/src/main/java/Main.java#L171
at boot time yes, you can set JAVA_OPTS=-Djenkins.install.runSetupWizard=false
but I'm looking for something to do at build time, as it is then when the plugins are installed into the image
I guess as things stand, either package it with a modification to the Main
file I referenced to set the system property (or find a way to include a properties file in the distribution... or just add the command line flag to a run script if this is for a docker image). Or package a simple plugin that overrides the default behavior. It's trivial to do the latter, just involves actually making a plugin. I could send you an example, but it's basically the same as the UpgradeWizard
I referenced: you just plug into the lifecycle, and set it to the RUNNING
state, no matter what and It'll bypass the wizard (or wait until the security is configured and send it to the RUNNING state). There are a lot of solutions to this problem, let me know if I can help any other way.
@carlossg Is there any update here?
No updates. IIUC there is the option to skip the wizard but not a way to skip only plugin installation.
@carlossg Again, a fairly trivial InstallStateFilter
will do the trick, you just need to add a plugin with it before the app starts.
@kzantow yes, I mean there is no way for someone extending the image to just do that easily with a file marker or something like that
In our case we created a new Jenkins image which automatically installs some plugins and creates a admin user with a default password. So there is no Jenkins setup visible and after starting the container you can directly use Jenkins. See here: https://github.com/foxylion/docker-jenkins
@foxylion I tried using the approach you described after looking at your Dockerfile but, I can't login to Jenkins. The Docker image built fine but when I try to login via the Jenkins web UI, I specify the default id and password that were also specified in the Dockefile and I get: Invalid login information. Please try again.
Never mind, I looked closer at your Dockerfile and figured it out....
@ckmason You're missing the Groovy file to add the user: https://github.com/foxylion/docker-jenkins/blob/master/docker-images/master/default-user.groovy
Edit: Ok. :smile:
@foxylion -- I am having trouble making my own image using your ideas, so I've fallen back on using your image but that doesn't work either. Details in foxylion/docker-jenkins#1
@kzantow Can you please expain this behaviour? When I create a new Jenkins container with no mounts to store data in the host, then complete the Jenkins setup and then stop the container to save it as a new docker image (docker commit ...). Why isn't the setup completed when I start a new container with the saved image? I was expecting that my saved image contains now a Jenkins that is configured and ready to use.
e.g.:
sudo docker pull jenkins sudo docker run -d -p 8080:8080 jenkins ...complete Jenkins setup .... sudo docker stop a9 sudo docker commit a9 foo sudo docker rm a9 sudo docker run -d -p 8080:8080 foo .... do Jenkins setup again because it can find the old setup
Is there a way to save images with Jenkins data? I want to use my Docker registry as a backup system
Ok, found it out, its because of the Volume statement in the Dockerfile, removing it gets me to the expected behaviour.
https://github.com/jenkinsci/docker/blob/fd794015787ba07d84a7c8d4c625652e648408c5/Dockerfile#L21
@krm1 to clarify, volumes are not preserved into an image layer during commit.
So @kzantow there is still no way to choose not to run the plugin install wizard at build time?
@kzantow It is possible, have a look at my customized image: https://github.com/foxylion/docker-jenkins You can also use this image directly.
If you want to do this from just groovy, I think correct incantation is:
import static jenkins.model.Jenkins.instance as jenkins
import jenkins.install.InstallState
if (!jenkins.installState.isSetupComplete()) {
println '--> Neutering SetupWizard'
InstallState.INITIAL_SETUP_COMPLETED.initializeState()
}
@foxylion In your master docker image, I can see where you copy your groovy scripts, but where in the Dockerfile do you Run them? Sorry if I'm missing something totally obvious, I'm a docker noob!
Ohh nm, it's because it's an init file.
@coderanger 's incantation worked for me.
Worth noting, I could not get it to work when executing through a $JENKINS_HOME/init.groovy hook. Inside the call to InstallState.INITIAL_SETUP_COMPLETED.initializeState()
, a null SetupWizard
object was returned here which caused the init.groovy script to crash. But when running the script as the admin
or any other user with appropriate permissions, it successfully disabled the Startup Wizard.
This is what was working for me inside docker for Jenkins version 2.107.3. I created this groovy script which disables setup wizard and creates admin user with custom admin password so you can just cut out the part with creating user if you don't need that.
basic-security.groovy
#!groovy
import jenkins.model.*
import hudson.security.*
import jenkins.install.InstallState
def instance = Jenkins.getInstance()
println "--> creating local user 'admin'"
// Create user with custom pass
def user = instance.getSecurityRealm().createAccount('admin', 'someAdminPass')
user.save()
def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
instance.setAuthorizationStrategy(strategy)
if (!instance.installState.isSetupComplete()) {
println '--> Neutering SetupWizard'
InstallState.INITIAL_SETUP_COMPLETED.initializeState()
}
instance.save()
Then in Dockerfile
COPY basic-security.groovy /var/lib/jenkins/init.groovy.d/
# In case you are running as root
RUN chown -R jenkins:jenkins /var/lib/jenkins/init.groovy.d/
Also if you want preinstalled plugins when building the image, you will need to copy plugin installation script from orginal Jenkins docker repository and optionally a text file with plugins to be installed.
install-plugins.sh https://github.com/jenkinsci/docker/blob/master/install-plugins.sh jenkins-support https://github.com/jenkinsci/docker/blob/master/jenkins-support
Plugins file example: plugins.txt https://github.com/fabric8io/jenkins-docker/blob/master/plugins.txt
Dockerfile
COPY install-plugins.sh /usr/local/bin/
COPY jenkins-support /usr/local/bin/
COPY plugins.txt /var/lib/jenkins/plugins.txt
RUN /usr/local/bin/install-plugins.sh < /var/lib/jenkins/plugins.txt
For me, the problem was default jenkins directory which is /var/lib/jenkins and preinstalled plugins go to /usr/share/jenkins/ref/plugins. Although the script should move installed plugins to /var/lib/jenkins/plugins, for some reason it didn't work. So I needed to change REF_DIR variable in install-plugins.sh script. After that, the script will install plugins directly to Jenkins home folder.
REF_DIR=${REF:-/usr/share/jenkins/ref/plugins}
to
REF_DIR=${REF:-/var/lib/jenkins/plugins}
Alternatively, if you don't want to change file directly you can do it with sed while building the image:
RUN sed -i "/REF_DIR=/c\REF_DIR=${REF:-/var/lib/jenkins/plugins}" /usr/local/bin/install-plugins.sh
@cromat Unfortunately the code for disabling the wizard does not work as of 2.121.1
@foxylion after skip the setup wizard.the file jenkins.model.JenkinsLocationConfiguration.xml at jenkins_home was missed. and in that case when I access the BUILD_URL or JOB_URL then will ruturn null, so I have to click the save-button in system settings.and after that the file jenkins.model.JenkinsLocationConfiguration.xml was be created. and as you know the jenkinsUrl in that file which can't be predefined in Dockerfile. is there anything else I can do ?
This seems to cause a great deal of confusion, see e.g.
- https://issues.jenkins-ci.org/browse/JENKINS-40279
- https://github.com/jenkinsci/configuration-as-code-plugin/issues/393
- https://github.com/geerlingguy/ansible-role-jenkins/issues/50
- https://riptutorial.com/jenkins/example/24925/disable-setup-wizard
etc. But many instructions seem wrong, outdated, etc. I can't yet find a method that actually works.
The answer "oh, just click OK" isn't really cool. This is meant to be a CI system, surely making it unnecessarily painful to deploy in fully automated, testable, configuration managed manner isn't ideal.
I was eventually able to make it behave with two JAVA_OPTS
properties, e.g.
docker run -it -p 8080:8080 -p 50000:50000 --rm \
--env JAVA_OPTS="-Djenkins.install.runSetupWizard=false" \
jenkins/jenkins
(Obviously my real run uses volumes etc, this is a minimal example)
I've created https://github.com/jenkinsci/docker/pull/833 to request some changes
After some trial and error, I was able to disable just the plugin installation phase of the installation wizard, without affecting the other sections.
The code I'm using is here: https://github.com/gryphon-zone/jenkins/blob/7788a6f9668561d5631c4c4b12fc69ba3bec1d84/configuration/disable-plugin-install-wizard.groovy And I'm adding it into my Dockerfile here: https://github.com/gryphon-zone/jenkins/blob/7788a6f9668561d5631c4c4b12fc69ba3bec1d84/Dockerfile#L41-L42
(worth noting, I'm doing other customization in the Dockerfile
to make Jenkins work for my specific use case, but the disable-plugin-install-wizard.groovy
script is solely for disabling the plugin section of the wizard, and can be used in isolation of any of the rest of the repo)
As mentioned in the comments for the groovy script, right now there isn't a dedicated installation state for the plugin configuration section of the wizard (or at least if there is, I couldn't find it), meaning it's possible that the script will break in a future release of Jenkins/start skipping more than just the plugin installation (if dedicated states are added in the future I'll update the script).
Additionally, I'm using the deprecated ExtensionList.add()
method: https://github.com/jenkinsci/jenkins/blob/57a3268afb749c84196ce5fa3cfd51b08cda1328/core/src/main/java/hudson/ExtensionList.java#L263-L279 (that may not be required, I haven't tried to get automatic registration working).
Definitely agree that given the presence of the install-plugins.sh
, it would be much more convenient if there were a simpler way to disable just the plugin installation phase of the wizard, without affecting other aspects.
Also worth mentioning, adding -Djenkins.install.runSetupWizard=false
isn't a good option anymore if your intention is just to skip plugin installation (if it ever was), because it bypasses the entire setup wizard, meaning things like adding an admin user and configuring the base URL are also skipped.
I think the README should be corrected, as is it misleading in its current state. The README clearly states:
For 2.x-derived images, you may also want to
RUN echo 2.0 > /usr/share/jenkins/ref/jenkins.install.UpgradeWizard.state
to indicate that this Jenkins installation is fully configured. Otherwise a banner will appear prompting the user to install additional plugins, which may be inappropriate.
This is clearly wrong, so this should be removed from the README.