これは、なにをしたくて書いたもの?
GitLab Runnerにはrun-singleというコマンドがあります。
GitLab Runner commands / Run-related commands / gitlab-runner run-single
こちらを使うと、単一GitLab CI/CDジョブを実行できるGitLab Runnerを使えるようなので試してみます。
gitlab-runner run-singleコマンド
GitLab Runnerで使えるコマンドはこちらです。
GitLab Runner commands | GitLab Docs
run-singleコマンドについてはこちらです。
GitLab Runner commands / Run-related commands / gitlab-runner run-single
単一のGitLabインスタンスから単一のビルドを実行するコマンドであるとされています。
Use this supplementary command to run a single build from a single GitLab instance.
またrunコマンドとは違い、GitLabのURLやRunnerのトークンを含め、すべてのオプションをCLIのオプションや環境変数として
指定します。
Take all options either as CLI parameters or environment variables, including the GitLab URL and Runner token. For example, a single job with all parameters specified explicitly:
ちょっと変わったコマンドだなと思うので、試してみましょう。
環境
今回の環境はこちら。
GitLab。192.168.0.7で動作しているものとします。
$ sudo gitlab-rake gitlab:env:info System information System: Ubuntu 24.04 Current User: git Using RVM: no Ruby Version: 3.3.10 Gem Version: 3.7.1 Bundler Version:2.7.1 Rake Version: 13.0.6 Redis Version: 7.2.11 Sidekiq Version:7.3.9 Go Version: unknown GitLab information Version: 18.10.1 Revision: 6bef35b5226 Directory: /opt/gitlab/embedded/service/gitlab-rails DB Adapter: PostgreSQL DB Version: 16.11 URL: http://192.168.0.7 HTTP Clone URL: http://192.168.0.7/some-group/some-project.git SSH Clone URL: git@192.168.0.7:some-group/some-project.git Using LDAP: no Using Omniauth: yes Omniauth Providers: GitLab Shell Version: 14.47.0 Repository storages: - default: unix:/var/opt/gitlab/gitaly/gitaly.socket GitLab Shell path: /opt/gitlab/embedded/service/gitlab-shell Gitaly - default Address: unix:/var/opt/gitlab/gitaly/gitaly.socket - default Version: 18.10.1 - default Git Version: 2.53.gc61120c
GitLab Runner。
$ gitlab-runner --version Version: 18.10.0 Git revision: ac71f4d8 Git branch: 18-10-stable GO version: go1.25.7 X:cacheprog Built: 2026-03-16T14:23:19Z OS/Arch: linux/amd64
環境はTerraformで構築します。
$ terraform version Terraform v1.14.8 on linux_amd64
準備
最初にGitLabプロジェクトとGitLab Runnerのトークンの作成を行います。
main.tf
terraform { required_version = "1.14.8" required_providers { gitlab = { source = "gitlabhq/gitlab" version = "18.10.0" } } } variable "root_access_token" { type = string ephemeral = true } provider "gitlab" { token = var.root_access_token base_url = "http://192.168.0.7/" } resource "gitlab_group" "sample_group" { name = "sample group" path = "sample-group" visibility_level = "private" } resource "gitlab_project" "sample_app" { name = "sample-app" namespace_id = gitlab_group.sample_group.id default_branch = "main" visibility_level = "private" auto_devops_enabled = false only_allow_merge_if_pipeline_succeeds = true only_allow_merge_if_all_discussions_are_resolved = true } resource "gitlab_branch_protection" "main_branch" { project = gitlab_project.sample_app.id branch = "main" allow_force_push = false merge_access_level = "maintainer" push_access_level = "no one" unprotect_access_level = "maintainer" } resource "gitlab_group_membership" "sample_user" { group_id = gitlab_group.sample_group.id user_id = gitlab_user.sample_user.id access_level = "owner" } resource "gitlab_user" "sample_user" { name = "sample-user" username = "sample-user" password = "P@ssw0rd" email = "sample-user@example.com" } resource "gitlab_personal_access_token" "sample_user_token" { user_id = gitlab_user.sample_user.id name = "sample-user-pat" scopes = ["api"] } resource "gitlab_user_runner" "instance_runner" { runner_type = "instance_type" description = "sample instance runner" untagged = true } resource "gitlab_user_runner" "group_runner" { runner_type = "group_type" group_id = gitlab_group.sample_group.id description = "sample group runner" untagged = true } resource "gitlab_user_runner" "project_runner" { runner_type = "project_type" project_id = gitlab_project.sample_app.id description = "sample project runner" untagged = true } output "user_personal_access_token" { value = gitlab_personal_access_token.sample_user_token.token sensitive = true } output "instance_runner_authentication_toke" { value = gitlab_user_runner.instance_runner.token sensitive = true } output "group_runner_authentication_token" { value = gitlab_user_runner.group_runner.token sensitive = true } output "project_runner_authentication_toke" { value = gitlab_user_runner.project_runner.token sensitive = true }
グループ、プロジェクト、ユーザーを作成し、ユーザーのPersona Access TokenやGitLab Runnerのトークンも作成します。
rootアカウントのPersonal Access Tokenは.auto.tfvarsで設定することにしました。
secrets.auto.tfvars
root_access_token = "glpat-xxxxx"
リソースを作成。
$ terraform init $ terraform apply
GitLab Runnerおよびトークンの組み合わせは全種類作っていますが、今回はグループを使うことにします。
$ terraform output group_runner_authentication_token "glrt-xxxx"
またインストール済みのGitLab Runnerは停止しておきます。
$ sudo gitlab-runner stop
設定ファイルも削除。
$ sudo rm /etc/gitlab-runner/config.toml
これで準備は完了です。
GitLab Runnerをrun-singleコマンドで動かしてみる
では、GitLab Runnerをrun-singleコマンドで動かしてみましょう。
GitLab Runner commands / Run-related commands / gitlab-runner run-single
実行前にヘルプを見てみます。
runコマンドから。
$ gitlab-runner run --help Runtime platform arch=amd64 os=linux pid=9698 revision=ac71f4d8 version=18.10.0 NAME: gitlab-runner run - run multi runner service USAGE: gitlab-runner run [command options] [arguments...] OPTIONS: --listen-address value Metrics / pprof server listening address [$LISTEN_ADDRESS] -c value, --config value Config file (default: "/home/vagrant/.gitlab-runner/config.toml") [$CONFIG_FILE] -n value, --service value Use different names for different services (default: "gitlab-runner") -d value, --working-directory value Specify custom working directory -u value, --user value Use specific user to execute shell scripts --syslog Log to system service logger [$LOG_SYSLOG]
run-single。runコマンドとはまったく異なる数のオプションが表示されます。
$ gitlab-runner run-single --help Runtime platform arch=amd64 os=linux pid=9707 revision=ac71f4d8 version=18.10.0 NAME: gitlab-runner run-single - start single runner USAGE: gitlab-runner run-single [command options] [arguments...] OPTIONS: --name value, --description value Runner name [$RUNNER_NAME] --limit value Maximum number of builds processed by this runner (default: "0") [$RUNNER_LIMIT] --output-limit value Maximum build trace size in kilobytes (default: "0") [$RUNNER_OUTPUT_LIMIT] --request-concurrency value Maximum concurrency for job requests (default: "0") [$RUNNER_REQUEST_CONCURRENCY] --strict-check-interval value When you set StrictCheckInterval to true, the runner disables the faster-than-check_interval re-polling loop that occurs when a runner receives a job. Instead, the runner waits <check_interval> seconds before it polls again, even if additional jobs are available. [$RUNNER_STRICT_CHECK_INTERVAL] --unhealthy-requests-limit value The number of unhealthy responses to new job requests after which a runner worker is turned off. (default: "0") [$RUNNER_UNHEALTHY_REQUESTS_LIMIT] --unhealthy-interval value Duration that the runner worker is turned off after it exceeds the unhealthy requests limit. Supports syntax like '3600s' and '1h30min'. --job-status-final-update-retry-limit value The maximum number of times GitLab Runner can retry to push the final job status to the GitLab instance. (default: "0") [$RUNNER_job_status_final_update_retry_limit] -u value, --url value GitLab instance URL [$CI_SERVER_URL] -t value, --token value Runner token [$CI_SERVER_TOKEN] --tls-ca-file value File containing the certificates to verify the peer when using HTTPS [$CI_SERVER_TLS_CA_FILE] --tls-cert-file value File containing certificate for TLS client auth when using HTTPS [$CI_SERVER_TLS_CERT_FILE] --tls-key-file value File containing private key for TLS client auth when using HTTPS [$CI_SERVER_TLS_KEY_FILE] --executor value Select executor, eg. shell, docker, etc. [$RUNNER_EXECUTOR] --builds-dir value Directory where builds are stored [$RUNNER_BUILDS_DIR] --cache-dir value Directory where build cache is stored [$RUNNER_CACHE_DIR] --clone-url value Overwrite the default URL used to clone or fetch the git ref [$CLONE_URL] --env value Custom environment variables injected to build environment [$RUNNER_ENV] --proxy-exec value (Experimental) Proxy execution via helper binary [$RUNNER_PROXY_EXEC] --pre-get-sources-script value Runner-specific commands to be executed on the runner before updating the Git repository and updating submodules. [$RUNNER_PRE_GET_SOURCES_SCRIPT] --post-get-sources-script value Runner-specific commands to be executed on the runner after updating the Git repository and updating submodules. [$RUNNER_POST_GET_SOURCES_SCRIPT] --pre-build-script value Runner-specific command script executed just before build executes [$RUNNER_PRE_BUILD_SCRIPT] --post-build-script value Runner-specific command script executed just after build executes [$RUNNER_POST_BUILD_SCRIPT] 〜省略〜
やっぱり単発実行のコマンドなんですね。
トークンは変数として設定済みとします。
$ RUNNER_TOKEN=...
GitLabプロジェクトにはこんな.gitlab-ci.ymlを用意。
.gitlab-ci.yml
stages: - run greeting: stage: run script: | echo 'Hello World'
.gitlab-ci.ymlを登録すると、パイプラインがPendingになります。
ここでGitLab Runnerをrun-singleコマンドで実行。事前のregisterコマンドの実行は不要です。
$ sudo gitlab-runner run-single \ --url "http://192.168.0.7/" \ --token "$RUNNER_TOKEN" \ --executor "docker" \ --docker-image ubuntu:24.04 \ --docker-privileged \ --docker-volumes "/certs/client" \ --description "sample group runner"
そのままフォアグラウンドでGitLab Runnerが実行され、こんな感じでGitLab CI/CDジョブが実行されます。
Runtime platform arch=amd64 os=linux pid=1515 revision=ac71f4d8 version=18.10.0 Starting runner for http://192.168.0.7/ with token Q4xdCJ8Z7 ... Checking for jobs... received correlation_id=01KNESW8VQKJB372N8S0VTYSHW job=1 repo_url=http://192.168.0.7/sample-group/sample-app.git runner=Q4xdCJ8Z7 runner_name=sample group runner Updating job... bytesize=0 checksum= correlation_id=46408a0238f844a18d327e7fdae92774 job=1 runner=Q4xdCJ8Z7 runner_name=sample group runner Submitting job to coordinator...ok bytesize=0 checksum= code=200 correlation_id=01KNESW9HY9G31W1E82HB607DK job=1 job-status=running runner=Q4xdCJ8Z7 runner_name=sample group runner update-interval=0s Using default image executor=docker gitlab_user_id=6 image=ubuntu:24.04 job=1 namespace_id=13 organization_id=1 project=6 project_full_path=sample-group/sample-app root_namespace_id=13 runner=Q4xdCJ8Z7 runner_name=sample group runner Appending trace to coordinator...ok code=202 correlation_id=01KNESWCGJFR6PBXMXWVDGW0ZW job=1 job-log=0-509 job-status=running runner=Q4xdCJ8Z7 runner_name=sample group runner sent-log=0-508 status=202 Accepted update-interval=1m0s Using default image executor=docker gitlab_user_id=6 image=ubuntu:24.04 job=1 namespace_id=13 organization_id=1 project=6 project_full_path=sample-group/sample-app root_namespace_id=13 runner=Q4xdCJ8Z7 runner_name=sample group runner Using default image executor=docker gitlab_user_id=6 image=ubuntu:24.04 job=1 namespace_id=13 organization_id=1 project=6 project_full_path=sample-group/sample-app root_namespace_id=13 runner=Q4xdCJ8Z7 runner_name=sample group runner Job succeeded container_name=runner-q4xdcj8z7-project-6-concurrent-0-232d2ca0bd10075c-build duration_s=27.537055253 gitlab_user_id=6 job=1 job-status=success name=ubuntu namespace_id=13 organization_id=1 project=6 project_full_path=sample-group/sample-app root_namespace_id=13 runner=Q4xdCJ8Z7 runner_name=sample group runner Appending trace to coordinator...ok code=202 correlation_id=01KNESX4EF32EM66WQ3RW6N2Y2 job=1 job-log=0-3511 job-status=running runner=Q4xdCJ8Z7 runner_name=sample group runner sent-log=509-3510 status=202 Accepted update-interval=3s Updating job... bytesize=3511 checksum=crc32:e2a49d15 correlation_id=0fe9f05a57b54a2caaee1b54a1dcc748 job=1 runner=Q4xdCJ8Z7 runner_name=sample group runner Submitting job to coordinator...ok bytesize=3511 checksum=crc32:e2a49d15 code=200 correlation_id=01KNESX4K1WM878NS7X7XEXNSS job=1 job-status=success runner=Q4xdCJ8Z7 runner_name=sample group runner update-interval=0s
そしてそのまま待機します。終了したかったらCtrl-cですね。
run-singleという名前の割に、どうして終了しないかはドキュメントに書かれています。
You can use the --max-builds option to control how many builds the runner executes before exiting. The default of 0 means that the runner has no build limit and jobs run forever.
GitLab Runner commands / Run-related commands / gitlab-runner run-single
デフォルトでは実行するビルド数に制限がなく、上限を設定するには--max-buildsオプションを使います。
では、--max-buildsを1にして登録してみましょう。
$ sudo gitlab-runner run-single \ --url "http://192.168.0.7/" \ --token "$RUNNER_TOKEN" \ --executor "docker" \ --max-builds 1 \ --docker-image ubuntu:24.04 \ --docker-privileged \ --docker-volumes "/certs/client" \ --description "sample group runner"
すると、先ほどの.gitlab-ci.ymlの内容だと1回ジョブを実行するとすぐに終了します。
This runner has processed its build limit, so now exiting
ところで、こういう使い方だと--max-buildsオプションの単位が気になりますね。
ビルド=ジョブと捉えてよさそうです。パイプラインではないことに注意です。
たとえば.gitlab-ci.ymlを以下のように変更します。ジョブが3つありますね。
.gitlab-ci.yml
stages: - stage1 - stage2 - stage3 foo: stage: stage1 script: | echo 'foo' bar: stage: stage2 script: | echo 'bar' fuga: stage: stage3 script: | echo 'fuga'
このパイプラインに対して、--max-buildsを1にして実行すると最初のジョブ(foo)を実行したところでGitLab Runnerは
終了します。
$ sudo gitlab-runner run-single \ --url "http://192.168.0.7/" \ --token "$RUNNER_TOKEN" \ --executor "docker" \ --max-builds 1 \ --docker-image ubuntu:24.04 \ --docker-privileged \ --docker-volumes "/certs/client" \ --description "sample group runner"
このパイプラインのジョブをすべて実行するには、この設定のままだと3回GitLab Runnerを実行する必要があります。
もしくは以下のように--max-buildsを3にして実行します。
$ sudo gitlab-runner run-single \ --url "http://192.168.0.7/" \ --token "$RUNNER_TOKEN" \ --executor "docker" \ --max-builds 3 \ --docker-image ubuntu:24.04 \ --docker-privileged \ --docker-volumes "/certs/client" \ --description "sample group runner"
すると、パイプラインに含まれるすべてのジョブ(foo、bar、fuga)を実行し終えたところでGitLab Runnerも終了します。
ちょっとわかりにくいですね…パイプラインを実行の単位にして欲しいところではありました…。とはいえ、難しいところ
なのでしょうね。
使い方はおよそわかりました。
おわりに
GitLab Runnerのrun-singleコマンドを使って、単一のGitLab CI/CDジョブを実行してみました。
もっとも、デフォルトは単一ではなく無制限なのですが。
個人的にはパイプライン単位で扱えると嬉しいなと思ったのですが、単位がジョブなのでちょっと扱い方が難しいですね。
自分のジョブを実行できる専用のGitLab Runnerとして使えると便利かなと思ったのですが、工夫すればなんとかなるもの
でしょうか…?
今回は使い方がわかったのでよしとしましょう。