Removing deprecated plugins when running Jenkins through Docker

Hi there! :wave:

I’ve been pondering a question and wanted to reach out to the community.
When you need to remove a deprecated plugin from your active Jenkins instance, whether you created it via docker-compose or a Dockerfile, what approach do you follow?
To be honest, my usual intuitive workflow doesn’t seem to do the trick.
Fortunately, @dduportal was generous enough to provide me with some valuable insights and knowledge about the lifecycle of Jenkins running in a Docker container. As a result, I now have a set of instructions that work well for me.
I’m curious, would you like me to share these instructions with the community? I’m curious if they would be helpful for others.

Context

Let’s consider a scenario where we are utilizing a docker-compose.yaml file to define our Jenkins instance. Although there may be numerous services, our focus will be on the Jenkins controller at present.

#  docker compose up -d --build --force-recreate
services:
    jenkins:
        build: ./controller
        restart: always
        ports:
            - "8080:8080"
            - "50000:50000"
        volumes:
            - jenkins-data:/var/jenkins_home:rw
            - ./casc.d:/var/jenkins_home/casc.d/:ro
            - ./secrets/id_jenkins.pem:/run/secrets/SSH_AGENT_KEY:ro
        environment:
            - JENKINS_EXT_URL=http://localhost:8080
            - CASC_JENKINS_CONFIG=/var/jenkins_home/casc.d/
            - org.jenkinsci.plugins.durabletask.BourneShellScript.LAUNCH_DIAGNOSTICS=true
            - PUBLIC_IP
[...]

The Dockerfile for the Jenkins controller is as follows:

FROM jenkins/jenkins:2.401.1-lts-jdk17

# [...]
## Install custom plugins
COPY --chown=jenkins:jenkins ./plugins.txt /usr/share/jenkins/plugins.txt
RUN jenkins-plugin-cli --plugin-file=/usr/share/jenkins/plugins.txt
# [...]

To define the plugins we wish to install, we are utilizing a plugins.txt file. However, it is worth noting that some of these plugins may become deprecated in the future. For this example, we are utilizing the Bootstrap 4 API Plugin, which has a dependency on the Popper API Plugin. At the time of writing, both of those plugins happen to be deprecated.

At the beginning of the removal process, these two plugins are defined in the plugins.txt file.

[...]
# See https://github.com/jenkinsci/docker#usage-1
[...]
bootstrap4-api
[...]
popper-api
[...]

Instructions

  1. Remove any references to the deprecated plugins in the plugins.txt file if you are using one.
  2. Rebuild the image.
    docker compose build jenkins
  3. Recreate your container if the rebuild was successful.
    docker compose up -d --build --force-recreate jenkins
  4. Optional: enter the running container to check if the plugin references are gone.
docker compose exec jenkins bash
cd /usr/share/jenkins/
cat plugins.txt | grep bootstrap
  1. Remove the plugins in the UI.
  2. Restart by hitting the /safeRestart endpoint.
  3. Optional: remove the plugins’ remnants from the Docker volume.
cd ~/plugins
ls -artl *
[...]
-rw-r--r--   1 jenkins jenkins        8 Jun  6 13:05 bootstrap4-api.jpi.version_from_image
-rw-r--r--   1 jenkins jenkins        0 Jun  6 13:05 bootstrap4-api.jpi.pinned
-rw-r--r--   1 jenkins jenkins        9 Jun  6 13:05 popper-api.jpi.version_from_image
-rw-r--r--   1 jenkins jenkins        0 Jun  6 13:05 popper-api.jpi.pinned
drwxr-xr-x   6 jenkins jenkins     4096 Jun  6 13:05 bootstrap4-api
drwxr-xr-x   5 jenkins jenkins     4096 Jun  6 13:05 popper-api
[...]
rm -fr bootstrap4-api* popper-api*

If anyone could take some time to review and/or test this set of instructions, I would appreciate it.
Thanks.