Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dockerfile versioning best practice

Tags:

git

docker

devops

We are a few developers currently developing a C++ app.

In order to be sure that everyone use the same libraries and dependencies than the remote production server, we are using docker to compile the code source in our localhost.

My question is what the best practices to use git with docker?

  1. Add the Dockerfile to the source code repository
  2. Create a dedicated repository for all our Dockerfiles
  3. Created a dedicated repository for each Dockerfile
  4. Others?
like image 421
Ilan Avatar asked Sep 11 '16 06:09

Ilan


2 Answers

Keep your Dockerfile with the source code. We use labels to add versioning info to the produced image. We add:

  • the git commit and branch
  • whether it's "dirty" meaning that changes were made locally on the src code from what's in git
  • a CI version number (publicly visible)
  • the person who built the image (not the person who last checked in git)

We also tag the image with the commit number.

Here's our code for one of our services. We're using Buildkite for our CI and Quay.io for our image registry.

build-image.sh

echo '===> Building docker image...'

GIT_BRANCH=$(git name-rev --name-only HEAD | sed "s/~.*//")
GIT_COMMIT=$(git rev-parse HEAD)
GIT_COMMIT_SHORT=$(echo $GIT_COMMIT | head -c 8)
GIT_DIRTY='false'
BUILD_CREATOR=$(git config user.email)
BUILD_NUMBER="${BUILDKITE_BUILD_NUMBER-0}"
# Whether the repo has uncommitted changes
if [[ $(git status -s) ]]; then
    GIT_DIRTY='true'
fi

docker build \
  -q \
  -t quay.io/myco/servicename:latest \
  -t quay.io/myco/servicename:"$GIT_COMMIT_SHORT" \
  --build-arg GIT_BRANCH="$GIT_BRANCH" \
  --build-arg GIT_COMMIT="$GIT_COMMIT" \
  --build-arg GIT_DIRTY="$GIT_DIRTY" \
  --build-arg BUILD_CREATOR="$BUILD_CREATOR" \
  --build-arg BUILD_NUMBER="$BUILD_NUMBER" \
  .

echo "Done"
echo "Push to quay using:"
echo "  docker push quay.io/myco/servicename:latest"
echo "  docker push quay.io/myco/servicename:$GIT_COMMIT_SHORT"

Dockerfile

FROM ...

ARG GIT_COMMIT
ARG GIT_BRANCH=master
ARG GIT_DIRTY=undefined
ARG BUILD_CREATOR
ARG BUILD_NUMBER

LABEL branch=$GIT_BRANCH \
    commit=$GIT_COMMIT \
    dirty=$GIT_DIRTY \
    build-creator=$BUILD_CREATOR \
    build-number=$BUILD_NUMBER

... etc

Then you can make scripts that check the version of your image. Eg:

docker inspect --format "{{.ContainerConfig.Labels.commit}}" imageid
like image 179
Bernard Avatar answered Sep 20 '22 13:09

Bernard


I'd go for 2 or 3.

I wouldn't keep the Dockerfile with the sources, because the purpose of each is different:

  • Docker and Dockerfile usually belong to the devops world, and behave independently from the actual software. e.g. Docker is one way of deploying your software, but it's not the only one.
  • your Dockerfile may in the future aggregate software from another git repository - in which repo will you keep it?
  • a change in the software should not systematiaclly impact the version of the Dockerfile repo branch
  • a change in the dockerfile should not impact the version of the Software repo branch

Sometimes tho I can understand that the Dockerfile is so tightly coupled to the software source that in fact you just want to store them all together for simplicity sake. But I'd not make it a standard in any way.

like image 20
Sebas Avatar answered Sep 17 '22 13:09

Sebas