オンプレGitLabでgit+CI+npmサーバー2024 の履歴(No.5)
更新自前サーバーで GitLab を動かしてプライベートな npm プロジェクトなどを置きたい†
GitLab は、
- GitHub のように使える git 利用開発支援機能
- テストやビルドやデプロイを自動化する CI サーバー機能
- npm パッケージサーバー機能
など、さまざまな機能を兼ね備えるフリーソフト。
自前のサーバーにインストールして動かせる。
GitLab を動かすには 4GB 以上のメモリが必要で、しばらく前だと二の足を踏んでいたのだけれど今なら軽いはず。
Docker を使ってサクッと動かす。(動かせるといいな)
目次†
GitLab サーバーを docker compose で動かす†
https://gitlab-docs.creationline.com/ee/install/docker.html#install-gitlab-using-docker-compose
を見ながら docker イメージで動作するよう設定する。
- ホストサーバーには docker 環境があって、自分が管理者である
- gitlab は docker 内で動かす
- ホストサーバーには apache2 が https://myserver.com/ への通信を受け付ける状況になっている
- https://myserver.com/gitlab/ というアドレスへの通信を docker 内の gitlab サーバーへ繋ぐ
という形で GitLab を動かします。
LANG:console $ cd ~ $ mkdir gitlab $ cd gitlab $ echo GITLAB_HOME=`pwd` > .env $ cat <<"EOS" > docker-compose.yml services: web: image: 'gitlab/gitlab-ce:latest' restart: always environment: GITLAB_OMNIBUS_CONFIG: | external_url 'https://myserver.com/gitlab' nginx['listen_port'] = 80 nginx['listen_https'] = false gitlab_rails['gitlab_shell_ssh_port'] = 2224 ports: - '8980:80' volumes: - '$GITLAB_HOME/etc:/etc/gitlab' - '$GITLAB_HOME/log:/var/log/gitlab' - '$GITLAB_HOME/data:/var/opt/gitlab' shm_size: '256m' EOS $ docker compose up -d [+] Running 10/10 ✔ web Pulled 58.2s ✔ 857cc8cb19c0 Pull complete 2.1s ✔ 28812802a434 Pull complete 2.1s ✔ 54e2e989e54c Pull complete 3.0s ✔ abb7892b26dc Pull complete 3.0s ✔ e9d667f5a8c1 Pull complete 3.0s ✔ a8891519352d Pull complete 3.1s ✔ 8b624a00a604 Pull complete 3.1s ✔ 0cf3370d74b6 Pull complete 3.1s ✔ 3253094bd895 Pull complete 55.9s [+] Running 2/2 ✔ Network gitlab_default Created 0.0s ✔ Container gitlab-web-1 Started 0.7s
これで docker 内で GitLab サーバーが立ち上がる。
全体としての注意†
上記のようにして動かすと、etc/ フォルダに etc/gitlab.rb というのができて、 これを書き換えれば設定を変えられる。
設定項目についてはこちらに説明がある。
https://gitlab-docs.creationline.com/omnibus/settings/configuration.html
また、ファイルの冒頭には以下の注意書きがある。
## GitLab configuration settings ##! This file is generated during initial installation and **is not** modified ##! during upgrades. ##! Check out the latest version of this file to know about the different ##! settings that can be configured, when they were introduced and why: ##! https://gitlab.com/gitlab-org/omnibus-gitlab/blame/master/files/gitlab-config-template/gitlab.rb.template ##! Locally, the complete template corresponding to the installed version can be found at: ##! /opt/gitlab/etc/gitlab.rb.template ##! You can run `gitlab-ctl diff-config` to compare the contents of the current gitlab.rb with ##! the gitlab.rb.template from the currently running version. ##! You can run `gitlab-ctl show-config` to display the configuration that will be generated by ##! running `gitlab-ctl reconfigure` ##! In general, the values specified here should reflect what the default value of the attribute will be. ##! There are instances where this behavior is not possible or desired. For example, when providing passwords, ##! or connecting to third party services. ##! In those instances, we endeavour to provide an example configuration. ## GitLab URL ##! URL on which GitLab will be reachable. ##! For more details on configuring external_url see: ##! https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab ##! ##! Note: During installation/upgrades, the value of the environment variable ##! EXTERNAL_URL will be used to populate/replace this value. ##! On AWS EC2 instances, we also attempt to fetch the public hostname/IP ##! address from AWS. For more details, see: ##! https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html # external_url 'GENERATED_EXTERNAL_URL' ## Roles for multi-instance GitLab ##! The default is to have no roles enabled, which results in GitLab running as an all-in-one instance. ##! Options: ##! redis_sentinel_role redis_master_role redis_replica_role geo_primary_role geo_secondary_role ##! postgres_role consul_role application_role monitoring_role ##! For more details on each role, see: ##! https://docs.gitlab.com/omnibus/roles/index.html#roles ##! # roles ['redis_sentinel_role', 'redis_master_role'] ## Legend ##! The following notations at the beginning of each line may be used to ##! differentiate between components of this file and to easily select them using ##! a regex. ##! ## Titles, subtitles etc ##! ##! More information - Description, Docs, Links, Issues etc. ##! Configuration settings have a single # followed by a single space at the ##! beginning; Remove them to enable the setting. ##! **Configuration settings below are optional.**
一方、例えば data/nginx/conf/gitlab-http.conf に nginx 関連の設定ファイルが見つかるのだけれど、 こちらの設定ファイルはサーバーを立ち上げ直すと gitlab.rb の内容を元に自動的に生成されるものなので、 手で書きかえてはいけない。
ちゃんと冒頭に
# This file is managed by gitlab-ctl. Manual changes will be # erased! To change the contents below, edit /etc/gitlab/gitlab.rb # and run `sudo gitlab-ctl reconfigure`.
などと書かれている。
etc/gitlab.rb を書き換えてしまうと設定情報が docker-compose.yml と gitlab.rb とに分かれてしまうので、どちらか一方にまとめた方がいいのかもしれない。
単純な見やすさからすると docker-compose.yml に書く方が良さそうなのだけれど、 gitlab-ctl diff-config を使うなら gitlab.rb でもいいのかもしれない。
docker コンテナの外から確認するなら:
LANG:console $ docker compose exec web gitlab-ctl diff-config
ポートの指定†
外からの接続を受ける apache2 と同じマシンに置くのであれば docker-compose.yml の
ports: - '8980:80'
のところは
ports: - '127.0.0.1:8980:80'
として、外からの接続が直接 docker へ行かないようにする。
docker でポートを開けると ufw などのファイアウォールで許可してなくても 外向きにポートが開いてしまうので十分注意する。
https を名乗りつつ http で待ち受ける†
gitlab の設定で
GITLAB_OMNIBUS_CONFIG: | external_url 'https://myserver.com/gitlab' nginx['listen_port'] = 80 nginx['listen_https'] = false
としている理由は以下の通り。
この docker イメージは external_url の設定を見て、内部の nginx で 80 番で http を待つか、443 番で https を待つかを決めている。
「どちらか片方しか有効にならない」というのが重要な点。
今実現したい構成では、外部から見た gitlab サーバーのアドレスは https://myserver.com/gitlab で https 接続になるのだけれど、その暗号化通信は間に入る apache2 が受け持つので docker 内の nginx への接続は http になる。
external_url を https としてしまうと gitlab docker は nginx を 443 番で https を待つように設定してしまい 80 番の http では繋がらなくなってしまう。
そこで 80 番で http を待つように設定しているのがこの部分だ。
サーバーに繋ぎに行って「接続をリセットされました」みたいになるときは、
LANG:console $ sudo less data/nginx/conf/gitlab-http.conf
として gitlab 関連の nginx の設定を確かめるといい。
(これに気付くのにかなり時間がかかりました・・・)
GITLAB_OMNIBUS_CONFIG で指定可能なその他の設定†
GITLAB_OMNIBUS_CONFIG では
LANG:console $ sudo less etc/gitlab.rb
として表示される設定項目に値を指定できるので、 「こんなことできないのかな」と思ったときにはじっくり読むといい。
apache2 をプロキシサーバーとして接続を中継させる†
ホストマシンの /etc/apache2/sites-enabled/default-ssl.conf に
<IfModule mod_proxy.c> ProxyRequests Off <Proxy *> Require all granted </Proxy> AllowEncodedSlashes NoDecode <Location /gitlab> Order deny,allow Allow from all </Location> RequestHeader set X_FORWARDED_PROTO 'https' ProxyPass /gitlab http://localhost:8980/gitlab ProxyPassReverse /gitlab http://localhost:8980/gitlab </IfModule>
と設定して、
LANG:console $ sudo a2enmod proxy $ sudo service apache2 reload
とすることで apache2 がプロキシサーバーとして振る舞い、 https://myserver.com/gitlab 以下へのアクセスを http://localhost:8929/gitlab へ転送してくれる。
ここで重要なのが AllowEncodedSlashes NoDecode だ。
これをしておかないと、後々 GitLab を npm パッケージサーバーとして使おうとした際に、パッケージリポジトリへの PUT が 404 で失敗する。
LANG: console $ npm publish # 他の設定が終わってからの話 ... npm error code E404 npm error 404 Not Found - PUT https://myserver.com/gitlab/api/v4/projects/1/packages/npm/@myscope%2fmypackage npm error 404 npm error 404 '@myscope/mypackage@0.0.1' is not in this registry. npm error 404 npm error 404 Note that you can also install from a npm error 404 tarball, folder, http url, or git url.
のように、npm publish で認証は通過しているのに、そして、アップロードしようとしているのに 404 で落ちるていたらこの設定を見直すといい。
メールを送れるように設定する†
GITLAB_OMNIBUS_CONFIG に
gitlab_rails['gitlab_email_from'] = 'gitlab@myserver.com' gitlab_rails['gitlab_email_display_name'] = 'GitLab' gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = "smtp.server" gitlab_rails['smtp_port'] = 465 gitlab_rails['smtp_user_name'] = "smtp user" gitlab_rails['smtp_password'] = "smtp password" gitlab_rails['smtp_domain'] = "example.com" gitlab_rails['smtp_authentication'] = "login" gitlab_rails['smtp_enable_starttls_auto'] = true gitlab_rails['smtp_tls'] = false gitlab_rails['smtp_pool'] = false
あたりを追加する。
設定の仕方はこちらを参照:
https://gitlab-docs.creationline.com/omnibus/settings/smtp.html
root でログインする†
初期設定で root という管理者ユーザーが登録されているので、 ウェブサーバーから https://myserver.com/gitlab へアクセスして root でログインする。
管理者 root の初期パスワードは gitlab の docker-compose.yml を作ったフォルダの下の etc フォルダを調べるとわかる。
LANG:console $ sudo cat etc/initial_root_password
自分で変更した root のパスワードを忘れてしまった場合†
にあるように、
LANG:console $ docker compose exec web gitlab-rake "gitlab:password:reset" Enter username: root Enter password: Confirm password: Password successfully updated for user with username root.
とすればパスワードを設定しなおせるらしい。
GitLab Runner も docker で動かす†
同時に使用する人数と比較するとこのサーバーには余裕があるので、 CI サーバーも同じホストで動かしてしまう。
先の docker-compose.yml に以下を追加する。
runner: image: 'gitlab/gitlab-runner:latest' restart: unless-stopped volumes: - '$GITLAB_HOME/runner:/etc/gitlab-runner' - /var/run/docker.sock:/var/run/docker.sock ports: - '8093:8093'
そして、
LANG:console $ sudo docker compose up -d
runner を GitLab に追加する†
GitLab 画面で新しい Runner インスタンスを作成†
https://myserver.com/gitlab/admin/runners
から右上の [New Instance Runner] を押す。
ここでは特別な設定をしないごく一般的な shell の動くサーバーを建てるので、
x Run untagged jobs のチェックを付けて [Create runner]
docker で動かした Runner と対応付ける†
次の画面の Step 1 となっているところで
$ gitlab-runner register --url https://myserver.com/gitlab --token glrt-iqghvxb-GLHJG9WsFPT6
のようなところをコピーする。
ちょっと手直しをして次の形にして Runnner を起動した docker-compose.yml のあるフォルダで実行。
$ docker compose exec runner \ gitlab-runner register \ --url https://myserver.com/gitlab \ --token glrt-iqghvxb-GLHJG9WsFPT6
コマンドを起動するといくつか質問に答えることになる。
- GitLab instance URL には指定した https://myserver.com/gitlab が入っているのでそのまま ENTER
- Enter a name for the runner にはこの Runner を識別する名前を付ける
- Enter an executor には shell を指定
これで Runner 一覧に正しく追加される。
CI 動作を試してみる†
LANG: console $ mkdir ~/gitlab-ci-hello $ cd ~/gitlab-ci-hello $ cat <<"EOS" > .gitlab-ci.yml build: script: - echo hello `pwd` - ls -la EOS $ git init $ git add . $ git commit -m "Initial commit"
として .gitlab-ci.yml だけをコミットした git リポジトリを作成する。
GitLab 上でブランクプロジェクトを作ってそこへコミットしてみる。
https://myserver.com/gitlab/projects/new#blank_project
- Project name: gitlab-ci-hello
- Project url: https://myserver.com/gitlab/myname/gitlab-ci-hello
- Visibility Level: private
- Project Configuration: README のチェックを外す
そして Create Project
次のページの Push an existing Git repository の手順で push する。
LANG:console $ git remote add origin https://myserver.com/gitlab/myname/gitlab-ci-hello.git $ git push --set-upstream origin --all Username for 'https://myserver.com': myname Password for 'https://myname@myserver.com': xxxxxx Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Delta compression using up to 4 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 266 bytes | 266.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 To https://myserver.com/gitlab/myname/gitlab-ci-hello.git * [new branch] master -> master branch 'master' set up to track 'origin/master'. $ git push --set-upstream origin --tags Username for 'https://myserver.com': myname Password for 'https://myname@myserver.com': xxxxxx Everything up-to-date
push 時には gitlab サーバーのユーザー名とパスワードを聞かれるので入力する。
GitLab の画面で確認すると、
こちらのようにコミット番号の隣に緑のチェックマークがついて、 ジョブが成功したことを確認できる。
このチェックをクリックして中を見ると、
LANG:console Running with gitlab-runner 17.3.1 (66269445) on myrunnner1 t2X9wkLjw, system ID: r_FoHQflE05Zou Preparing the "shell" executor 00:00 Using Shell (bash) executor... Preparing environment 00:00 Running on 8163caea6de5... Getting source from Git repository 00:00 Fetching changes with git depth set to 20... Initialized empty Git repository in /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/myname/gitlab-ci-hello/.git/ Created fresh repository. Checking out cc71a4d9 as detached HEAD (ref is master)... Skipping Git submodules setup Executing "step_script" stage of the job script 00:00 $ echo hello `pwd` hello /home/gitlab-runner/builds/t2X9wkLjw/0/gitlab/myname/gitlab-ci-hello $ ls -la total 16 drwxrwxr-x 3 gitlab-runner gitlab-runner 4096 Sep 7 13:03 . drwxrwxr-x 4 gitlab-runner gitlab-runner 4096 Sep 7 13:03 .. drwxrwxr-x 6 gitlab-runner gitlab-runner 4096 Sep 7 13:03 .git -rw-rw-r-- 1 gitlab-runner gitlab-runner 53 Sep 7 13:03 .gitlab-ci.yml Cleaning up project directory and file based variables 00:00 Job succeeded
のようにして、
LANG:console $ echo hello `pwd`
と
LANG:console $ ls -la
が正しく実行されていることを確認できる。
ワーキングフォルダが /home/gitlab-runner の下にあることからもわかるとおり、 このシェルは gitlab-runner というユーザー権限で実行される。
そのままでは sudo は使えないので、システムに変更を加えるようなコマンドは実行できない。
Runner の Dockerfile はこちらにある:
https://hub.docker.com/r/gitlab/gitlab-runner/dockerfile
中身はものすごく古い ubuntu を元にしている?
なんでこんなに古いんだろう???
CI スクリプトの書き方†
概要:
https://gitlab-docs.creationline.com/ee/ci/yaml/gitlab_ci_yaml.html
リファレンス:
https://gitlab-docs.creationline.com/ee/ci/yaml/index.html
用語の整理:
- パイプラインは複数のステージから構成される
- 個々のステージは並列実行可能な複数のジョブから構成される
- 個々のステージは前のステージのジョブがすべて成功してから次へ進む