DEV Community

Cover image for GitLab CI: How to Use a Dockerfile from Remote Repository
Kelvyn Thai
Kelvyn Thai

Posted on

GitLab CI: How to Use a Dockerfile from Remote Repository

🧩 The Problem

You have multiple (group) projects (frontend, backend, etc.) and you want:

  • A single Dockerfile in a central repo (cicd-template/frontend/gitlab-template.yml)
  • All group app repos reuse it
  • No duplication, no drift, better control

You try:

include:
  - project: "kelvyn-labs/cicd-template"
    ref: master
    file: "/frontend/gitlab-ci.yml"
Enter fullscreen mode Exit fullscreen mode

But during the pipeline:

docker build -f frontend/Dockerfile .
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ ❌ It fails β€” file not found


🧠 Why This Happens

In GitLab:

include:project only imports CI YAML, not repository files

Your pipeline still runs inside:

nextjs-cicd-template
Enter fullscreen mode Exit fullscreen mode

So it cannot access files from:

cicd-template
Enter fullscreen mode Exit fullscreen mode

❌ Common (Wrong) Solutions

  • Copy Dockerfile into every repo ❌
  • Use Git submodules ❌ (heavy, messy)
  • Assume include gives file access ❌

βœ… The Correct Solution

Use:

CI_JOB_TOKEN + GitLab Repository Files API

When a CI/CD pipeline job is about to run, GitLab generates a unique token and makes it available to the job as the CI_JOB_TOKEN predefined variable. The token is valid only while the job is running. After the job finishes, the token access is revoked and you cannot use the token anymore.

This allows your pipeline to securely fetch files from another project at runtime.


πŸ”‘ How It Works

Pipeline (app repo)
   ↓
CI_JOB_TOKEN (auth)
   ↓
GitLab API
   ↓
cicd-template repo
   ↓
Download Dockerfile
Enter fullscreen mode Exit fullscreen mode

πŸ§ͺ Implementation

Step 1 β€” Allow Cross-Project Access

In cicd-template:

Settings β†’ CI/CD β†’ Job token permissions -> Fine-grained permissions -> Add kelvyn-labs/nextjs-cicd-template
Enter fullscreen mode Exit fullscreen mode

Source:
https://docs.gitlab.com/ci/jobs/fine_grained_permissions/#repositories-endpoints


Step 2 β€” Fetch Dockerfile

.build-job:
 variables:
  CICD_TEMPLATE_PROJECT_ID: "81568045" // project ID
  CICD_TEMPLATE_REF: "master" // target branch
  CICD_TEMPLATE_DOCKERFILE_PATH: "frontend%2FDockerfile" // encode url
 script:
  - echo "Fetch Dockerfile from cicd-template"
  - 'curl --fail --location --header "JOB-TOKEN: $CI_JOB_TOKEN" "https://gitlab.com/api/v4/projects/$CICD_TEMPLATE_PROJECT_ID/repository/files/$CICD_TEMPLATE_DOCKERFILE_PATH/raw?ref=$CICD_TEMPLATE_REF" -o Dockerfile'
Enter fullscreen mode Exit fullscreen mode

⚠️ Important Notes

  • File path must be URL-encoded
  frontend/Dockerfile β†’ frontend%2FDockerfile
Enter fullscreen mode Exit fullscreen mode
  • Use project ID (simpler than encoding path)
  • Token only works while job is running
  • Target repo must allow access (allowlist)

Step 3 β€” Build Image

docker buildx build \
  --file Dockerfile \
  --tag $IMAGE_TAG \
  --push .
Enter fullscreen mode Exit fullscreen mode

🧠 Why This Is Better

βœ… Centralized Control

  • Dockerfile lives in one repo
  • Platform team controls build logic

βœ… No Duplication

  • No copy-paste across repos

βœ… Secure

  • Controlled via:

    • allowlist
    • user permissions
    • CI_JOB_TOKEN scope

βœ… Flexible

  • Works for FE / BE / any service

πŸš€ Advanced Tips

1. Pin Version (Don’t Use master)

variables:
  CICD_TEMPLATE_REF: "v1.0.0"
Enter fullscreen mode Exit fullscreen mode
...?ref=${CICD_TEMPLATE_REF}
Enter fullscreen mode Exit fullscreen mode

2. Make It Reusable

variables:
  CICD_TEMPLATE_PROJECT_ID: "81568045"
  CICD_TEMPLATE_DOCKERFILE: "frontend%2FDockerfile"
Enter fullscreen mode Exit fullscreen mode

3. When NOT to Use This

If your Dockerfile depends on multiple files:

COPY scripts/start.sh /app/
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ Then use git clone instead of single-file fetch


🏁 Final Takeaway

include is for config reuse
CI_JOB_TOKEN is for secure runtime access

If you want to reuse real files across projects:

πŸ‘‰ use GitLab API + CI_JOB_TOKEN


πŸ’¬ Closing

This pattern is used by many teams to build:

  • Internal CI/CD platforms
  • Standardized pipelines
  • Centralized build logic

If you’ve ever struggled with:

β€œWhy can’t my pipeline access files from another repo?”

Now you know the missing piece.


πŸ”₯ Bonus Thought

Stop copying Dockerfiles.
Start treating CI/CD like a platform.

Full source codes:

Top comments (0)