Back to TIL
March 2026
posted on 03.29.2026

Git Submodules Are Not Cloned in Docker Builds

When a Dockerfile copies source with COPY . ., git submodules appear as empty directories. Git submodules are tracked by reference (a commit SHA in .gitmodules), not by content. Docker's build context does not include .git/ metadata, so there is nothing to resolve the submodule from.

# Submodule directory will be EMPTY after this
COPY . .

# Fix: clone the submodule content directly if missing
RUN if [ ! "$(ls src/content/blog/*.mdx 2>/dev/null)" ]; then \
      echo "Fetching content..." && \
      apk add --no-cache git && \
      git clone --depth 1 \
        "https://x-access-token:${GITHUB_TOKEN}@github.com/user/content.git" \
        src/content && \
      rm -rf src/content/.git; \
    fi

The pattern: check if the submodule directory has the expected files. If not, clone it with --depth 1 (shallow, fast) using a GitHub token passed as a build arg. Remove .git/ after cloning to keep the image small.

This applies to every submodule independently. If you have three submodules (content, prompts, til), you need three separate clone fallback blocks.

Alternative: use git clone --recursive in CI before docker build, so the build context already has submodule contents. But this requires CI to have git access, which is not always the case with managed platforms like Dokploy.

No reactions yet

in Naperville, IL
Last visitor from Mitaka, Japan
⌘K