Register a runner on a separate machine:
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
sudo apt install -y gitlab-runner
sudo gitlab-runner register --url https://gitlab.example.com \
--token <runner-authentication-token> --executor docker --docker-image alpine:3.19
Since GitLab 16.0 the runner is created in the UI first (Settings, CI/CD, Runners) and registered with an authentication token.
.gitlab-ci.yml:
stages: [test, build, deploy]
default:
image: node:20
test:
stage: test
cache:
key: { files: [package-lock.json] }
paths: [node_modules/]
script: [npm ci, npm test]
build:
stage: build
image: docker:25
services: [docker:25-dind]
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
rules: [{ if: '$CI_COMMIT_BRANCH == "main"' }]
deploy:
stage: deploy
environment: production
when: manual
script: ./deploy.sh
Mark secrets as masked and protected variables so only protected branches can read them.