Table of Contents
Using Docker Alongside Git
Docker and Git often appear together in modern development workflows. Git manages your source code history, while Docker defines how that code runs. In this chapter you will see how they fit together and what is specific about combining them in a clean and maintainable way.
What Belongs in Git and What Belongs in Images
A basic question is what should be stored in your Git repository and what should only live in Docker images. Source code, configuration templates, Docker-related configuration files, and small scripts belong in Git. Compiled artifacts, large binaries, and installed dependencies are usually better rebuilt during the Docker image build process instead of being checked in.
If you build your application inside the image, the Git repository stays focused on human edited files. The image becomes the place where dependencies are installed. This separation helps when you clone the repository on a new machine. You can simply run the same Docker commands and get an identical environment without having to install all system level dependencies locally.
Keep source code and configuration in Git, and keep compiled artifacts and installed dependencies in Docker images. Never commit large generated files just because the image build creates them.
Versioning Code and Images Together
Git provides commit hashes and tags that identify specific versions of your code. Docker images also use tags and immutable digests. A clean workflow connects these two worlds.
One common approach is to build Docker images from a specific Git commit and to tag those images with both an application version and the Git commit hash. For example, if your Git commit is abc1234 and your version is 1.2.0, you might tag the image as myapp:1.2.0 and myapp:abc1234. The Git history explains what changed in the code, and the Docker registry holds the corresponding runtime image.
This link between Git commits and image tags makes debugging and rollbacks much easier. If a bug appears in production, you can identify which Git commit created the image, inspect that commit, and if needed redeploy a previously known good image built from an older commit.
Always make it possible to trace a running container back to a specific Git commit by using meaningful image tags or labels that reference the commit hash.
Storing Docker Configuration in Git
Docker related configuration should live alongside your code in the same Git repository. This usually includes the Dockerfile, optional entrypoint scripts, and in more complex setups files like docker-compose.yml that you will see in a different chapter.
Keeping these files under version control ensures that your entire application environment is reproducible. When the code changes and requires a new dependency or a different build step, the Dockerfile changes in the same commit. Anyone who checks out that commit can rebuild the same image.
It is helpful to treat your Docker configuration as part of the application rather than an afterthought. Code reviews should include changes to the Dockerfile and related scripts. This practice keeps your container environment evolving in sync with your source code.
Handling Secrets and Environment Specific Data
Some data must never be stored in Git, especially in public repositories. API keys, private certificates, database passwords, and any other secrets must not appear in the Dockerfile or in committed environment files.
Instead you can keep environment specific values in files that are excluded from Git through .gitignore, or you can rely on environment variables passed at runtime, or use a dedicated secrets management tool. The key rule is that the Git repository contains only generic configuration templates or example values, while each environment supplies real secrets through external means.
Never commit secrets, passwords, or private keys into Git or hard code them in Dockerfiles. Use environment variables, ignored files, or a secrets manager instead.
Using Git Ignore with Docker Related Files
The .gitignore file is important when working with Docker. Builds often create directories like node_modules, target, or dist, as well as intermediate files or volume data. You should instruct Git to ignore these generated files, just as you would in a non Docker project.
When Docker bind mounts a local directory into a container, the container may create logs, caches, or other build artifacts inside your working tree. If these are not ignored, git status becomes noisy and you risk committing files that should stay local. A carefully maintained .gitignore keeps your repository clean and small and avoids merging conflicts for generated content.
Branches, Feature Work, and Temporary Images
In a feature branch workflow, each branch represents a separate line of development in Git. Docker fits naturally into this model because you can build and run images directly from any branch without changing your local environment.
When you check out a different branch, the Dockerfile and the code it depends on may change. Building an image on that branch gives you an isolated environment for that specific feature or fix. The images you build while experimenting do not need to be pushed to a registry. They can remain local and temporary, identified by branch specific tags or even left with the default latest tag if you prefer.
If you later decide to share a branch for testing, you can push both the Git branch and a tagged image built from it. Testers then know which image matches the code they are reviewing.
Commit Hooks and Automation with Docker
Git supports hooks that run when you commit or push. Some teams use these hooks to automate Docker related checks. For example, a pre commit hook might run a lightweight Docker build to validate the Dockerfile syntax, or a pre push hook might run tests inside a container to ensure a basic level of quality before code leaves the developer machine.
Although hooks are optional and local to each clone by default, they demonstrate how tightly you can integrate Docker with everyday Git operations. On shared infrastructure, such as continuous integration servers, Git pushes often trigger automated Docker builds and tests, which you will explore further in the CI and CD chapter.
Collaboration and Reproducibility Across Machines
When a project is correctly configured, a new contributor only needs Git and Docker installed. They clone the repository, build or pull the defined image, and then run the containers as described in the project documentation or helper scripts.
The combination of Git for source and Docker for runtime greatly improves reproducibility. Developers on different operating systems can work on the same project without trying to match system level dependencies by hand. The repository becomes the single source of truth for both the code and the instructions on how it should run in containers.
Over time this approach reduces the typical class of bugs that arise from "it works on my machine" situations. If everyone uses the same image defined in Git, environment differences are minimized and debugging becomes more focused on the code itself.