### CHANGELOG
Changelog
=========
| See [GitHub releases](https://github.com/jenkinsci/docker/releases) |
| --- |
These release notes represent changes in the controller image content or packaging, but not in the bundled WAR files.
Please refer to the [weekly changelog](https://jenkins.io/changelog/) and [LTS changelog](https://jenkins.io/changelog-stable/) for WAR file changelogs.
## Version scheme
The repository follows the scheme of Jenkins, 2-digit for [Weekly releases](https://jenkins.io/download/weekly/) and 3-digit for [LTS releases](https://jenkins.io/download/lts/).
---
### CONTRIBUTING
# Issues and Contributing
Please note that only issues related to this Docker image will be addressed here.
* If you have Docker related issues, please ask in the [Docker user mailing list](https://groups.google.com/forum/#!forum/docker-user).
* If you have Jenkins related issues, please ask in the [Jenkins mailing lists](https://jenkins-ci.org/content/mailing-lists).
* If you are not sure, then this is probably not the place to create an issue and you should use any of the previously mentioned mailing lists.
If after going through the previous checklist you still think you should create an issue here please provide:
* Docker commands that you execute
* Actual result
* Expected outcome
* Have you tried a non-dockerized Jenkins and get the expected outcome?
* Output of `docker version`
* Other relevant information
If you are interested to provide fixes by yourself, you might want to check out the [dedicated documentation](HACKING.adoc).
---
### README
# Official Jenkins Docker image
[](https://hub.docker.com/r/jenkins/jenkins/)
[](https://hub.docker.com/r/jenkins/jenkins/)
[](https://gitter.im/jenkinsci/docker?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
The Jenkins Continuous Integration and Delivery server [available on Docker Hub](https://hub.docker.com/r/jenkins/jenkins).
This is a fully functional Jenkins server.
[https://jenkins.io/](https://jenkins.io/).
# Usage
```
docker run -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk21
```
NOTE: Read the section [_Connecting agents_](#connecting-agents) below for the role of the `50000` port mapping.
NOTE: Read the section [_DNS Configuration_](#dns-configuration) in case you see the message "This Jenkins instance appears to be offline."
This will store the workspace in `/var/jenkins_home`.
All Jenkins data lives in there - including plugins and configuration.
You will probably want to make that an explicit volume so you can manage it and attach to another container for upgrades:
```
docker run -p 8080:8080 -p 50000:50000 --restart=on-failure -v jenkins_home:/var/jenkins_home jenkins/jenkins:lts-jdk21
```
This will automatically create a 'jenkins_home' [docker volume](https://docs.docker.com/storage/volumes/) on the host machine.
Docker volumes retain their content even when the container is stopped, started, or deleted.
NOTE: Avoid using a [bind mount](https://docs.docker.com/storage/bind-mounts/) from a folder on the host machine into `/var/jenkins_home`, as this might result in file permission issues (the user used inside the container might not have rights to the folder on the host machine).
If you _really_ need to bind mount jenkins_home, ensure that the directory on the host is accessible by the jenkins user inside the container (jenkins user - uid 1000) or use `-u some_other_user` parameter with `docker run`.
```
docker run -d -v jenkins_home:/var/jenkins_home -p 8080:8080 -p 50000:50000 --restart=on-failure jenkins/jenkins:lts-jdk21
```
This will run Jenkins in detached mode with port forwarding and a volume attached. You can access logs using the command 'docker logs CONTAINER_ID' to check the first login token. The container ID will be returned in the output of the command above.
Or, directly print the initial admin password using:
```
docker exec cat /var/jenkins_home/secrets/initialAdminPassword
```
Replace `` with your actual Jenkins container ID or name.
To access Jenkins and complete the initial setup, follow the instructions in the [installation guide](https://www.jenkins.io/doc/book/installing/docker/#setup-wizard).
## Backing up data
If you bind mount a volume - you can simply back up that directory
(which is jenkins_home) at any time.
Using a bind mount is not recommended since it can lead to permission issues. Treat the jenkins_home directory as you would a database - in Docker you would generally put a database on a volume.
If your volume is inside a container - you can use `docker cp $ID:/var/jenkins_home` command to extract the data, or other options to find where the volume data is.
Note that some symlinks on some OSes may be converted to copies (this can confuse jenkins with lastStableBuild links, etc)
For more info check Docker docs section on [Use volumes](https://docs.docker.com/storage/volumes/)
## Setting the number of executors
You can define the number of executors on the Jenkins built-in node using a groovy script.
By default it is set to 2 executors, but you can extend the image and change it to your desired number of executors (recommended 0 executors on the built-in node) :
`executors.groovy`
```
import jenkins.model.*
Jenkins.instance.setNumExecutors(0) // Recommended to not run builds on the built-in node
```
and `Dockerfile`
```
FROM jenkins/jenkins:lts
COPY --chown=jenkins:jenkins executors.groovy /usr/share/jenkins/ref/init.groovy.d/executors.groovy
```
## Connecting agents
You can run builds on the controller out of the box.
The Jenkins project recommends that no executors be enabled on the controller.
In order to connect agents **through an inbound TCP connection**, map the port: `-p 50000:50000`.
That port will be used when you connect agents to the controller.
If you are only using [SSH (outbound) build agents](https://plugins.jenkins.io/ssh-slaves/), this port is not required, as connections are established from the controller.
If you connect agents using web sockets, the TCP agent port is not used either.
## Passing JVM parameters
You might need to customize the JVM running Jenkins, typically to adjust [system properties](https://www.jenkins.io/doc/book/managing/system-properties/) or tweak heap memory settings.
Use the `JAVA_OPTS` or `JENKINS_JAVA_OPTS` environment variables for this purpose :
```
docker run --name myjenkins -p 8080:8080 -p 50000:50000 --restart=on-failure --env JAVA_OPTS=-Dhudson.footerURL=http://mycompany.com jenkins/jenkins:lts-jdk21
```
JVM options specifically for the Jenkins controller should be set through `JENKINS_JAVA_OPTS`, as other tools might also respond to the `JAVA_OPTS` environment variable.
## Configuring logging
Jenkins logging can be configured through a properties file and `java.util.logging.config.file` Java property.
For example:
```
mkdir data
cat > data/log.properties < If this property is already set in **JAVA_OPTS** or **JENKINS_JAVA_OPTS**, then the value of
> `JENKINS_SLAVE_AGENT_PORT` will be ignored.
# Installing more tools
You can run your container as root - and install via apt-get, install as part of build steps via jenkins tool installers, or you can create your own Dockerfile to customise, for example:
```
FROM jenkins/jenkins:lts-jdk21
# if we want to install via apt
USER root
RUN apt-get update && apt-get install -y ruby make more-thing-here
# drop back to the regular jenkins user - good practice
USER jenkins
```
In such a derived image, you can customize your jenkins instance with hook scripts or additional plugins.
For this purpose, use `/usr/share/jenkins/ref` as a place to define the default JENKINS_HOME content you
wish the target installation to look like :
```
FROM jenkins/jenkins:lts-jdk21
COPY --chown=jenkins:jenkins custom.groovy /usr/share/jenkins/ref/init.groovy.d/custom.groovy
```
If you need to maintain the entire init.groovy.d directory and have a persistent JENKINS_HOME you may run the docker image with `-e PRE_CLEAR_INIT_GROOVY_D=true`
### Environment variable substitution for reference files
By default, environment variable substitution is disabled to preserve backward compatibility.
Set `JENKINS_ENABLE_ENV_SUBST=true` to enable it for configuration files copied from `/usr/share/jenkins/ref` to `$JENKINS_HOME` during container initialization.
Supported syntax:
- `${VAR}`
- `${VAR:-default}`
Supported file types: `.xml`, `.conf`, `.properties`, `.groovy`
Example configuration file:
```xml
${JENKINS_URL:-http://localhost:8080/}
${SMTP_HOST}
```
Example container startup:
```bash
docker run \
-e JENKINS_ENABLE_ENV_SUBST=true \
-e JENKINS_URL=https://jenkins.example.com \
-e SMTP_HOST=smtp.example.com \
jenkins/jenkins:lts-jdk21
```
> [!NOTE]
> For most dynamic configuration use cases, [Jenkins Configuration as Code](https://www.jenkins.io/projects/jcasc/) remains the recommended approach.
## Preinstalling plugins
### Install plugins
You can rely on [the plugin manager CLI](https://github.com/jenkinsci/plugin-installation-manager-tool/) to pass a set of plugins to download with their dependencies. This tool will perform downloads from update centers, and internet access is required for the default update centers.
### Setting update centers
During the download, the CLI will use update centers defined by the following environment variables:
- `JENKINS_UC` - Main update center.
This update center may offer plugin versions depending on the Jenkins LTS Core versions.
Default value: https://updates.jenkins.io
- `JENKINS_UC_EXPERIMENTAL` - [Experimental Update Center](https://jenkins.io/blog/2013/09/23/experimental-plugins-update-center/).
This center offers Alpha and Beta versions of plugins.
Default value: https://updates.jenkins.io/experimental
- `JENKINS_INCREMENTALS_REPO_MIRROR` -
Defines Maven mirror to be used to download plugins from the
[Incrementals repo](https://jenkins.io/blog/2018/05/15/incremental-deployment/).
Default value: https://repo.jenkins-ci.org/incrementals
- `JENKINS_UC_DOWNLOAD` - Download url of the Update Center.
Default value: `$JENKINS_UC/download`
- `JENKINS_PLUGIN_INFO` - Location of plugin information.
Default value: https://updates.jenkins.io/current/plugin-versions.json
It is possible to override the environment variables in images.
:exclamation: Note that changing update center variables **will not** change the Update Center being used by Jenkins runtime, it concerns only the plugin manager CLI.
### Installing Custom Plugins
Installing prebuilt, custom plugins can be accomplished by copying the plugin HPI file into `/usr/share/jenkins/ref/plugins/` within the `Dockerfile`:
```
COPY --chown=jenkins:jenkins path/to/custom.hpi /usr/share/jenkins/ref/plugins/
```
### Usage
You can run the CLI manually in Dockerfile:
```Dockerfile
FROM jenkins/jenkins:lts-jdk21
RUN jenkins-plugin-cli --plugins pipeline-model-definition github-branch-source:1.8
```
Furthermore, it is possible to pass a file that contains this set of plugins (with or without line breaks).
```Dockerfile
FROM jenkins/jenkins:lts-jdk21
COPY --chown=jenkins:jenkins plugins.txt /usr/share/jenkins/ref/plugins.txt
RUN jenkins-plugin-cli -f /usr/share/jenkins/ref/plugins.txt
```
When the Jenkins container starts, it will check whether `JENKINS_HOME` has this reference content and copy it
there if required. It will not override such files, so if you upgraded some plugins from the UI they won't
be reverted on the next start.
In case you _do_ want to override, append '.override' to the name of the reference file. E.g. a file named
`/usr/share/jenkins/ref/config.xml.override` will overwrite an existing `config.xml` file in JENKINS_HOME.
Also see [JENKINS-24986](https://issues.jenkins.io/browse/JENKINS-24986)
Here is an example to get the list of plugins from an existing server:
```
JENKINS_HOST=username:password@myhost.com:port
curl -sSL "http://$JENKINS_HOST/pluginManager/api/xml?depth=1&xpath=/*/*/shortName|/*/*/version&wrapper=plugins" | perl -pe 's/.*?([\w-]+).*?([^<]+)()(<\/\w+>)+/\1 \2\n/g'|sed 's/ /:/'
```
Example Output:
```
cucumber-testresult-plugin:0.8.2
pam-auth:1.1
matrix-project:1.4.1
script-security:1.13
...
```
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.
### Access logs
To enable Jenkins user access logs from the Jenkins home directory inside a Docker container, set the `JENKINS_OPTS` environment variable value to `--accessLoggerClassName=winstone.accesslog.SimpleAccessLogger --simpleAccessLogger.format=combined --simpleAccessLogger.file=/var/jenkins_home/logs/access_log`
### Naming convention in tags
The naming convention for the tags on Docker Hub follows the format `:`, where the repository name is jenkins/jenkins and where the tag specifies the image version.
In the case of the LTS and latest versions, the tags are `lts` and `latest`, respectively.
You can use these tags to pull the corresponding Jenkins images from Docker Hub and run them on your system.
For example, to pull the LTS version of the Jenkins image, use this command: `docker pull jenkins/jenkins:lts`
### Docker Compose with Jenkins
To use Docker Compose with Jenkins, you can define a docker-compose.yml file including a Jenkins instance and any other services it depends on.
For example, the following docker-compose.yml file defines a Jenkins controller and a Jenkins SSH agent:
```yaml
services:
jenkins:
image: jenkins/jenkins:lts
ports:
- "8080:8080"
volumes:
- jenkins_home:/var/jenkins_home
ssh-agent:
image: jenkins/ssh-agent
volumes:
jenkins_home:
```
This `docker-compose.yml` file creates two containers: one for Jenkins and one for the Jenkins SSH agent.
The Jenkins container is based on the `jenkins/jenkins:lts` image and exposes the Jenkins web interface on port 8080.
The `jenkins_home` volume is a [named volume](https://docs.docker.com/storage/volumes/) that is created and managed by Docker.
It is mounted at `/var/jenkins_home` in the Jenkins container, and it will persist the Jenkins configuration and data.
The ssh-agent container is based on the `jenkins/ssh-agent` image and runs an SSH server to execute [Jenkins SSH Build Agent](https://plugins.jenkins.io/ssh-slaves/).
To start the Jenkins instance and the other services defined in the `docker-compose.yml` file, run the `docker compose up -d`.
This will pull the necessary images from Docker Hub if they are not already present on your system, and start the services in the background.
You can then access the Jenkins web interface on `http://localhost:8080` on your host system to configure and manage your Jenkins instance (where `localhost` points to the published port by your Docker Engine).
NOTE: Read the section [_DNS Configuration_](#dns-configuration) in case you see the message "This Jenkins instance appears to be offline." In that case, add the DNS configuration to the YAML:
```yaml
services:
jenkins:
# ... other config
dns:
- 1.1.1.1
- 8.8.8.8
# ... other config
```
### Updating plugins file
The [plugin-installation-manager-tool](https://github.com/jenkinsci/plugin-installation-manager-tool) supports updating the plugin file for you.
Example command:
```command
JENKINS_IMAGE=jenkins/jenkins:lts-jdk21
docker run -it ${JENKINS_IMAGE} bash -c "stty -onlcr && jenkins-plugin-cli -f /usr/share/jenkins/ref/plugins.txt --available-updates --output txt" > plugins2.txt
mv plugins2.txt plugins.txt
```
## Upgrading
All the data needed is in the /var/jenkins_home directory - so depending on how you manage that - depends on how you upgrade.
Generally - you can copy it out - and then "docker pull" the image again - and you will have the latest LTS - you can then start up with -v pointing to that data (/var/jenkins_home) and everything will be as you left it.
As always - please ensure that you know how to drive docker - especially volume handling!
If you mount the Jenkins home directory to a [Docker named volume](https://docs.docker.com/storage/volumes/), then the upgrade consists of `docker pull` and nothing more.
We recommend using `docker compose`, especially in cases where the user is also running a parallel nginx/apache container as a reverse proxy for the Jenkins container.
### Upgrading plugins
By default, plugins will be upgraded if they haven't been upgraded manually and if the version from the docker image is newer than the version in the container.
Versions installed by the docker image are tracked through a marker file.
To force upgrades of plugins that have been manually upgraded, run the docker image with `-e PLUGINS_FORCE_UPGRADE=true`.
The default behaviour when upgrading from a docker image that didn't write marker files is to leave existing plugins in place.
If you want to upgrade existing plugins without marker you may run the docker image with `-e TRY_UPGRADE_IF_NO_MARKER=true`.
Then plugins will be upgraded if the version provided by the docker image is newer.
# Hacking
If you wish to contribute fixes to this repository, please refer to the [dedicated documentation](HACKING.adoc).
# Security
For information related to the security of this Docker image, please refer to the [dedicated documentation](SECURITY.md).
# Questions?
We're on Gitter, https://gitter.im/jenkinsci/docker
---
### SECURITY
# Security Policy
The Jenkins project takes security seriously.
We make every possible effort to ensure users can adequately secure their automation infrastructure.
You can find more information in the [general Security Policy](https://github.com/jenkinsci/.github/blob/master/SECURITY.md), this policy is specific to our Docker images.
## Docker Image Publication
When an image is published, the latest image and the latest available packages are used.
We rely on the base image provider for the security of the system libraries.
The default base image is Debian but multiple other variants are proposed, that could potentially better fit your needs.
## Reporting Security Vulnerabilities
If you have identified a security vulnerability and would like to report it, please be aware of those requirements.
For findings from a **Software Composition Analysis (SCA) scanner report**, all of the following points must be satisfied:
- If the finding is coming from the system (Docker layer):
- The scan must have been done on the latest version of the image.
Vulnerabilities are discovered in a continuous way, so it is expected that past releases could contain some.
- The package should have a fixed version provided in the base image that is not yet included in our image.
We rely on the base image provider to propose the corrections.
- The correction should have existed at the time the image was created.
Normally our update workflow ensures that the latest available versions are used.
- If the finding is coming from the application dependencies:
- Proof of exploitation or sufficiently good explanation about why you think it's impacting the application.
For all "valid" findings from SCA, your report must contain:
- The path to the library (there are ~2000 components in the ecosystem, we don't want to have to guess)
- The version and variant of the Docker image you scanned.
- The scanner name and version as well.
- The publicly accessible information about the vulnerability (ideally CVE). For private vulnerability database, please provide all the information at your disposal.
The objective is to reduce the number of reports we receive that are not relevant to the security of the project.
For findings from a **manual audit**, the report must contain either reproduction steps or a sufficiently well described proof to demonstrate the impact.
Once the report is ready, please follow the process about [Reporting Security Vulnerabilities](https://jenkins.io/security/reporting/).
We will reject reports that are not satisfying those requirements.
## Vulnerability Management
Once the report is considered legitimate, a new image is published with the latest packages.
In the case the adjustment has to be done in the building process (e.g. in the Dockerfile), the correction will be prioritized and applied as soon as possible.
By default we do not plan to publish advisories for vulnerabilities at the Docker level.
There may be exceptions.
---