Setup CI with GitLab Pipelines
How to configure GitLab CI/CD pipelines for testing, building, and deploying applications using .gitlab-ci.yml with stages, jobs, caching, and runners.
Overview
GitLab CI/CD is a built-in continuous integration and deployment platform that uses a .gitlab-ci.yml file to define pipelines. Jobs run in isolated Docker containers on shared or self-hosted runners, making it easy to automate testing, building, and releasing software.
Before CI/CD pipelines, teams ran tests and deployments manually from local machines. This led to “works on my laptop” bugs, inconsistent environments, and no audit trail of what was deployed when. GitLab CI/CD solves this by codifying every step of the delivery process in version-controlled YAML.
When to Use
Use this recipe when:
- Setting up automated testing for a GitLab-hosted project on every push or merge request.
- Building and pushing Docker images to a registry as part of the release process.
- Deploying to staging or production with environment-specific variables and manual approvals.
- Running scheduled pipelines for nightly backups, dependency audits, or periodic cleanup tasks.
- Using self-hosted runners for private infrastructure or specialized build environments.
What Works
- Use
npm ciinstead ofnpm installin CI for reproducible builds that strictly respectpackage-lock.json. - Cache dependencies between jobs using the
cachekeyword to dramatically reduce build times. - Pin Docker image versions instead of using
latesttags to ensure reproducible builds. - Use
artifactsto pass files between stages (e.g., compiled bundles from build to deploy). - Set
onlyorrulescarefully to avoid running expensive deploy jobs on feature branches. - Use
environmentblocks for deployment jobs to track what is deployed and enable rollbacks.
Common Mistakes
- Not caching
node_modulescauses every job to reinstall dependencies from scratch, wasting minutes per run. - Using
onlyinstead ofrules—rulesis the modern, more flexible way to control job execution. - Running DIND without TLS can expose the Docker socket to other jobs on the same runner.
- Storing secrets in
.gitlab-ci.yml— always use CI/CD variables from the project settings. - Forgetting
tagsfor self-hosted runners causes jobs to queue indefinitely on shared runners.
Performance Tips
- Use
needsfor DAG execution. Reduce wall-clock time by starting jobs as soon as their dependencies finish:
test:
needs: [build] # Starts immediately after build
- Cache per-branch. Avoid cache collisions between branches:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- node_modules/
- Use
interruptible: truefor MR jobs. Save runner time by canceling superseded pipelines:
test:
interruptible: true
- Use small images. Reduce pull time:
# Bad: large image
image: node:20
# Good: slim image
image: node:20-slim
# Best: alpine if compatible
image: node:20-alpine
- Use
before_scriptandafter_scriptwisely. They run for every job in the file:
default:
before_script:
- npm ci --silent
after_script:
- echo "Job completed with exit code $?" Frequently Asked Questions
What is a GitLab Runner?
A GitLab Runner is the agent that executes pipeline jobs. It can be shared, group-specific, or project-specific, and runs on Linux, Windows, macOS, or Kubernetes.
How do I cache dependencies in GitLab CI?
Use the cache keyword to persist directories like node_modules, .m2, or .pip between pipelines. Use key to scope caches per branch or lockfile.
What is the difference between stages and jobs?
Stages define execution phases (build, test, deploy) that run sequentially. Jobs are the individual tasks within a stage, which can run in parallel if they share a stage.
Related Resources
GitHub Actions CI/CD
How to build and deploy with GitHub Actions using workflows, matrices, caching, and secrets.
RecipeDocker Basics
How to containerize an application, write a Dockerfile, and run containers with Docker Compose.
RecipeEnvironment Variables
How to read, set, and manage environment variables securely across Python, JavaScript, and Java.
RecipeDeploy Containers to AWS ECS with Fargate
How to deploy Docker containers to AWS ECS using Fargate serverless compute with Terraform and GitHub Actions
RecipeBackground Jobs
How to schedule and run background jobs using cron, task queues, and workers.
GuideComplete Guide to CI/CD with GitHub Actions
Build CI/CD pipelines from scratch with GitHub Actions. Covers workflows, runners, matrix builds, caching, secrets, environments, deployment strategies, and reusable workflows.