{"id":16532828,"url":"https://github.com/mjstealey/jenkins-nginx-docker","last_synced_at":"2025-03-21T09:32:08.489Z","repository":{"id":29906021,"uuid":"118849687","full_name":"mjstealey/jenkins-nginx-docker","owner":"mjstealey","description":"Jenkins LTS / Nginx - Orchestrated with Docker Compose","archived":false,"fork":false,"pushed_at":"2023-03-03T18:25:28.000Z","size":12813,"stargazers_count":61,"open_issues_count":3,"forks_count":57,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-17T23:50:03.094Z","etag":null,"topics":["docker","docker-in-docker","jenkins","letsencrypt","nginx"],"latest_commit_sha":null,"homepage":"","language":"Dockerfile","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mjstealey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-25T02:16:41.000Z","updated_at":"2024-12-14T15:35:10.000Z","dependencies_parsed_at":"2024-10-11T18:13:36.150Z","dependency_job_id":"aafe87d8-f4b9-487e-b014-07ac3aef311f","html_url":"https://github.com/mjstealey/jenkins-nginx-docker","commit_stats":{"total_commits":17,"total_committers":2,"mean_commits":8.5,"dds":0.05882352941176472,"last_synced_commit":"8e5027c1c9212537abce15138824f55f17f07cd3"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjstealey%2Fjenkins-nginx-docker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjstealey%2Fjenkins-nginx-docker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjstealey%2Fjenkins-nginx-docker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mjstealey%2Fjenkins-nginx-docker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mjstealey","download_url":"https://codeload.github.com/mjstealey/jenkins-nginx-docker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244772429,"owners_count":20507983,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","docker-in-docker","jenkins","letsencrypt","nginx"],"created_at":"2024-10-11T18:13:31.283Z","updated_at":"2025-03-21T09:32:07.909Z","avatar_url":"https://github.com/mjstealey.png","language":"Dockerfile","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jenkins LTS - Docker\n\nNotes on [Jenkins LTS](https://www.jenkins.io/download/lts/#ji-toolbar) as a docker deployment orchestrated by Docker Compose. (version denoted at the time of writing this document)\n\n- Use the LTS version of Jenkins (v2.319.2)\n- Use Nginx as the web server (v1)\n- Include self-signed SSL certificate (Let's Encrypt localhost format)\n\n**DISCLAIMER: The code herein may not be up to date nor compliant with the most recent package and/or security notices. The frequency at which this code is reviewed and updated is based solely on the lifecycle of the project for which it was written to support, and is not actively maintained outside of that scope. Use at your own risk.**\n\n## Table of contents\n\n- [Overview](#overview)\n    - [Host Requirements](#reqts)\n- [Configuration](#config)\n- [Deploy](#deploy)\n- [GitHub OAuth integration](#github)\n- [Teardown](#teardown)\n- [References](#references)\n- [Notes](#notes)\n\n## \u003ca name=\"overview\"\u003e\u003c/a\u003eOverview\n\nJenkins offers a simple way to set up a continuous integration or continuous delivery environment for almost any combination of languages and source code repositories using pipelines, as well as automating other routine development tasks. While Jenkins doesn’t eliminate the need to create scripts for individual steps, it does give you a faster and more robust way to integrate your entire chain of build, test, and deployment tools than you can easily build yourself.\n\n\n- This work is based on the **Official Jenkins LTS Docker Image** [jenkins/jenkins:lts-jdk11](https://github.com/jenkinsci/docker)\n- Installs some prerequisites, configures the official Docker apt repositories and installs the latest **Docker CE** binaries\n- Mount the host machine's **Docker socket** in the container (This will allow your container to use the host machine's Docker daemon to run containers and build images).\n\n### \u003ca name=\"reqts\"\u003e\u003c/a\u003eHost requirements\n\nBoth Docker and Docker Compose are required on the host to run this code\n\n- Install Docker Engine: [https://docs.docker.com/engine/install/](https://docs.docker.com/engine/install/)\n- Install Docker Compose: [https://docs.docker.com/compose/install/](https://docs.docker.com/compose/install/)\n\n## \u003ca name=\"config\"\u003e\u003c/a\u003eConfiguration\n\nCopy the `env.template` file as `.env` and populate according to your environment\n\n```ini\n# docker-compose environment file\n#\n# When you set the same environment variable in multiple files,\n# here’s the priority used by Compose to choose which value to use:\n#\n#  1. Compose file\n#  2. Shell environment variables\n#  3. Environment file\n#  4. Dockerfile\n#  5. Variable is not defined\n\n# Jenkins Settings\nexport JENKINS_LOCAL_HOME=./jenkins_home\nexport JENKINS_UID=1000\nexport JENKINS_GID=1000\nexport HOST_DOCKER_SOCK=/var/run/docker.sock\n\n# Nginx Settings\nexport NGINX_CONF=./nginx/default.conf\nexport NGINX_SSL_CERTS=./ssl\nexport NGINX_LOGS=./logs/nginx\n\n# User Settings\n# TBD\n```\n\nModify `nginx/default.conf` and replace `$host:8443` with your server domain name and port throughout the file\n\n```conf\nupstream jenkins {\n    keepalive 32;              # keepalive connections\n    server cicd-jenkins:8080;  # jenkins container ip and port\n}\n\n# Required for Jenkins websocket agents\nmap $http_upgrade $connection_upgrade {\n    default upgrade;\n    '' close;\n}\n\nserver {\n    listen 80;                    # Listen on port 80 for IPv4 requests\n    server_name $host;\n    return 301 https://$host:8443$request_uri; # replace '8443' with your https port\n}\n\nserver {\n    listen          443 ssl;      # Listen on port 443 for IPv4 requests\n    server_name     $host:8443;   # replace '$host:8443' with your server domain name and port\n\n    # SSL certificate - replace as required with your own trusted certificate\n    ssl_certificate /etc/ssl/fullchain.pem;\n    ssl_certificate_key /etc/ssl/privkey.pem;\n\n    # logging\n    access_log      /var/log/nginx/jenkins.access.log;\n    error_log       /var/log/nginx/jenkins.error.log;\n\n    # this is the jenkins web root directory\n    # (mentioned in the /etc/default/jenkins file)\n    root            /var/jenkins_home/war/;\n\n    # pass through headers from Jenkins that Nginx considers invalid\n    ignore_invalid_headers off;\n\n    location ~ \"^/static/[0-9a-fA-F]{8}\\/(.*)$\" {\n        # rewrite all static files into requests to the root\n        # E.g /static/12345678/css/something.css will become /css/something.css\n        rewrite \"^/static/[0-9a-fA-F]{8}\\/(.*)\" /$1 last;\n    }\n\n    location /userContent {\n        # have nginx handle all the static requests to userContent folder\n        # note : This is the $JENKINS_HOME dir\n        root /var/jenkins_home/;\n        if (!-f $request_filename) {\n            # this file does not exist, might be a directory or a /**view** url\n            rewrite (.*) /$1 last;\n            break;\n        }\n        sendfile on;\n    }\n\n    location / {\n        sendfile off;\n        proxy_pass         http://jenkins;\n        proxy_redirect     default;\n        proxy_http_version 1.1;\n\n        # Required for Jenkins websocket agents\n        proxy_set_header   Connection        $connection_upgrade;\n        proxy_set_header   Upgrade           $http_upgrade;\n\n        proxy_set_header   Host              $host;\n        proxy_set_header   X-Real-IP         $remote_addr;\n        proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;\n        proxy_set_header   X-Forwarded-Proto $scheme;\n        proxy_set_header   X-Forwarded-Host  $host;\n        proxy_set_header   X-Forwarded-Port  8443; # replace '8443' with your https port\n        proxy_max_temp_file_size 0;\n\n        #this is the maximum upload size\n        client_max_body_size       10m;\n        client_body_buffer_size    128k;\n\n        proxy_connect_timeout      90;\n        proxy_send_timeout         90;\n        proxy_read_timeout         90;\n        proxy_buffering            off;\n        proxy_request_buffering    off; # Required for HTTP CLI commands\n        proxy_set_header Connection \"\"; # Clear for keepalive\n    }\n\n}\n```\n\n## \u003ca name=\"deploy\"\u003e\u003c/a\u003eDeploy\n\nOnce configured the containers can be brought up using Docker Compose\n\n```console\nsource .env\ndocker-compose pull\ndocker-compose build\ndocker-compose up -d\n```\n\nAfter a few moments the containers should be observed as running\n\n```console\n$ docker-compose ps\nNAME                COMMAND                  SERVICE             STATUS              PORTS\ncicd-jenkins        \"/sbin/tini -- /dock…\"   jenkins             running             0.0.0.0:50000-\u003e50000/tcp\ncicd-nginx          \"/docker-entrypoint.…\"   nginx               running             0.0.0.0:8080-\u003e80/tcp, 0.0.0.0:8443-\u003e443/tcp\n```\n\nThe Jenkins application can be reached at the designated host and port (e.g. [https://127.0.0.1:8443]()).\n\n- **NOTE**: you will likely have to acknowledge the security risk if using the included self-signed certificate.\n\n![](./imgs/jenkins-unlock.png)\n\nCopy the `Administrator password` from the docker log output of the jenkins container.\n\n```console\n$ docker-compose logs jenkins\ncicd-jenkins  | usermod: no changes\n...\ncicd-jenkins  | 2022-01-26 16:37:12.863+0000 [id=34]\tINFO\tjenkins.install.SetupWizard#init:\ncicd-jenkins  |\ncicd-jenkins  | *************************************************************\ncicd-jenkins  | *************************************************************\ncicd-jenkins  | *************************************************************\ncicd-jenkins  |\ncicd-jenkins  | Jenkins initial setup is required. An admin user has been created and a password generated.\ncicd-jenkins  | Please use the following password to proceed to installation:\ncicd-jenkins  |\ncicd-jenkins  | 1cd0eea03abc4ff1b184547625dd48f2\ncicd-jenkins  |\ncicd-jenkins  | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword\ncicd-jenkins  |\ncicd-jenkins  | *************************************************************\ncicd-jenkins  | *************************************************************\ncicd-jenkins  | *************************************************************\ncicd-jenkins  |\ncicd-jenkins  | 2022-01-26 16:37:24.156+0000 [id=34]\tINFO\tjenkins.InitReactorRunner$1#onAttained: Completed initialization\n```\n\nInstall the plugins you are interested in\n\n![](./imgs/jenkins-plugins-select.png)\n\nSetup an Administrative user\n\n![](./imgs/jenkins-admin-user.png)\n\nConfirm the URL and start using Jenkins\n\n![](./imgs/jenkins-url.png)\n![](./imgs/jenkins-is-ready.png)\n![](./imgs/jenkins-landing-page.png)\n\n## \u003ca name=\"github\"\u003e\u003c/a\u003eGitHub OAuth integration\n\n**GOAL**: Use GitHub to authenticate user access into Jenkins and authorize actions within it\n\n- Authorization is delegated using **Matrix-based security** by `organization` or `organization*repo` represented as **Group** membership at the user level\n- Do **NOT** log off the initial Administrator account prior to establishing a new Administrative User or Group that is accessible to an authorized GitHub user\n    - Once the **GitHub Authentication Plugin** is activated you will lose the standard login option of Username/Password\n    - After installing, the `\u003csecurityRealm\u003e` class should have been updated in your `/var/lib/jenkins/config.xml` file. The value of `\u003cclientID\u003e` should agree with what you pasted into the admin UI. If it doesn't or you still can't log in, reset to `\u003csecurityRealm class=\"hudson.security.HudsonPrivateSecurityRealm\"\u003e` and restart Jenkins from the command-line.\n\n### Install the GitHub OAuth Plugin\n\n- From Plugin Manager search for [GitHub Authentication](https://plugins.jenkins.io/github-oauth/)\n- Download and install after restart\n\n### Setup\n\nBefore configuring the plugin you must create a GitHub application registration.\n\n1. Visit [https://github.com/settings/applications/new](https://github.com/settings/applications/new) to create a GitHub application registration.\n2. The values for application name, homepage URL, or application description don't matter. They can be customized however desired.\n3. However, the authorization callback URL takes a specific value. It must be `https://jenkins.example.com/securityRealm/finishLogin` where jenkins.example.com is the location of the Jenkins server.\nThe important part of the callback URL is `/securityRealm/finishLogin`\n4. Finish by clicking Register application.\n\nThe `Client ID` and the `Client Secret` will be used to configure the Jenkins Security Realm. Keep the page open to the application registration so this information can be copied to your Jenkins configuration.\n\n### Security Realm in Global Security\n\nThe security realm in Jenkins controls authentication (i.e. you are who you say you are). The GitHub Authentication Plugin provides a security realm to authenticate Jenkins users via GitHub OAuth.\n\n1. In the Global Security configuration choose the Security Realm to be **GitHub Authentication Plugin**.\n2. The settings to configure are: GitHub Web URI, GitHub API URI, Client ID, Client Secret, and OAuth Scope(s).\n3. If you're using GitHub Enterprise then the API URI is [https://ghe.example.com/api/v3]().\nThe GitHub Enterprise API URI ends with `/api/v3`.\n4. The recommended minimum GitHub OAuth scopes are `read:org,user:email`.\nThe recommended scopes are designed for using both authentication and authorization functions in the plugin. If only authentication is being used then the scope can be further limited to `(no scope)` or `user:email`.\n\nIn the plugin configuration pages each field has a little (**?**) next to it. Click on it for help about the setting.\n\n![](./imgs/jenkins-github-oauth.png)\n\n### Authorization in Global Security.\n\nThe authorization configuration in Jenkins controls what your users can do (i.e. read jobs, execute builds, administer permissions, etc.). The GitHub OAuth Plugin supports multiple ways of configuring authorization.\n\nIt is highly recommended that you configure the security realm and log in via GitHub OAuth before configuring authorization. This way Jenkins can look up and verify users and groups if configuring matrix-based authorization.\n\n### Matrix-based Authorization strategy\n\nControl user authorization using **Matrix-based security** or **Project-based Matrix Authorization Strategy**. Project-based Matrix Authorization Strategy allows one to configure authorization globally per project and, when using Project-based Matrix Authorization Strategy with the CloudBees folder plugin, per folder.\n\nThere are a few built-in authorizations to consider.\n\n- `anonymous` - is anyone who has not logged in. Recommended permissions are just `Job/Discover` and `Job/ViewStatus`.\n- `authenticated` - is anyone who has logged in. You can configure permissions for anybody who has logged into Jenkins. Recommended permissions are `Overall/Read` and `View/Read`.\n`anonymous` and `authenticated` usernames are case sensitive and must be lower case. This is a consideration when configuring authorizations via Groovy. Keep in mind that anonymous shows up as Anonymous in the Jenkins UI.\n\nYou can configure authorization based on GitHub users, organizations, or teams.\n\n- `username` - give permissions to a specific GitHub username.\n- `organization` - give permissions to every user that belongs to a specific GitHub organization.\n- `organization*team` - give permissions to a specific GitHub team of a GitHub organization. Notice that organization and team are separated by an asterisk (*).\n\n![](./imgs/jenkins-authorization-matrix.png)\n\nRelated to the screenshot above:\n\n- User: `Michael J. Stealey` is an Administrative user that authenticated using the GitHub OAuth Plugin\n- User: `Jenkins Admin` is the original admin account but is no longer reachable using the GitHub OAuth Plugin\n- Group: `RENCI-NRIG` is a GitHub Organization reflected as a Group for any users who belong to that organization and is being used to set **Job** based authorizations within Jenkins\n\n**Reference**: \n\n- Documentation: [https://plugins.jenkins.io/github-oauth/](https://plugins.jenkins.io/github-oauth/)\n- GitHub: [https://github.com/jenkinsci/github-oauth-plugin](https://github.com/jenkinsci/github-oauth-plugin)\n\n## \u003ca name=\"teardown\"\u003e\u003c/a\u003eTeardown\n\nFor a complete teardown all containers must be stopped and removed along with the volumes and network that were created for the application containers\n\nCommands\n\n```console\ndocker-compose stop\ndocker-compose rm -fv\ndocker-network rm cicd-jenkins\n# removal calls may require sudo rights depending on file permissions\nrm -rf ./jenkins_home\nrm -rf ./logs\n```\n\nExpected output\n\n```console\n$ docker-compose stop\n[+] Running 2/2\n ⠿ Container cicd-nginx    Stopped                                                                                                     0.9s\n ⠿ Container cicd-jenkins  Stopped                                                                                                     1.0s\n$ docker-compose rm -fv\nGoing to remove cicd-nginx, cicd-jenkins\n[+] Running 2/0\n ⠿ Container cicd-jenkins  Removed                                                                                                     0.0s\n ⠿ Container cicd-nginx    Removed                                                                                                     0.0s\n$ docker network rm cicd-jenkins\ncicd-jenkins\n$ rm -rf ./jenkins_home\n$ rm -rf ./logs\n```\n\n## \u003ca name=\"references\"\u003e\u003c/a\u003eReferences\n\n- Jenkins Docker images: [https://github.com/jenkinsci/docker](https://github.com/jenkinsci/docker)\n- Jenkins Documentation: [https://www.jenkins.io/doc/](https://www.jenkins.io/doc/)\n- Docker Documentation: [https://docs.docker.com](https://docs.docker.com)\n\n---\n\n## \u003ca name=\"notes\"\u003e\u003c/a\u003eNotes\n\nGeneral information regarding standard Docker deployment of Jenkins for reference purposes\n\n### Host volume mounts\n\nThe provided configuration creates two host volume mounts that may require some permissions adjustments to work correctly.\n\n1. `${JENKINS_LOCAL_HOME}:/var/jenkins_home` - Maps the `/var/jenkins_home` directory inside the `jenkins` container to the Docker volume identified by `${JENKINS_LOCAL_HOME}`. Other Docker containers controlled by this Docker container’s Docker daemon can mount data from Jenkins (e.g. the Nginx container).\n\n    Generally speaking it is suggested to set the jenkins user UID and GID values to that of the user running the application.\n    \n    ```console\n    $ id -u\n    1011\n    $ id -g\n    1011\n    ```\n    \n    Then in the `.env` file set\n    \n    ```ini\n    ...\n    export JENKINS_UID=1011\n    export JENKINS_GID=1011\n    ...\n    ```\n\n2. `${NGINX_LOGS}:/var/log/nginx` - Maps the `/var/log/nginx` directory inside the `nginx` container to the Docker volume identified by `${NGINX_LOGS}`\n\n    There is no easy to change user UID/GID flag in Nginx, you either need to rebuild the Docker image with a custom UID/GID set, or just accept the log output as it is and use a privileged account to modify the files if needed.\n\n### Deploy with /jenkins prefix\n\nAt times it is desirable to run Jenkins at a non-root URL such as [https://127.0.0.1:8443/jenkins]()\n\nThis can be achieved by adjusting a few parameters\n\n1. Modify the `docker-compose.yml` file to include in `JENKINS_OPTS`\n\n    ```yaml\n    ...\n      jenkins:\n        # default ports 8080, 50000 - expose mapping as needed to host\n        build:\n          context: ./jenkins\n          dockerfile: Dockerfile\n        container_name: cicd-jenkins\n        restart: unless-stopped\n        networks:\n          - jenkins\n        ports:\n          - \"50000:50000\"\n        environment:\n          # Uncomment JENKINS_OPTS to add prefix: e.g. https://127.0.0.1:8443/jenkins\n          - JENKINS_OPTS=\"--prefix=/jenkins\"  # \u003c-- Uncomment this line\n          - JENKINS_UID=${JENKINS_UID}\n          - JENKINS_GID=${JENKINS_GID}\n        volumes:\n          - ${JENKINS_LOCAL_HOME}:/var/jenkins_home\n          - ${HOST_DOCKER_SOCK}:/var/run/docker.sock\n    ```\n\n2. Modify `.env` to use the `nginx/prefix_jenkins.conf` file instead of `nginx/default.conf`\n\n    ```ini\n    ...\n    # Nginx Settings\n    export NGINX_CONF=./nginx/prefix_jenkins.conf\n    export NGINX_SSL_CERTS=./ssl\n    export NGINX_LOGS=./logs/nginx\n    ```\n\n3. Follow the **Deploy** instructions from above\n\n### Let's Encrypt SSL Certificate\n\nUse: [https://github.com/RENCI-NRIG/ez-letsencrypt](https://github.com/RENCI-NRIG/ez-letsencrypt) - A shell script to obtain and renew [Let's Encrypt](https://letsencrypt.org/) certificates using Certbot's `--webroot` method of [certificate issuance](https://certbot.eff.org/docs/using.html#webroot).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjstealey%2Fjenkins-nginx-docker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjstealey%2Fjenkins-nginx-docker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjstealey%2Fjenkins-nginx-docker/lists"}