Checkout the repository with git

This changes the build process even further. Instead
f using `wget` to fetch the current code, `git` is used.
This allows for faster switching between branches,
because only the differences between them have to be
fetched from the server.

But the main advantage is that the build cache can
finally be used as designed by Docker. Repetitive
builds are very fast now. This is also true between
branches and tags, as long as the `requirements.txt`
file doesn't change.
This commit is contained in:
Christian Mäder 2019-10-14 21:54:49 +02:00
parent f3b9c34e3b
commit 20109c3392
5 changed files with 149 additions and 166 deletions

View File

@ -28,7 +28,8 @@ RUN pip install --install-option="--prefix=/install" \
# django_auth_ldap is required for ldap # django_auth_ldap is required for ldap
django_auth_ldap django_auth_ldap
COPY .netbox/netbox/requirements.txt / ARG NETBOX_PATH
COPY ${NETBOX_PATH}/requirements.txt /
RUN pip install --install-option="--prefix=/install" -r /requirements.txt RUN pip install --install-option="--prefix=/install" -r /requirements.txt
### ###
@ -53,7 +54,9 @@ RUN apk add --no-cache \
WORKDIR /opt WORKDIR /opt
COPY --from=builder /install /usr/local COPY --from=builder /install /usr/local
COPY .netbox/netbox /opt/netbox
ARG NETBOX_PATH
COPY ${NETBOX_PATH} /opt/netbox
COPY docker/configuration.docker.py /opt/netbox/netbox/netbox/configuration.py COPY docker/configuration.docker.py /opt/netbox/netbox/netbox/configuration.py
COPY configuration/gunicorn_config.py /etc/netbox/config/ COPY configuration/gunicorn_config.py /etc/netbox/config/
@ -69,13 +72,11 @@ ENTRYPOINT [ "/opt/netbox/docker-entrypoint.sh" ]
CMD ["gunicorn", "-c /etc/netbox/config/gunicorn_config.py", "netbox.wsgi"] CMD ["gunicorn", "-c /etc/netbox/config/gunicorn_config.py", "netbox.wsgi"]
LABEL SRC_URL="$URL" LABEL NETBOX_DOCKER_PROJECT_VERSION="custom build" \
NETBOX_BRANCH="custom build" \
ARG NETBOX_DOCKER_PROJECT_VERSION=snapshot ORIGINAL_DOCKER_TAG="custom build" \
LABEL NETBOX_DOCKER_PROJECT_VERSION="$NETBOX_DOCKER_PROJECT_VERSION" NETBOX_GIT_COMMIT="not built from git" \
NETBOX_GIT_URL="not built from git"
ARG NETBOX_BRANCH=custom_build
LABEL NETBOX_BRANCH="$NETBOX_BRANCH"
##### #####
## LDAP specific configuration ## LDAP specific configuration

View File

@ -83,9 +83,6 @@ export VERSION=v2.6.6
docker-compose up -d docker-compose up -d
``` ```
Hint: If you're building a specific version by tag name, the `--no-cache` argument is not strictly necessary.
This can increase the build speed if you're just adjusting the config, for example.
[git-ref]: https://git-scm.com/book/en/v2/Git-Internals-Git-References [git-ref]: https://git-scm.com/book/en/v2/Git-Internals-Git-References
[netbox-github]: https://github.com/netbox-community/netbox/releases [netbox-github]: https://github.com/netbox-community/netbox/releases

View File

@ -18,9 +18,6 @@ fi
ERROR=0 ERROR=0
# Don't build if not on `master` and don't build if on a pull request,
# but build when DEBUG is not empty
for BUILD in "${BUILDS[@]}"; do for BUILD in "${BUILDS[@]}"; do
echo "🛠 Building '$BUILD' from '$DOCKERFILE'" echo "🛠 Building '$BUILD' from '$DOCKERFILE'"
case $BUILD in case $BUILD in

View File

@ -72,42 +72,6 @@ if [ "${PRERELEASE}" == "true" ]; then
fi fi
fi fi
### # shellcheck disable=SC2068
# Compose DOCKER_TAG to build ./build.sh "${VERSION}" $@
### exit $?
if [ -z "$DOCKER_TARGET" ] || [ "$DOCKER_TARGET" == "main" ]; then
DOCKER_TAG="${VERSION}"
else
DOCKER_TAG="${VERSION}-${DOCKER_TARGET}"
fi
###
# Check if the version received is not already available on Docker Hub:
###
ORIGINAL_DOCKERHUB_REPO="${DOCKER_ORG-netboxcommunity}/${DOCKER_REPO-netbox}"
DOCKERHUB_REPO="${DOCKERHUB_REPO-$ORIGINAL_DOCKERHUB_REPO}"
# Bearer Token
URL_DOCKERHUB_TOKEN="https://auth.docker.io/token?service=registry.docker.io&scope=repository:${DOCKERHUB_REPO}:pull"
BEARER_TOKEN="$($CURL "${URL_DOCKERHUB_TOKEN}" | jq -r .token)"
# Actual API call
URL_DOCKERHUB_TAG="https://registry.hub.docker.com/v2/${DOCKERHUB_REPO}/tags/list"
AUTHORIZATION_HEADER="Authorization: Bearer ${BEARER_TOKEN}"
ALREADY_BUILT="$($CURL -H "${AUTHORIZATION_HEADER}" "${URL_DOCKERHUB_TAG}" | jq -e ".tags | any(.==\"${DOCKER_TAG}\")")"
###
# Only build the image if it's not already been built before
###
if [ -n "$DEBUG" ] || [ "$ALREADY_BUILT" == "false" ]; then
if [ -n "$DEBUG" ]; then
echo "⚠️ Would not build, because ${DOCKER_TAG} already exists on https://hub.docker.com/r/${DOCKERHUB_REPO}, but DEBUG is enabled."
fi
# shellcheck disable=SC2068
./build.sh "${VERSION}" $@
exit $?
else
echo "${DOCKER_TAG} already exists on https://hub.docker.com/r/${DOCKERHUB_REPO}"
exit 0
fi

176
build.sh
View File

@ -8,58 +8,78 @@ set -e
if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then if [ "${1}x" == "x" ] || [ "${1}" == "--help" ] || [ "${1}" == "-h" ]; then
echo "Usage: ${0} <branch> [--push|--push-only]" echo "Usage: ${0} <branch> [--push|--push-only]"
echo " branch The branch or tag to build. Required." echo " branch The branch or tag to build. Required."
echo " --push Pushes built the Docker image to the registry." echo " --push Pushes the built Docker image to the registry."
echo " --push-only Does not build. Only pushes the Docker image to the registry." echo " --push-only Only pushes the Docker image to the registry, but does not build it."
echo "" echo ""
echo "You can use the following ENV variables to customize the build:" echo "You can use the following ENV variables to customize the build:"
echo " BRANCH The branch to build." echo " SRC_ORG Which fork of netbox to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})."
echo " Also used for tagging the image." echo " Default: netbox-community"
echo " SRC_REPO The name of the repository to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})."
echo " Default: netbox"
echo " URL Where to fetch the code from."
echo " Must be a git repository. Can be private."
echo " Default: https://github.com/\${SRC_ORG}/\${SRC_REPO}.git"
echo " NETBOX_PATH The path where netbox will be checkout out."
echo " Must not be outside of the netbox-docker repository (because of Docker)!"
echo " Default: .netbox"
echo " SKIP_GIT If defined, git is not invoked and \${NETBOX_PATH} will not be altered."
echo " This may be useful, if you are manually managing the NETBOX_PATH."
echo " Default: undefined"
echo " TAG The version part of the docker tag." echo " TAG The version part of the docker tag."
echo " Default:" echo " Default:"
echo " When <BRANCH>=master: latest" echo " When \${BRANCH}=master: latest"
echo " When <BRANCH>=develop: snapshot" echo " When \${BRANCH}=develop: snapshot"
echo " Else: same as <BRANCH>" echo " Else: same as \${BRANCH}"
echo " DOCKER_ORG The Docker registry (i.e. hub.docker.com/r/<DOCKER_ORG>/<DOCKER_REPO>)" echo " DOCKER_ORG The Docker registry (i.e. hub.docker.com/r/\${DOCKER_ORG}/\${DOCKER_REPO})"
echo " Also used for tagging the image." echo " Also used for tagging the image."
echo " Default: netboxcommunity" echo " Default: netboxcommunity"
echo " DOCKER_REPO The Docker registry (i.e. hub.docker.com/r/<DOCKER_ORG>/<DOCKER_REPO>)" echo " DOCKER_REPO The Docker registry (i.e. hub.docker.com/r/\${DOCKER_ORG}/\${DOCKER_REPO})"
echo " Also used for tagging the image." echo " Also used for tagging the image."
echo " Default: netbox" echo " Default: netbox"
echo " DOCKER_FROM The base image to use." echo " DOCKER_FROM The base image to use."
echo " Default: Whatever is defined as default in the Dockerfile." echo " Default: Whatever is defined as default in the Dockerfile."
echo " DOCKER_TAG The name of the tag which is applied to the image." echo " DOCKER_TAG The name of the tag which is applied to the image."
echo " Useful for pushing into another registry than hub.docker.com." echo " Useful for pushing into another registry than hub.docker.com."
echo " Default: <DOCKER_ORG>/<DOCKER_REPO>:<BRANCH>" echo " Default: \${DOCKER_ORG}/\${DOCKER_REPO}:\${TAG}"
echo " DOCKER_SHORT_TAG The name of the short tag which is applied to the" echo " DOCKER_SHORT_TAG The name of the short tag which is applied to the"
echo " image. This is used to tag all patch releases to their" echo " image. This is used to tag all patch releases to their"
echo " containing version e.g. v2.5.1 -> v2.5" echo " containing version e.g. v2.5.1 -> v2.5"
echo " Default: <DOCKER_ORG>/<DOCKER_REPO>:\$MAJOR.\$MINOR" echo " Default: \${DOCKER_ORG}/\${DOCKER_REPO}:<MAJOR>.<MINOR>"
echo " DOCKERFILE The name of Dockerfile to use." echo " DOCKERFILE The name of Dockerfile to use."
echo " Default: Dockerfile" echo " Default: Dockerfile"
echo " DOCKER_TARGET A specific target to build." echo " DOCKER_TARGET A specific target to build."
echo " It's currently not possible to pass multiple targets." echo " It's currently not possible to pass multiple targets."
echo " Default: main ldap" echo " Default: main ldap"
echo " SRC_ORG Which fork of netbox to use (i.e. github.com/<SRC_ORG>/<SRC_REPO>)."
echo " Default: netbox-community"
echo " SRC_REPO The name of the netbox for to use (i.e. github.com/<SRC_ORG>/<SRC_REPO>)."
echo " Default: netbox"
echo " URL Where to fetch the package from."
echo " Must be a tar.gz file of the source code."
echo " Default: https://github.com/<SRC_ORG>/<SRC_REPO>/archive/\$BRANCH.tar.gz"
echo " HTTP_PROXY The proxy to use for http requests." echo " HTTP_PROXY The proxy to use for http requests."
echo " Example: http://proxy.domain.tld:3128" echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty" echo " Default: undefined"
echo " HTTPS_PROXY The proxy to use for https requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty"
echo " FTP_PROXY The proxy to use for ftp requests."
echo " Example: http://proxy.domain.tld:3128"
echo " Default: empty"
echo " NO_PROXY Comma-separated list of domain extensions proxy should not be used for." echo " NO_PROXY Comma-separated list of domain extensions proxy should not be used for."
echo " Example: .domain1.tld,.domain2.tld" echo " Example: .domain1.tld,.domain2.tld"
echo " Default: empty" echo " Default: undefined"
echo " DEBUG If defined, the script does not stop when certain checks are unsatisfied." echo " DEBUG If defined, the script does not stop when certain checks are unsatisfied."
echo " Default: undefined"
echo " DRY_RUN Prints all build statements instead of running them." echo " DRY_RUN Prints all build statements instead of running them."
echo " Default: undefined"
echo ""
echo "Examples:"
echo " ${0} master"
echo " This will fetch the latest 'master' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:latest'."
echo " ${0} develop"
echo " This will fetch the latest 'develop' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:snapshot'."
echo " ${0} v2.6.6"
echo " This will fetch the 'v2.6.6' tag, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:v2.6.6' and 'netboxcommunity/netbox:v2.6'."
echo " ${0} develop-2.7"
echo " This will fetch the 'develop-2.7' branch, build a Docker Image and tag it"
echo " 'netboxcommunity/netbox:develop-2.7'."
echo " SRC_ORG=cimnine ${0} feature-x"
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,"
echo " build a Docker Image and tag it 'netboxcommunity/netbox:feature-x'."
echo " SRC_ORG=cimnine DOCKER_ORG=cimnine ${0} feature-x"
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,"
echo " build a Docker Image and tag it 'cimnine/netbox:feature-x'."
if [ "${1}x" == "x" ]; then if [ "${1}x" == "x" ]; then
exit 1 exit 1
@ -71,7 +91,7 @@ fi
### ###
# Determining the build command to use # Determining the build command to use
### ###
if [ -z "$DRY_RUN" ]; then if [ -z "${DRY_RUN}" ]; then
DRY="" DRY=""
else else
echo "⚠️ DRY_RUN MODE ON ⚠️" echo "⚠️ DRY_RUN MODE ON ⚠️"
@ -90,26 +110,31 @@ NETBOX_DOCKER_PROJECT_VERSION="${NETBOX_DOCKER_PROJECT_VERSION-$(sed -e 's/^[[:s
SRC_ORG="${SRC_ORG-netbox-community}" SRC_ORG="${SRC_ORG-netbox-community}"
SRC_REPO="${SRC_REPO-netbox}" SRC_REPO="${SRC_REPO-netbox}"
BRANCH="${1}" BRANCH="${1}"
URL="${URL-https://github.com/${SRC_ORG}/${SRC_REPO}/archive/$BRANCH.tar.gz}" URL="${URL-https://github.com/${SRC_ORG}/${SRC_REPO}.git}"
### ###
# fetching the source # fetching the source
### ###
if [ "${2}" != "--push-only" ] ; then if [ "${2}" != "--push-only" ] ; then
echo "🗑️ Preparing" NETBOX_PATH="${NETBOX_PATH-.netbox}"
$DRY rm -rf .netbox echo "🌐 Checking out '${BRANCH}' of netbox from the url '${URL}' into '${NETBOX_PATH}'"
$DRY mkdir .netbox if [ ! -d "${NETBOX_PATH}" ]; then
echo "✅ Done preparing" $DRY git clone -q --depth 10 -b "${BRANCH}" "${URL}" "${NETBOX_PATH}"
fi
echo "🌐 Downloading netbox from the url '${URL}'"
( (
$DRY cd .netbox $DRY cd "${NETBOX_PATH}"
$DRY wget -qO netbox.tgz "${URL}" && \ if [ -n "${HTTP_PROXY}" ]; then
$DRY tar -xzf netbox.tgz && \ git config http.proxy "${HTTP_PROXY}"
$DRY mv netbox-* netbox fi
$DRY git remote set-url origin "${URL}"
$DRY git fetch -qpP --depth 10 origin "${BRANCH}"
$DRY git checkout -qf FETCH_HEAD
$DRY git prune
) )
echo "✅ Downloaded netbox" echo "✅ Checked out netbox"
fi fi
### ###
@ -120,7 +145,7 @@ DOCKERFILE="${DOCKERFILE-Dockerfile}"
if [ ! -f "${DOCKERFILE}" ]; then if [ ! -f "${DOCKERFILE}" ]; then
echo "🚨 The Dockerfile ${DOCKERFILE} doesn't exist." echo "🚨 The Dockerfile ${DOCKERFILE} doesn't exist."
if [ -z "$DEBUG" ]; then if [ -z "${DEBUG}" ]; then
exit 1 exit 1
else else
echo "⚠️ Would exit here with code '1', but DEBUG is enabled." echo "⚠️ Would exit here with code '1', but DEBUG is enabled."
@ -152,13 +177,13 @@ echo "🏭 Building the following targets:" "${DOCKER_TARGETS[@]}"
# Build each target # Build each target
### ###
for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
echo "🏗 Building the target '$DOCKER_TARGET'" echo "🏗 Building the target '${DOCKER_TARGET}'"
### ###
# composing the final TARGET_DOCKER_TAG # composing the final TARGET_DOCKER_TAG
### ###
TARGET_DOCKER_TAG="${DOCKER_TAG-${DOCKER_ORG}/${DOCKER_REPO}:${TAG}}" TARGET_DOCKER_TAG="${DOCKER_TAG-${DOCKER_ORG}/${DOCKER_REPO}:${TAG}}"
if [ "$DOCKER_TARGET" != "main" ]; then if [ "${DOCKER_TARGET}" != "main" ]; then
TARGET_DOCKER_TAG="${TARGET_DOCKER_TAG}-${DOCKER_TARGET}" TARGET_DOCKER_TAG="${TARGET_DOCKER_TAG}-${DOCKER_TARGET}"
fi fi
@ -173,57 +198,63 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-${DOCKER_ORG}/${DOCKER_REPO}:v${MAJOR}.${MINOR}}" DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG-${DOCKER_ORG}/${DOCKER_REPO}:v${MAJOR}.${MINOR}}"
if [ "$DOCKER_TARGET" != "main" ]; then if [ "${DOCKER_TARGET}" != "main" ]; then
DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG}-${DOCKER_TARGET}" DOCKER_SHORT_TAG="${DOCKER_SHORT_TAG}-${DOCKER_TARGET}"
fi fi
fi fi
### ###
# Composing global Docker CLI arguments # Proceeding to buils stage, except if `--push-only` is passed
### ###
DOCKER_OPTS=( if [ "${2}" != "--push-only" ] ; then
--pull
--target "$DOCKER_TARGET"
)
### ###
# Composing arguments for `docker build` CLI # Composing all arguments for `docker build`
### ###
DOCKER_BUILD_ARGS=( DOCKER_BUILD_ARGS=(
--build-arg "NETBOX_DOCKER_PROJECT_VERSION=${NETBOX_DOCKER_PROJECT_VERSION}" --pull
--build-arg "NETBOX_BRANCH=${BRANCH}" --target "${DOCKER_TARGET}"
--build-arg "DOCKER_ORG=${DOCKER_ORG}" -f "${DOCKERFILE}"
-t "${TARGET_DOCKER_TAG}"
)
if [ -n "${DOCKER_SHORT_TAG}" ]; then
DOCKER_BUILD_ARGS+=( -t "${DOCKER_SHORT_TAG}" )
fi
# --label
DOCKER_BUILD_ARGS+=(
--label "NETBOX_DOCKER_PROJECT_VERSION=${NETBOX_DOCKER_PROJECT_VERSION}"
--label "NETBOX_BRANCH=${BRANCH}"
--label "ORIGINAL_DOCKER_TAG=${TARGET_DOCKER_TAG}"
)
if [ -d "${NETBOX_PATH}/.git" ]; then
DOCKER_BUILD_ARGS+=(
--label "NETBOX_GIT_COMMIT=$($DRY cd ${NETBOX_PATH}; $DRY git rev-parse HEAD)"
--label "NETBOX_GIT_URL=$($DRY cd ${NETBOX_PATH}; $DRY git remote get-url origin)"
)
fi
# --build-arg
DOCKER_BUILD_ARGS+=(
--build-arg "NETBOX_PATH=${NETBOX_PATH}"
--build-arg "DOCKER_REPO=${DOCKER_REPO}" --build-arg "DOCKER_REPO=${DOCKER_REPO}"
) )
if [ -n "$DOCKER_FROM" ]; then if [ -n "${DOCKER_FROM}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "FROM=${DOCKER_FROM}" ) DOCKER_BUILD_ARGS+=( --build-arg "FROM=${DOCKER_FROM}" )
fi fi
if [ -n "$HTTP_PROXY" ]; then if [ -n "${HTTP_PROXY}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "http_proxy=${HTTP_PROXY}" ) DOCKER_BUILD_ARGS+=( --build-arg "http_proxy=${HTTP_PROXY}" )
fi
if [ -n "$HTTPS_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "https_proxy=${HTTPS_PROXY}" ) DOCKER_BUILD_ARGS+=( --build-arg "https_proxy=${HTTPS_PROXY}" )
fi fi
if [ -n "$FTP_PROXY" ]; then if [ -n "${NO_PROXY}" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "ftp_proxy=${FTP_PROXY}" )
fi
if [ -n "$NO_PROXY" ]; then
DOCKER_BUILD_ARGS+=( --build-arg "no_proxy=${NO_PROXY}" ) DOCKER_BUILD_ARGS+=( --build-arg "no_proxy=${NO_PROXY}" )
fi fi
### ###
# Building the docker images, except if `--push-only` is passed # Building the docker image
### ###
if [ "${2}" != "--push-only" ] ; then
echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG}'." echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG}'."
$DRY docker build -t "${TARGET_DOCKER_TAG}" "${DOCKER_BUILD_ARGS[@]}" "${DOCKER_OPTS[@]}" -f "${DOCKERFILE}" . $DRY docker build "${DOCKER_BUILD_ARGS[@]}" .
echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG}'" echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG}'"
if [ -n "$DOCKER_SHORT_TAG" ]; then
echo "🐳 Tagging image '${DOCKER_SHORT_TAG}'."
$DRY docker tag "${TARGET_DOCKER_TAG}" "${DOCKER_SHORT_TAG}"
echo "✅ Tagged image '${DOCKER_SHORT_TAG}'"
fi
fi fi
### ###
@ -241,10 +272,3 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
fi fi
fi fi
done done
###
# Cleaning up
###
echo "🗑️ Cleaning up"
$DRY rm -rf .netbox
echo "✅ Cleaned up"