Since a few months ago this is possible using gitlab-runner:

gitlab-runner exec docker my-job-name

Note that you need both docker and gitlab-runner installed on your computer to get this working.

You also need the image key defined in your .gitlab-ci.yml file. Otherwise won't work.

Here's the line I currently use for testing locally using gitlab-runner:

gitlab-runner exec docker test --docker-volumes "/home/elboletaire/.ssh/id_rsa:/root/.ssh/id_rsa:ro"

Note: You can avoid adding a --docker-volumes with your key setting it by default in /etc/gitlab-runner/config.toml. See the official documentation for more details. Also, use gitlab-runner exec docker --help to see all docker-based runner options (like variables, volumes, networks, etc.).

Due to the confusion in the comments, I paste here the gitlab-runner --help result, so you can see that gitlab-runner can make builds locally:

   gitlab-runner --help
NAME:
   gitlab-runner - a GitLab Runner

USAGE:
   gitlab-runner [global options] command [command options] [arguments...]
   
VERSION:
   1.1.0~beta.135.g24365ee (24365ee)
   
AUTHOR(S):
   Kamil Trzciński <ayufan@ayufan.eu> 
   
COMMANDS:
   exec         execute a build locally
   [...]
   
GLOBAL OPTIONS:
   --debug          debug mode [$DEBUG]
   [...]

As you can see, the exec command is to execute a build locally.

Even though there was an issue to deprecate the current gitlab-runner exec behavior, it ended up being reconsidered and a new version with greater features will replace the current exec functionality.

Note that this process is to use your own machine to run the tests using docker containers. This is not to define custom runners. To do so, just go to your repo's CI/CD settings and read the documentation there. If you wanna ensure your runner is executed instead of one from gitlab.com, add a custom and unique tag to your runner, ensure it only runs tagged jobs and tag all the jobs you want your runner to be responsible of.

Unofficial alternative gitlab-ci-local

There's an unofficial package which looks promising, with more features than the official gitlab-runner exec: https://github.com/firecow/gitlab-ci-local

It allows you to run gitlab pipelines locally as shell executor or docker executor.

Answer from elboletaire on Stack Overflow
🌐
GitLab
docs.gitlab.com › gitlab docs › administer › administer gitlab runner › runner executors › shell
The Shell executor | GitLab Docs
The Shell executor is the simplest executor configuration for GitLab Runner. It executes builds locally on the machine where GitLab Runner is installed, so all dependencies must be installed on the same machine. It supports all systems on which the Runner can be installed.
🌐
GitLab
docs.gitlab.com › gitlab docs › administer › administer gitlab runner › runner executors › shell › supported shells
Types of shells supported by GitLab Runner | GitLab Docs
PowerShell Core is the default shell for new runner registration on Windows. However, this registration default applies only when you explicitly set a shell value in config.toml. When no shell is configured: The docker-windows and kubernetes executors default to PowerShell Desktop at runtime.
🌐
GitLab
docs.gitlab.com › gitlab docs › install › configure gitlab runner › commands
GitLab Runner commands | GitLab Docs
This command installs GitLab Runner as a service. It accepts different sets of arguments depending on which system it’s run on. When run on Windows or as super-user, it accepts the --user flag which allows you to drop privileges of builds run with the shell executor.
Top answer
1 of 11
237

Since a few months ago this is possible using gitlab-runner:

gitlab-runner exec docker my-job-name

Note that you need both docker and gitlab-runner installed on your computer to get this working.

You also need the image key defined in your .gitlab-ci.yml file. Otherwise won't work.

Here's the line I currently use for testing locally using gitlab-runner:

gitlab-runner exec docker test --docker-volumes "/home/elboletaire/.ssh/id_rsa:/root/.ssh/id_rsa:ro"

Note: You can avoid adding a --docker-volumes with your key setting it by default in /etc/gitlab-runner/config.toml. See the official documentation for more details. Also, use gitlab-runner exec docker --help to see all docker-based runner options (like variables, volumes, networks, etc.).

Due to the confusion in the comments, I paste here the gitlab-runner --help result, so you can see that gitlab-runner can make builds locally:

   gitlab-runner --help
NAME:
   gitlab-runner - a GitLab Runner

USAGE:
   gitlab-runner [global options] command [command options] [arguments...]
   
VERSION:
   1.1.0~beta.135.g24365ee (24365ee)
   
AUTHOR(S):
   Kamil Trzciński <ayufan@ayufan.eu> 
   
COMMANDS:
   exec         execute a build locally
   [...]
   
GLOBAL OPTIONS:
   --debug          debug mode [$DEBUG]
   [...]

As you can see, the exec command is to execute a build locally.

Even though there was an issue to deprecate the current gitlab-runner exec behavior, it ended up being reconsidered and a new version with greater features will replace the current exec functionality.

Note that this process is to use your own machine to run the tests using docker containers. This is not to define custom runners. To do so, just go to your repo's CI/CD settings and read the documentation there. If you wanna ensure your runner is executed instead of one from gitlab.com, add a custom and unique tag to your runner, ensure it only runs tagged jobs and tag all the jobs you want your runner to be responsible of.

Unofficial alternative gitlab-ci-local

There's an unofficial package which looks promising, with more features than the official gitlab-runner exec: https://github.com/firecow/gitlab-ci-local

It allows you to run gitlab pipelines locally as shell executor or docker executor.

2 of 11
189

Deprecated since 2024-05 (see edit)

Only for gitlab-runner < 17.0.

  • See gitlab issue.
  • See gitlab docu

I use this docker-based approach:

Edit: 2024-05

docker run --entrypoint bash --rm -w "PWD:$PWD" -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:v15.11.1 -c 'git config --global --add safe.directory "*";gitlab-runner exec docker test'

Thanks to user Ivo Smits who reported a successful test with gitlab-runner:v15.11.1

Edit: 2022-10

For all git versions > 2.35.2. You must add safe.directory within the container to avoid fatal: detected dubious ownership in repository at.... This also true for patched git versions < 2.35.2. The old command will not work anymore.

Details

0. Create a git repo to test this answer

mkdir my-git-project
cd my-git-project
git init
git commit --allow-empty -m"Initialize repo to showcase gitlab-runner locally."

1. Go to your git directory

cd my-git-project

2. Create a .gitlab-ci.yml

Example .gitlab-ci.yml

image: alpine

test:
  script:
    - echo "Hello Gitlab-Runner"

3. Create a docker container with your project dir mounted

docker run -d \
  --name gitlab-runner \
  --restart always \
  -v "PWD" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  gitlab/gitlab-runner:latest

(-d) run container in background and print container ID

(--restart always) or not?

(-v "PWD") Mount current directory into the current directory of the container - Note: On Windows you could bind your dir to a fixed location, e.g. -v "${PWD}:/opt/myapp". Also $PWD will only work at powershell not at cmd

(-v /var/run/docker.sock:/var/run/docker.sock) This gives the container access to the docker socket of the host so it can start "sibling containers" (e.g. Alpine).

(gitlab/gitlab-runner:latest) Just the latest available image from dockerhub.

4. Execute with

Avoid fatal: detected dubious ownership in repository at... More info

docker exec -it -w $PWD gitlab-runner git config --global --add safe.directory "*"

Actual execution

docker exec -it -w $PWD gitlab-runner gitlab-runner exec docker test
#                ^          ^           ^            ^     ^      ^
#                |          |           |            |     |      |
#               (a)        (b)         (c)          (d)   (e)    (f)

(a) Working dir within the container. Note: On Windows you could use a fixed location, e.g. /opt/myapp.

(b) Name of the docker container

(c) Execute the command "gitlab-runner" within the docker container

(d)(e)(f) run gitlab-runner with "docker executer" and run a job named "test"

5. Prints

...
Executing "step_script" stage of the job script
$ echo "Hello Gitlab-Runner"
Hello Gitlab-Runner
Job succeeded
...

Note: The runner will only work on the commited state of your code base. Uncommited changes will be ignored. Exception: The .gitlab-ci.yml itself does not have be commited to be taken into account.

Note: There are some limitations running locally. Have a look at limitations of gitlab runner locally.

🌐
GitLab
docs.gitlab.com › gitlab docs › administer › administer gitlab runner › runner executors
Executors | GitLab Docs
Default shell for jobs with the docker-windows and kubernetes executors. ↩︎ · Default shell for runner registration and for jobs with the shell executor.
🌐
GitHub
github.com › buzzdeee › gitlab-runner › blob › master › docs › executors › shell.md
gitlab-runner/docs/executors/shell.md at master · buzzdeee/gitlab-runner
The Shell executor is a simple executor that allows you to execute builds locally to the machine that the Runner is installed. It supports all systems on which the Runner can be installed.
Author: buzzdeee
🌐
Testmuai
testmuai.com › testmu ai › blog › how to use gitlab ci to run tests locally
How To Use GitLab CI To Run Tests Locally
March 10, 2021 - Since gitlab-Runner exec clones the current state of the local Git repository, be sure to have committed any changes you want to test beforehand. The exec command should be executed directly from the root directory because .gitlab-ci.yml is present there. And while executing it, you must specify the executor and the name of the job. The following instruction, for example, executes a job called ‘test’ locally using a shell executor.
🌐
Medium
medium.com › @umutuluer › how-to-test-gitlab-ci-locally-f9e6cef4f054
How to Test Gitlab Ci Locally. I have a gitlab-ci.yml file and I want… | by Umut Uluer | Medium
October 31, 2018 - Finally, lets make test locally. In this section, we will use gitlab-runner exec command with executor type and stage title. I will run test stage. Furthermore, I will share deploy stage to be reference.
🌐
GitLab
gitlab.com › gitlab.org › gitlab-runner › #4275
How to use exec command with the dockerized version of gitlab-runner (#4275) · Issues · GitLab.org / gitlab-runner · GitLab
Summary Trying to debug a failing gitlab ci job by using the docker gitlab-runner exec functionality. But it fails right away...
Find elsewhere
Top answer
1 of 2
2

Worth checking:

GitLab CI/CD Pipeline: Run Script via SSH to remote server

Better way for multiline ssh command

TL;DR

  1. Create SSH keys. You'll get 2 keys: one private-key (ex: id_ed25519) and one public-key (ex: id_ed25519.pub)

  2. Add the private-key as a GitLab Variable: Settings -> CI/CD -> Variables -> Expand -> Add Variable (GitLab’s variable is a key-value pair. Name the key SSH_PRIVATE_KEY and paste your private-key in the value field. Then Click Add Variable.)

  3. Add one more Gitlab variable: DServerIP as the IP address of the remote server (in your case, the server hosting the gitLab-runner)

  4. Add the public-key to the remote server under the .ssh folder (it should be /home/username/.ssh or /root/.ssh)

  5. Paste the public-key into authorized_keys file (it should be /home/username/.ssh/authorized_keys or /root/.ssh/authorized_keys, but if you don’t have authorized_keys file, create it.)

  6. use the following script in your .gitlab-ci file

image: alpine:latest

stages:
  - Execute_script_on_remote_host

update:
  stage: Execute_script_on_remote_host
  before_script:
    - 'command -v ssh-agent >/dev/null || ( apk add --update openssh-client )'
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - ssh-keyscan $DServerIP >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
  script:
    - scp  ./auto_update_test.sh root@$DServerIP:/opt/splunktest
    - |
      ssh  -tt root@$DServerURL /bin/bash -s << EOT
      cd /opt/splunktest
      chmod +x auto_update_test.sh
      bash auto_update_test.sh
      exit
      EOT

Notes:

  • make sure that the file auto_update_test.sh is in the same directory as .gitlab-ci.yml (or just change its path in the script)
  • you can put all your commands into a shell script (ex: remote_update.sh) in your project and change the SSH command:

remote_update.sh:

cd /opt/splunktest
chmod +x auto_update_test.sh
bash auto_update_test.sh
exit

SSH command in the script:

script:
    - scp  ./auto_update_test.sh root@$DServerIP:/opt/splunktest
    - ssh  -tt root@$DServerIP "/bin/bash -s" <remote_update.sh

  • you even can connect via ssh and execute the commands of the auto_update_test.sh file without the need to copying it to the remote server.

SSH command in the script:

script:
    - ssh  -tt root@$DServerIP "/bin/bash -s" <auto_update_test.sh

See also:

  • https://superuser.com/questions/649186/how-can-i-get-the-scp-command-to-overwrite-the-destination-folder
  • Pseudo-terminal will not be allocated because stdin is not a terminal
2 of 2
0

Your runner is using the docker executor. When you run jobs with this runner, it creates new docker containers for each job. The container has its own filesystem separate from your 'baremetal' host where the runner is installed.

Therefore you have two problems:

  1. you won't find /opt/splunk in your container filesystem (the immediate cuase of your error)
  2. Running the script inside your job container may not have the effect you're expecting it to have on the host system, since it's running inside a container.

If you only need to update files on the host in the /opt/splunk directory, you can configure your runner to mount this directory from the host into your job containers, so that /opt/splunk from the host will be available in /opt/splunk in the job containers and changes within that directory will persist on the host.

In your runner's /etc/gitlab-runner/config.toml, you can add this volumes key:

# ...
[runners.docker]
  # ...
  volumes = ["/opt/splunk"]

Then restart your runner.

You could also consider using a shell executor instead, which would run jobs (and commands therein) directly on the same host and filesystem(s) where the runner is installed.

🌐
Lullabot
lullabot.com › articles › debugging-jobs-gitlab-ci
Debugging Jobs in GitLab CI | Lullabot
December 27, 2025 - Run the job with the command gitlab-runner exec docker [job id goes here].
🌐
GitLab
gitlab.com › gitlab.org › gitlab-runner › repository
docs/commands · fd98f3b671c5ee4fb8fd54a41c7a242eb73a91d9 · GitLab.org / gitlab-runner · GitLab
gitlab-runner exec clones the current state of the local Git repository. Make sure you have committed any changes you want to test beforehand. For example, the following command executes the job named tests locally using a shell executor:
🌐
Gitlab
gitlab-docs-d6a9bb.gitlab.io › administer › administer gitlab runner › runner executors › shell
The Shell executor | GitLab
The shell executor starts the script for each job in a new process. On UNIX systems, it sets the main process as a process group. ... A job times out. A job is canceled. On UNIX system gitlab-runner sends SIGTERM to the process and its child processes, and after 10 minutes sends SIGKILL.
🌐
BrowserStack
browserstack.com › home › guide › how to run test on gitlab ci locally
How to run test on GitLab CI Locally | BrowserStack
May 30, 2023 - Explore the shell executor. ... Gitlab-runner exec is the command that helps test locally. The exec command should be executed directly from the root directory because .gitlab-ci.yml will be kept in the root directory.
🌐
ADHDecode
adhdecode.com › articles › gitlab-ci › gitlab-ci-runner-shell-executor
Configure GitLab CI Runner with Shell Executor (2026) | ADHDecode
Imagine you have a simple ... $(pwd)" - ls -la · When this job runs on a shell executor, the echo and ls commands are executed directly on the runner machine....
🌐
GitLab
gitlab.com › gitlab.org › gitlab-runner › repository
docs/executors/shell.md · main · GitLab.org / gitlab-runner · GitLab
GitLab Runner is the open source project that is used to run your CI/CD jobs and send the results back to GitLab
🌐
GitLab
docs.gitlab.com › gitlab docs › administer › administer gitlab runner
GitLab Runner | GitLab Docs
Executor: The method GitLab Runner uses to execute jobs (Docker, Shell, Kubernetes, etc.).
🌐
GitLab
gitlab.com › gitlab.org › gitlab-runner › #312
gitlab-runner exec: easily test builds locally (#312) · Issues · GitLab.org / gitlab-runner · GitLab
I just pushed a brand new feature to GitLab Runner: exec. It allows you to run the jobs defined in .gitlab-ci.yml locally!
🌐
Medium
medium.com › fme-developer-stories › locally-testing-gitlab-ci-jobs-aeb3eb5ec4a8
Locally testing Gitlab CI jobs. We are using Gitlab now for two and a… | by Florian Maul | fme DevOps Stories | Medium
November 15, 2018 - mkdir -p /tmp/gitlabrunnergitlab-runner exec docker --docker-volumes /tmp/gitlabrunner:/cache <jobname> The build (in docker) is significantly slower as a local build on my Mac, i.e. it’s not a good idea to run every local build using this method. But it is fine for testing the build script. If you only want to run the script without the docker environment you can use the shell executor which runs the build script on your local machine directly.
🌐
Gitlab
docs.gitlab.co.jp › runner › shells
Types of shells supported by GitLab Runner | GitLab
The cmd shell remains included in future versions of GitLab Runner however, any new feature for Windows is to be tested and supported only for use with PowerShell. Only critical bugs and regressions to the cmd shell will be investigated and fixed. You can execute Batch scripts from PowerShell using Start-Process "cmd.exe" "/c C:\Path\file.bat" for old Batch scripts not ported to PowerShell.