dockerにJenkinsを構築してHTTPS化してみた

https://jenkins.example.comとなるようにjenkinsを構築します。
osはCentOS Streamです。

dockerのインストール

https://docs.docker.com/engine/install/centos/

docker-composeのインストール

https://docs.docker.com/compose/install/

dockerコマンドをsudoなしで実行できるようにする

https://qiita.com/DQNEO/items/da5df074c48b012152ee

docker-composeをsudoなしで実行できるようにする

$ sudo visudo
	
// :/usr/local/binを追加します
$ Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin

Certbotを使用してSSL証明書を発行

docker-compose.yml

version: '3'
services:
  nginx:
    image: nginx:1.21-alpine
    restart: unless-stopped
    volumes:
      - ./data/nginx:/etc/nginx/conf.d
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/jenkins:/var/www/certbot
    ports:
      - "80:80"
      - "443:443"
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
  certbot:
    image: certbot/certbot
    restart: unless-stopped
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/jenkins:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $${!}; done;'"

data/nginx/nginx.conf

server {
    listen 80;
    server_name jenkins.example.com;
    server_tokens off;

    proxy_connect_timeout       600;
    proxy_send_timeout          600;
    proxy_read_timeout          600;
    send_timeout                600;

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /var/www/certbot;
    }

    location / {
        if ($http_x_forwarded_proto = "http") {
            return 301 https://$host$request_uri;
        }
    }
}

server {
    listen 443 ssl;
    server_name jenkins.example.com;
    server_tokens off;

    ssl_certificate /etc/letsencrypt/live/jenkins.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/jenkins.example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / {
        proxy_pass  http://jenkins.example.com;
        proxy_set_header    Host                $http_host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    }
}

証明書の発行

下記を参考にしました。

https://pentacent.medium.com/nginx-and-lets-encrypt-with-docker-in-less-than-5-minutes-b4b8a60d3a71

# 推奨されるTLSパラメーターをダウンロード
mkdir -p data/certbot/conf
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot-nginx/certbot_nginx/_internal/tls_configs/options-ssl-nginx.conf > data/certbot/conf/options-ssl-nginx.conf
curl -s https://raw.githubusercontent.com/certbot/certbot/master/certbot/certbot/ssl-dhparams.pem > data/certbot/conf/ssl-dhparams.pem

# ダミー証明書を作成
mkdir -p data/certbot/conf/live/jenkins.example.com

docker-compose run --rm --entrypoint "\
  openssl req -x509 -nodes -newkey rsa:4096 -days 1\
    -keyout "/etc/letsencrypt/live/jenkins.example.com/privkey.pem" \
    -out "/etc/letsencrypt/live/jenkins.example.com/fullchain.pem" \
    -subj '/CN=localhost'" certbot

# nginxを起動
docker-compose up -d nginx

# ダミーの認証情報を削除
docker-compose run --rm --entrypoint "\
  rm -Rf /etc/letsencrypt/live/jenkins.example.com && \
  rm -Rf /etc/letsencrypt/archive/jenkins.example.com && \
  rm -Rf /etc/letsencrypt/renewal/jenkins.example.com.conf" certbot

# Let'sEncrypt証明書を作成
docker-compose run --rm --entrypoint "\
  certbot certonly --webroot -w /var/www/certbot \
    -d jenkins.example.com \
    --register-unsafely-without-email \
    --rsa-key-size 4096 \
    --agree-tos \
    --force-renewal --dry-run" certbot

# nginxをリロード
docker-compose exec nginx nginx -s reload

Jenkinsの構築

data/nginx/nginx.conf

Certbotを使用してSSL証明書を発行した際に使用したnginx.confを以下に書き換えます。

upstream jenkins {
  keepalive 32; # keepalive connections
  server jenkins:8080; # jenkins ip and port
}

# Required for Jenkins websocket agents
map $http_upgrade $connection_upgrade {
  default upgrade;
  '' close;
}

server {
    listen 80;
    server_name jenkins.example.com;
    server_tokens off;

    proxy_connect_timeout       600;
    proxy_send_timeout          600;
    proxy_read_timeout          600;
    send_timeout                600;

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root /var/www/certbot;
    }

    location / {
        if ($http_x_forwarded_proto = "http") {
            return 301 https://$host$request_uri;
        }
    }
}

server {
  listen 443 ssl;

  server_name     jenkins.example.com
  server_tokens off;

  ssl_certificate /etc/letsencrypt/live/jenkins.example.com/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/jenkins.example.com/privkey.pem;
  include /etc/letsencrypt/options-ssl-nginx.conf;
  ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

  # this is the jenkins web root directory
  # (mentioned in the /etc/default/jenkins file)
  root            /var/run/jenkins/war/;

  # pass through headers from Jenkins that Nginx considers invalid
  ignore_invalid_headers off;

  location ~ "^/static/[0-9a-fA-F]{8}\/(.*)$" {
    # rewrite all static files into requests to the root
    # E.g /static/12345678/css/something.css will become /css/something.css
    rewrite "^/static/[0-9a-fA-F]{8}\/(.*)" /$1 last;
  }

  location /userContent {
    # have nginx handle all the static requests to userContent folder
    # note : This is the $JENKINS_HOME dir
    root /var/lib/jenkins/;
    if (!-f $request_filename){
      # this file does not exist, might be a directory or a /**view** url
      rewrite (.*) /$1 last;
      break;
    }
    sendfile on;
  }

  location / {
      sendfile off;
      proxy_pass         http://jenkins;
      proxy_redirect     default;
      proxy_http_version 1.1;

      # Required for Jenkins websocket agents
      proxy_set_header   Connection        $connection_upgrade;
      proxy_set_header   Upgrade           $http_upgrade;

      proxy_set_header   Host              $host;
      proxy_set_header   X-Real-IP         $remote_addr;
      proxy_set_header   X-Forwarded-For   $proxy_add_x_forwarded_for;
      proxy_set_header   X-Forwarded-Proto $scheme;
      proxy_max_temp_file_size 0;

      #this is the maximum upload size
      client_max_body_size       10m;
      client_body_buffer_size    128k;

      proxy_connect_timeout      90;
      proxy_send_timeout         90;
      proxy_read_timeout         90;
      proxy_buffering            off;
      proxy_request_buffering    off; # Required for HTTP CLI commands
      proxy_set_header Connection ""; # Clear for keepalive
  }
}

docker-compose.yml

Certbotを使用してSSL証明書を発行した際に使用した docker-compose.ymlを以下に書き換えます。

version: "3"
services:
  nginx:
    image: nginx:1.21-alpine
    restart: unless-stopped
    volumes:
      - ./data/nginx:/etc/nginx/conf.d
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/jenkins:/var/www/certbot
    ports:
      - "80:80"
      - "443:443"
    command: "/bin/sh -c 'while :; do sleep 77h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
  jenkins:
    image: jenkins/jenkins:lts
    restart: unless-stopped
    ports:
      - "8080:8080"
      - "50000:50000"
    volumes:
      - jenkins_home:/var/jenkins_home
volumes:
  jenkins_home:
networks:
  default:
    external:
      name: "nginx_default" # nginxが使用しているネットワークを指定

nginxで使用しているネットワーク

docker inspect nginx_1 | grep -i network

起動

docker-compose up -d jenkins
docker-compose up --force-recreate -d nginx

未分類

Posted by ababa