オンプレGitLab PagesをDockerで構築する方法

こちら のQiitaの投稿を読みまして、 GitLab Pagesを使えばドキュメントのバージョン管理ができる!しかもMarkdownで!ええやん!と思いましたので構築してみました。

投稿ではSaaS版を使っているようですが、オンプレ好きなので自前で構築します。
以前こちら の投稿でコンテナでGitLabを構築しましたのでそれをベースに機能追加してみます。
ただし、GitLabはバージョンを12.7.6にアップデートしています。


2021/7/19 更新
アクセス制御を有効化する場合はこちら をご確認ください


GitLab Pages有効化

sameersbnのGitLabはデフォルトでOFFになっているので、まずGitLab Pagesを有効化します。
docker-compose.ymlのGitLabのenvironmentに以下の設定を追記してください。
ドメインやポート番号は各自の環境に変更してくださいね。

    environment:
    - GITLAB_PAGES_ENABLED=true
    - GITLAB_PAGES_DOMAIN=tsuchinokometal.com
    - GITLAB_PAGES_PORT=18080
    - GITLAB_PAGES_EXTERNAL_HTTP=:18080

また、portsにも追記します。

    ports:
    - "18080:18080"

追記しましたらGitLabコンテナを再作成して設定を反映します。
起動後にAdmin Areaを見るとGitlab Pagesが有効化していると思います。

gitlab_pages_001.png

GitLab Runnerの登録

GitLab PagesはGitLab CIでデプロイするのですが、その際GitLab Runnerが必要らしいです。
というわけでコンテナを追加します。
(手順はこちら を参考にさせていただきました)
docker-compose.ymlに以下を追記してください。
ここでvolumesにしているcertsフォルダに前回作成した自己証明書がありますので、それを使います。

  runner:
    restart: always
    image: gitlab/gitlab-runner:v12.9.0-rc1
    container_name: runner
    volumes:
      - gitlab-runner:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
      - ./certs:/etc/ssl/certs

起動します。

[centos@centos gitlab]$ docker-compose up -d runner

起動後、コンテナにログインしてGitLabに登録します。
入力内容は参考にさせていただいたサイト様の通りです。

[centos@centos gitlab]$ docker exec -it runner bash
root@156d87b14de0:/# gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=30 revision=a350f628 version=12.9.0-rc1
Running in system-mode.                            
                                                   
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://example.tsuchinokometal.com/gitlab/
Please enter the gitlab-ci token for this runner:
XXXXXXXXXXXXXXXXXXXX
Please enter the gitlab-ci description for this runner:
[156d87b14de0]: 
Please enter the gitlab-ci tags for this runner (comma separated):
runner01
Registering runner... succeeded                     runner=EJr1a19y
Please enter the executor: docker-ssh+machine, docker-ssh, parallels, shell, ssh, docker+machine, custom, docker, virtualbox, kubernetes:
docker
Please enter the default Docker image (e.g. ruby:2.6):
ruby:2.6
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 

この時、以下のエラーのようにGitLabとの通信がうまくいかなかった場合、
Dockerを起動してるホストのファイヤーウォールを疑ってください。

ERROR: Registering runner... failed                 runner=EJr1a19y status=couldn't execute POST against https://example.tsuchinokometal.com/gitlab/api/v4/runners: Post https://example.tsuchinokometal.com/gitlab/api/v4/runners: dial tcp 192.168.100.4:443: connect: no route to host
PANIC: Failed to register this runner. Perhaps you are having network problems 

GitLab自体にはhttpsで繋がるので予想外でハマりました。
とりあえずファイヤーウォールを止めて進めたのですが、どう設定すればいいのか知っている方がいたら教えて欲しいです。
あとファイヤーウォールをいじったらDockerも再起動する必要があるみたいです。
止めた途端コンテナが外部ネットワークと通信できなくなって普通逆じゃね!?とこれにもハマりました。

無事登録できたら、Admin AreaのRunnersに表示されていると思います。

gitlab_pages_002.png

ここで、鉛筆っぽいマークでEdit画面に入って、「Run untagged jobs」にチェックを入れてください。

gitlab_pages_003.png

チェックを入れないとあとの手順でジョブがpenddingのまま進まなくなります。

Hugoプロジェクト作成

ここの手順はこちらとほぼ一緒ですね。
まずGitLab上で空のプロジェクトを作成します。
おそらく管理しやすいんじゃないかと思ったので、pagesグループを作成してそこにプロジェクトを作成しました。

gitlab_pages_004.png

では、Hugoサイトを構築していきます。

% git clone ssh://git@example.tsuchinokometal.com:10022/pages/hugo-sample.git
% cd hugo-sample
% hugo new site . --force
Congratulations! Your new Hugo site is created in /Users/kentaro/work/hugo-sample.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
   Choose a theme from https://themes.gohugo.io/ or
   create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
   with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.
% git submodule add https://github.com/vjeantet/hugo-theme-docdock.git themes/docdock
% git submodule init
% git submodule update
% cp -r themes/docdock/exampleSite/* .

config.tomlはひとまず以下の3行を変更します。

baseURL = "http://pages.tsuchinokometal.com:18080/hugo-sample/"
theme = "docdock"
# themesdir = "../.."

続いてリポジトリ直下に.gitlab-ci.ymlを作成します。

% vi .gitlab-ci.yml

こちらも丸パクリで行けました。

image: registry.gitlab.com/pages/hugo:latest

variables:
  GIT_SUBMODULE_STRATEGY: recursive

pages:
  stage: deploy
  environment: production
  script:
  - hugo
  artifacts:
    paths:
    - public

プッシュしたらCI/CDのJobsを確認してみてください。

gitlab_pages_005.png

runningしてるジョブがあると思います。
ジョブを選択して以下のようにJob succeededと表示されれば成功です。

gitlab_pages_006.png

うまく動かない場合はエラー内容を確認してGitLab Runnerの設定かソースを修正してください。

SettingsのPagesをクリックするとAccess pagesにリンクがあります。

gitlab_pages_007.png

今回の例でいうと「http://pages.tsuchinokometal.com:18080/hugo-sample」ですね。
しかし、見ての通りpages.tsuchinokometal.comの名前解決ができないとアクセスできません。
GitLabと同じサーバーにデプロイされていますので、hostsなどで追記してアクセスできるようにしてください。
問題なければ以下のように表示されると思います。

gitlab_pages_008.png

GitLab Pagesに自己証明書でHTTPSアクセス

以上の手順でGitLab Pagesが使えるようになりましたがhttp通信です。
せっかくGitLab自体がhttpsなのに残念な感じです。
というわけでオレオレ証明書ですがhttpsにしたいと思います。

今回の環境ではnginxのリバースプロキシでhttpsにしているのでそこに設定を追加します。

[centos@centos gitlab]$ vi conf.d/ssl.conf

以下の内容を追記します。
GitLabをhttpsにした部分のほぼコピペですね。

server {
    root /dev/null;
    server_name pages.tsuchinokometal.com;
    charset UTF-8;

    listen *:443 ssl http2;
    ssl_certificate /certs/server.crt;
    ssl_certificate_key /certs/server.key;

    ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4';
    ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache  builtin:1000  shared:SSL:10m;
    ssl_session_timeout  5m;

    client_max_body_size 0;
    chunked_transfer_encoding on;

    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;
    proxy_set_header  X-Forwarded-Proto $scheme;
    proxy_read_timeout                  900;

    location / {
        proxy_pass http://gitlab:18080;
    }
}
server {
    listen *:80;
    server_name  pages.tsuchinokometal.com;
    server_tokens off;
    return 301 https://$http_host:$request_uri;
}

追記したらnginxを再起動して設定を反映させてください。
また、config.tomlも書き換えます。

baseURL = "https://pages.tsuchinokometal.com/hugo-sample/"
editURL = "https://example.tsuchinokometal.com/gitlab/pages/hugo-sample/edit/master/content/"

config.tomlをプッシュしてジョブが完了したら、
「http://pages.tsuchinokometal.com:18080/hugo-sample」

「https://pages.tsuchinokometal.com/hugo-sample/」
に書き換えてアクセスしてみてください。
httpsでアクセスできると思います。

gitlab_pages_009.png

また、画面下部の「Improve this page」をクリックすると、
編集ページにアクセスできると思います。

gitlab_pages_010.png

結構苦労しましたが、一応使えるようになったのでこれからいろんなテーマとか使ってみたいと思います。
これで会社のExcelドキュメント群を駆逐できるかなぁ。無理かなぁ。

ちなみに今回構築に使用したdocker-compose.ymlは以下の通りです。

version: '3'
 
services:
  redis:
    restart: always
    image: sameersbn/redis:4.0.9-2
    container_name: redis
    command:
    - --loglevel warning
    volumes:
    - redis-data:/var/lib/redis:Z
 
  postgresql:
    restart: always
    image: sameersbn/postgresql:10-2
    container_name: postgresql
    volumes:
    - postgresql-data:/var/lib/postgresql:Z
    environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
    - DB_EXTENSION=pg_trgm

  gitlab:
    restart: always
    image: sameersbn/gitlab:12.7.6
    container_name: gitlab
    depends_on:
    - redis
    - postgresql
    ports:
    - "10080:80"
    - "10022:22"
    - "18080:18080"
    volumes:
    - gitlab-data:/home/git/data:Z
    - ./certs:/certs
    environment:
    
    - GITLAB_PAGES_ENABLED=true
    - GITLAB_PAGES_DOMAIN=tsuchinokometal.com
    - GITLAB_PAGES_PORT=18080
    - GITLAB_PAGES_EXTERNAL_HTTP=:18080

    - GITLAB_REGISTRY_ENABLED=true
    - GITLAB_REGISTRY_HOST=example.tsuchinokometal.com
    - GITLAB_REGISTRY_PORT=443
    - GITLAB_REGISTRY_API_URL=http://registry:5000
    - GITLAB_REGISTRY_KEY_PATH=/certs/server.key
 
    - DEBUG=false
 
    - DB_ADAPTER=postgresql
    - DB_HOST=postgresql
    - DB_PORT=5432
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
 
    - REDIS_HOST=redis
    - REDIS_PORT=6379
 
    - TZ=Asia/Tokyo
    - GITLAB_TIMEZONE=Tokyo
 
    - GITLAB_HTTPS=true
    - SSL_SELF_SIGNED=false
 
    - GITLAB_HOST=example.tsuchinokometal.com
    - GITLAB_PORT=
    - GITLAB_SSH_PORT=10022
    - GITLAB_RELATIVE_URL_ROOT=/gitlab
    - GITLAB_SECRETS_DB_KEY_BASE=Nz7kgKFT9CzgscN7Wzj9chCp3KRk77ghr4wqmTHbdRxWw44Kmc9WpvPqfjFhkXM7
    - GITLAB_SECRETS_SECRET_KEY_BASE=hPFsKkX4kqftKJpMwgnpvnqKwqsWmkfPsN3F4xTCbTghJ77qvnxdFkxkt3XX3PFT
    - GITLAB_SECRETS_OTP_KEY_BASE=HXWdMCLhkWwLLMCnJLNK4sLhPk9VsskrvJpppCFfhRhfb9fMd9hdqWJp9tgCXXvz
 
    - GITLAB_ROOT_PASSWORD=
    - GITLAB_ROOT_EMAIL=
 
    - GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
    - GITLAB_NOTIFY_PUSHER=false
 
    - GITLAB_EMAIL=notifications@example.com
    - GITLAB_EMAIL_REPLY_TO=noreply@example.com
    - GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com
 
    - GITLAB_BACKUP_SCHEDULE=daily
    - GITLAB_BACKUP_TIME=01:00
 
    - SMTP_ENABLED=false
    - SMTP_DOMAIN=www.example.com
    - SMTP_HOST=smtp.gmail.com
    - SMTP_PORT=587
    - SMTP_USER=mailer@example.com
    - SMTP_PASS=password
    - SMTP_STARTTLS=true
    - SMTP_AUTHENTICATION=login
 
    - IMAP_ENABLED=false
    - IMAP_HOST=imap.gmail.com
    - IMAP_PORT=993
    - IMAP_USER=mailer@example.com
    - IMAP_PASS=password
    - IMAP_SSL=true
    - IMAP_STARTTLS=false
 
    - OAUTH_ENABLED=false
    - OAUTH_AUTO_SIGN_IN_WITH_PROVIDER=
    - OAUTH_ALLOW_SSO=
    - OAUTH_BLOCK_AUTO_CREATED_USERS=true
    - OAUTH_AUTO_LINK_LDAP_USER=false
    - OAUTH_AUTO_LINK_SAML_USER=false
    - OAUTH_EXTERNAL_PROVIDERS=
 
    - OAUTH_CAS3_LABEL=cas3
    - OAUTH_CAS3_SERVER=
    - OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false
    - OAUTH_CAS3_LOGIN_URL=/cas/login
    - OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate
    - OAUTH_CAS3_LOGOUT_URL=/cas/logout
 
    - OAUTH_GOOGLE_API_KEY=
    - OAUTH_GOOGLE_APP_SECRET=
    - OAUTH_GOOGLE_RESTRICT_DOMAIN=
 
    - OAUTH_FACEBOOK_API_KEY=
    - OAUTH_FACEBOOK_APP_SECRET=
 
    - OAUTH_TWITTER_API_KEY=
    - OAUTH_TWITTER_APP_SECRET=
 
    - OAUTH_GITHUB_API_KEY=
    - OAUTH_GITHUB_APP_SECRET=
    - OAUTH_GITHUB_URL=
    - OAUTH_GITHUB_VERIFY_SSL=
 
    - OAUTH_GITLAB_API_KEY=
    - OAUTH_GITLAB_APP_SECRET=
 
    - OAUTH_BITBUCKET_API_KEY=
    - OAUTH_BITBUCKET_APP_SECRET=
 
    - OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=
    - OAUTH_SAML_IDP_CERT_FINGERPRINT=
    - OAUTH_SAML_IDP_SSO_TARGET_URL=
    - OAUTH_SAML_ISSUER=
    - OAUTH_SAML_LABEL="Our SAML Provider"
    - OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient
    - OAUTH_SAML_GROUPS_ATTRIBUTE=
    - OAUTH_SAML_EXTERNAL_GROUPS=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_USERNAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=
 
    - OAUTH_CROWD_SERVER_URL=
    - OAUTH_CROWD_APP_NAME=
    - OAUTH_CROWD_APP_PASSWORD=
 
    - OAUTH_AUTH0_CLIENT_ID=
    - OAUTH_AUTH0_CLIENT_SECRET=
    - OAUTH_AUTH0_DOMAIN=
    - OAUTH_AUTH0_SCOPE=
 
    - OAUTH_AZURE_API_KEY=
    - OAUTH_AZURE_API_SECRET=
    - OAUTH_AZURE_TENANT_ID=

  nginx:
    image: nginx
    container_name: nginx
    volumes:
      - ./conf.d:/etc/nginx/conf.d
      - ./certs:/certs
    ports:
      - "80:80"
      - "443:443"
 
  registry:
    restart: always
    image: registry:2
    container_name: registry
    expose:
      - "5000"
    ports:
      - "5000:5000"
    volumes:
      - registry-data:/registry
      - ./certs:/certs
    environment:
      - REGISTRY_LOG_LEVEL=info
      - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/registry
      - REGISTRY_AUTH_TOKEN_REALM=https://example.tsuchinokometal.com/gitlab/jwt/auth
      - REGISTRY_AUTH_TOKEN_SERVICE=container_registry
      - REGISTRY_AUTH_TOKEN_ISSUER=gitlab-issuer
      - REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/certs/server.crt
      - REGISTRY_STORAGE_DELETE_ENABLED=true

  runner:
    restart: always
    image: gitlab/gitlab-runner:v12.9.0-rc1
    container_name: runner
    volumes:
      - gitlab-runner:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
      - ./certs:/etc/ssl/certs

volumes:
  redis-data:
  postgresql-data:
  gitlab-data:
  registry-data:
  gitlab-runner: