基于Docker的GitLab CI Review App流水线搭建及Runner选型咨询
Hey there! Let's break down your questions step by step:
Your plan to build a GitLab CI pipeline with Docker + docker-compose hits all the right notes for your requirements:
- Docker标准化环境: Ensures consistent builds and runtime across all branches, eliminating "it works on my machine" issues.
- Review Apps via GitLab Environments: GitLab CI natively supports dynamic environments, which is perfect for spinning up unique
http://feature_*.your-project.example.comURLs per branch. - Local Registry Integration: Pushing built images to your internal registry is a standard, scalable way to manage and deploy your app artifacts.
For the Review App piece specifically, you'll want to leverage GitLab's environment keyword in your CI config to create branch-specific environments. You can use CI variables like ${CI_COMMIT_BRANCH//\//_} to sanitize branch names (replacing slashes with underscores for valid URLs) and map them to your subdomain pattern.
Your past issues with Shell Runner make total sense—here's why Docker Runner is the better fit for your workflow:
Why Shell Runner causes headaches
- Environment pollution: Shell Runners execute commands directly on the host machine. Multiple branches/jobs can leave behind conflicting dependencies, leftover containers, or port locks, leading to random failures.
- Lack of consistency: The host's Docker/docker-compose versions might not match what your project needs, creating compatibility gaps.
- Concurrency limits: Running multiple jobs at once on the same host increases the risk of resource clashes (e.g., two jobs trying to use port 3000).
Why Docker Runner is the right choice
- Isolation: Every CI job runs in a clean, dedicated Docker container. No cross-job interference, no leftover cruft.
- Controlled environments: You can specify exact base images (like
docker:latestordocker/compose:latest) to ensure all jobs use the same Docker tooling versions. - Easy maintenance: No need to install dependencies on the host—everything your job needs comes pre-packaged in the runner's base image.
- Better scalability: Supports concurrent jobs without the host-level conflicts you'd get with Shell Runner.
Key Docker Runner setup note
You'll need to enable Docker-in-Docker (DinD) mode for your runner. This lets your CI jobs run Docker commands (like building/pushing images, starting docker-compose stacks) inside the runner's container. Just make sure your runner config has privileged: true enabled to allow DinD functionality.
Here's a simplified .gitlab-ci.yml example that aligns with your goals:
stages: - build-image - deploy-review - cleanup-review # Build and push image to local registry build-image: stage: build-image image: docker:latest services: - docker:dind variables: DOCKER_DRIVER: overlay2 IMAGE_TAG: your-local-registry/nodejs-express-todoapp:${CI_COMMIT_BRANCH//\//_}-${CI_COMMIT_SHORT_SHA} before_script: - docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD your-local-registry script: - docker build -t $IMAGE_TAG . - docker push $IMAGE_TAG # Deploy Review App with unique subdomain deploy-review: stage: deploy-review image: docker/compose:latest services: - docker:dind variables: REVIEW_URL: http://${CI_COMMIT_BRANCH//\//_}.nodejs-express-todoapp.example.com IMAGE_TAG: your-local-registry/nodejs-express-todoapp:${CI_COMMIT_BRANCH//\//_}-${CI_COMMIT_SHORT_SHA} environment: name: review/${CI_COMMIT_BRANCH} url: $REVIEW_URL on_stop: cleanup-review script: - docker login -u $REGISTRY_USER -p $REGISTRY_PASSWORD your-local-registry - docker-compose up -d only: - branches # Clean up Review App when branch is deleted or manually triggered cleanup-review: stage: cleanup-review image: docker/compose:latest services: - docker:dind variables: GIT_STRATEGY: none environment: name: review/${CI_COMMIT_BRANCH} action: stop script: - docker-compose down when: manual only: - branches
- Set up wildcard DNS for
*.nodejs-express-todoapp.example.compointing to your runner/host IP so Review App URLs resolve correctly. - Store your registry credentials (
REGISTRY_USER,REGISTRY_PASSWORD) as GitLab CI/CD variables to avoid hardcoding them. - Consider adding image caching to your build stage to speed up repeated builds.
内容的提问来源于stack exchange,提问作者ysakiyev

