Hello again! In Part 1 of Git on Localhost | Self-hosted GitLab series, we successfully installed our own self-hosted GitLab server in localhost using Docker. You may have even gone ahead, created your first project, and added a .gitlab-ci.yml file, only to see your pipeline get "stuck" with a pending status.
If not, try setting up a project from your project list:
Note: If you already setup a project and a pipeline to your local server, then skip the setup part & directly move to the next part.
⚠ Though its a
part 2article, but I mistakenly wrote 'part 3' in the Cover image! Sorry for that! 🙏🏻
first create a repository with a name Go CI Test,then add some code there from your pc:
cd project_folder
git init --initial-branch=main
git remote add origin http://localhost:8080/root/ci-test.git
git add .
git commit -m "add: test CI"
git push --set-upstream origin main
now create a file name .gitlab-ci.yml in the root folder and add some demo CI/CD code:
stages:
- test
dummy_test_job:
stage: test
script:
- echo "Running dummy test..."
- exit 0
An Error Occured! pipeline cant run!
This is expected! We've built the "brain" (the GitLab server), but we haven't given it any "hands" to do the work. This is where the GitLab Runner comes in.
In this article, we'll install and register our own local runner—also using Docker—to pick up those pending jobs and bring our CI/CD pipelines to life.
What is a GitLab Runner and Why Do We Need One?
A GitLab Runner is a separate application that executes the CI/CD jobs specified in your GitLab projects.
On GitLab.com, your jobs run on a shared fleet of runners managed by GitLab.
On our self-hosted server, we are in a private environment. The GitLab server knows what to do (from
.gitlab-ci.yml) but has no one to delegate the task to.
We must provide our own Runner. This runner will poll our GitLab server, ask "Are there any jobs for me?", and if so, execute them. We'll use the Docker executor, which means our runner will spin up a fresh, clean Docker container for every single job, providing a perfectly isolated and reproducible build environment.
Installation Process
As we did in Part 1, we will use Docker to keep our setup clean and containerized.
Caution: Before we start, make sure Docker is running on your machine along with the gitlab container.
Step 0: Create a Docker Network
To allow our gitlab container and our new gitlab-runner container to communicate with each other by name, we should create a dedicated Docker network.
- First, create the network:
docker network create gitlab-network
You can verify it exists with docker network ls command.
- Next, connect your existing gitlab container (from Part 1) to this network:
docker network connect gitlab-network gitlab
This allows the runner to find the server at the hostname gitlab.
Step 1: Pull the GitLab Runner Docker Image
Open your terminal and pull the latest official image for the runner:
docker pull gitlab/gitlab-runner:latest
Step 2: Start the Runner Container
Now we'll launch the runner container. This command creates a persistent volume for the runner's configuration and mounts the host's Docker socket so the runner can launch other containers.
For Linux / macOS: (This assumes you want to store the config in /code/gitlab-runner/config, similar to Part 1)
docker run -d \
--name gitlab-runner \
--restart always \
--network gitlab-network \
-v /code/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:
For Windows (using PowerShell): (This assumes you're using the D:\code\ path from Part 1)
docker run -d --name gitlab-runner --restart always --network gitlab-network -v D:\code\gitlab-runner\config:/etc/gitlab-runner -v //var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:
Command Breakdown:
--name gitlab-runner: A recognizable name for our container.--restart always: Ensures the runner restarts if you reboot your machine.--network gitlab-network: Connects the runner to the same network as our GitLab server.-v /code/gitlab-runner/config:/etc/gitlab-runner: Persistent Config. This maps a folder on your host machine to the config folder inside the container. This is critical so your runner doesn't forget its registration if you update or restart the container.-v /var/run/docker.sock:/var/run/docker.sock: The Docker Socket. This is the magic. It gives the runner permission to use your host machine's Docker daemon. This is how the runner can spin up new containers (e.g., golang:1.21 or node:18) to run your jobs. (Note for Windows: the //var/run/docker.sock path is correct).
Step 3: Register the Runner
Our runner container is running, but it's not authenticated with our server. We need to "register" it.
- Find Your Registration Token:
Log into your local GitLab server (
http://localhost:8080) as therootuser.Click the Admin Area (wrench icon) in the top navigation bar.
In the left sidebar, go to CI/CD > Runners.
-
Click the "Register an instance runner" button.
Copy the registration token displayed. It will start with
glrt...
- Run the Interactive Registration Command: We will execute a command inside our running
gitlab-runnercontainer:
docker exec -it gitlab-runner gitlab-runner register
- Answer the Prompts: This will start an interactive setup.

Here are the answers you should provide:
-
Enter the GitLab instance URL:http://gitlab(We usehttp://gitlabinstead oflocalhostbecause both containers are on thegitlab-networkand can find each other by their container names.8080is the port we exposed in Part 1.) -
Enter the registration token:[PASTE_THE_TOKEN_YOU_COPIED]
-
Enter a description for the runner:'My Local Docker Runner (or whatever you want to write)' (This is just a friendly name you'll see in the UI.)
-
Enter tags for the runner(comma-separated):docker,local(Tags are very important. This allows you to "tag" your jobs in.gitlab-ci.ymlto ensure they run on the correct runner.) -
Enter an optional maintenance note:
(Just press Enter to leave this blank.)
-
Enter the executor:docker(This is the most important setting. It tells the runner to use Docker to run jobs.) -
Enter the default Docker image:alpine:latest(This is a fallback image to use if a job in your.gitlab-ci.ymldoesn't specify its own image:.)
The registration is now complete!
Step 4: Verify Your Runner
Go back to your GitLab browser window (the Admin Area > Runners page) and refresh.
You should now see your new runner listed, with a green circle indicating it is online and ready for jobs.
Optional: You can manually verify that the runner is available to pick up jobs.
docker exec -it gitlab-runner gitlab-runner run
Now, go back to that "pending" pipeline (or push a new commit to trigger one). You will see it get picked up by your new runner and finally switch to "running" and then "passed"!
Conclusion
Congratulations! You now have a complete, end-to-end CI/CD setup on your local machine. You have the Local GitLab Server to manage your code and pipelines, and a GitLab Runner to execute the work.
Hope this tutorial series helps you setup your own local version control!
Next what you can do is deploy this to your server and can access from anywhere!
Enjoy your own Private gitlab!







Top comments (0)