Build multi-arch images based on Debian

This commit is contained in:
Christian Mäder 2021-03-12 16:55:51 +01:00
parent b0261e8cc6
commit 7ec68ecccb
6 changed files with 465 additions and 350 deletions

View File

@ -13,12 +13,15 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Checks syntax of our code name: Checks syntax of our code
steps: steps:
- uses: actions/checkout@v2 -
uses: actions/checkout@v2
with: with:
# Full git history is needed to get a proper list of changed files within `super-linter` # Full git history is needed to get a proper list of changed files within `super-linter`
fetch-depth: 0 fetch-depth: 0
- uses: actions/setup-python@v2 -
- name: Lint Code Base uses: actions/setup-python@v2
-
name: Lint Code Base
uses: github/super-linter@v4 uses: github/super-linter@v4
env: env:
DEFAULT_BRANCH: develop DEFAULT_BRANCH: develop
@ -35,8 +38,9 @@ jobs:
PYTHON_BLACK_CONFIG_FILE: pyproject.toml PYTHON_BLACK_CONFIG_FILE: pyproject.toml
PYTHON_FLAKE8_CONFIG_FILE: .flake8 PYTHON_FLAKE8_CONFIG_FILE: .flake8
PYTHON_ISORT_CONFIG_FILE: pyproject.toml PYTHON_ISORT_CONFIG_FILE: pyproject.toml
build: build:
continue-on-error: ${{ matrix.docker_from == 'alpine:edge' }} continue-on-error: ${{ matrix.build_cmd != './build-latest.sh' }}
strategy: strategy:
matrix: matrix:
build_cmd: build_cmd:
@ -44,23 +48,39 @@ jobs:
- PRERELEASE=true ./build-latest.sh - PRERELEASE=true ./build-latest.sh
- ./build.sh feature - ./build.sh feature
- ./build.sh develop - ./build.sh develop
docker_from: platform:
- '' # use the default of the build script - linux/amd64
- alpine:edge - linux/arm64
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Builds new NetBox Docker Images name: Builds new NetBox Docker Images
steps: steps:
- id: git-checkout -
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- id: docker-build -
name: Build the image from '${{ matrix.docker_from }}' with '${{ matrix.build_cmd }}' name: Get Version of NetBox Docker
run: |
echo "::set-output name=version::$(cat VERSION)"
shell: bash
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
id: buildx-setup
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
install: true
-
id: docker-build
name: Build the image with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }} run: ${{ matrix.build_cmd }}
env: env:
DOCKER_FROM: ${{ matrix.docker_from }}
GH_ACTION: enable GH_ACTION: enable
- id: docker-test BUILDX_BUILDER_NAME: ${{ steps.buildx-setup.outputs.name }}
BUILDX_PLATFORMS: ${{ matrix.platform }}
-
name: Test the image name: Test the image
run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'

View File

@ -1,9 +1,9 @@
name: release name: release
on: on:
push: release:
branches: types:
- release - published
schedule: schedule:
- cron: '45 5 * * *' - cron: '45 5 * * *'
@ -16,68 +16,88 @@ jobs:
- PRERELEASE=true ./build-latest.sh - PRERELEASE=true ./build-latest.sh
- ./build.sh feature - ./build.sh feature
- ./build.sh develop - ./build.sh develop
platform:
- linux/amd64,linux/arm64
fail-fast: false fail-fast: false
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: Builds new NetBox Docker Images name: Builds new NetBox Docker Images
steps: steps:
- id: git-checkout -
name: Checkout name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
- id: docker-build -
name: Get Version of NetBox Docker
run: |
echo "::set-output name=version::$(cat VERSION)"
shell: bash
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
id: buildx-setup
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
with:
install: true
-
name: Available platforms
run: echo ${{ steps.buildx-setup.outputs.platforms }}
-
id: docker-build
name: Build the image with '${{ matrix.build_cmd }}' name: Build the image with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }} run: ${{ matrix.build_cmd }}
env: env:
GH_ACTION: enable GH_ACTION: enable
- id: docker-test BUILDX_BUILDER_NAME: ${{ steps.buildx-setup.outputs.name }}
BUILDX_PLATFORMS: ${{ matrix.platform }}
-
name: Test the image name: Test the image
run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh run: IMAGE="${FINAL_DOCKER_TAG}" ./test.sh
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'
- id: registry-login -
name: Login to the Docker Registry name: Login to docker.io
run: | uses: docker/login-action@v1
echo "::add-mask::$DOCKERHUB_USERNAME" with:
echo "::add-mask::$DOCKERHUB_PASSWORD" registry: docker.io
docker login -u "$DOCKERHUB_USERNAME" --password "${DOCKERHUB_PASSWORD}" "${DOCKER_REGISTRY}" username: ${{ secrets.dockerhub_username }}
env: password: ${{ secrets.dockerhub_password }}
DOCKERHUB_USERNAME: ${{ secrets.dockerhub_username }}
DOCKERHUB_PASSWORD: ${{ secrets.dockerhub_password }}
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'
- id: registry-push -
name: Push the image name: Push the image to docker.io
run: ${{ matrix.build_cmd }} --push-only run: ${{ matrix.build_cmd }} --push-only
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'
- id: registry-logout
name: Logout of the Docker Registry
run: docker logout "${DOCKER_REGISTRY}"
if: steps.docker-build.outputs.skipped != 'true'
# Quay.io # quay.io
- id: quayio-docker-build -
name: Build the image with '${{ matrix.build_cmd }}' name: Login to Quay.io
run: ${{ matrix.build_cmd }} uses: docker/login-action@v1
with:
registry: quay.io
username: ${{ secrets.quayio_username }}
password: ${{ secrets.quayio_password }}
if: steps.docker-build.outputs.skipped != 'true'
-
name: Build and push the image with '${{ matrix.build_cmd }}'
run: ${{ matrix.build_cmd }} --push
env: env:
DOCKER_REGISTRY: quay.io DOCKER_REGISTRY: quay.io
GH_ACTION: enable GH_ACTION: enable
- id: quayio-registry-login
name: Login to the Quay.io Registry
run: |
echo "::add-mask::$QUAYIO_USERNAME"
echo "::add-mask::$QUAYIO_PASSWORD"
docker login -u "$QUAYIO_USERNAME" --password "${QUAYIO_PASSWORD}" "${DOCKER_REGISTRY}"
env:
DOCKER_REGISTRY: quay.io
QUAYIO_USERNAME: ${{ secrets.quayio_username }}
QUAYIO_PASSWORD: ${{ secrets.quayio_password }}
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'
- id: quayio-registry-push
name: Push the image # ghcr.io
run: ${{ matrix.build_cmd }} --push-only -
env: name: Login to GitHub Container Registry
DOCKER_REGISTRY: quay.io uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'
- id: quayio-registry-logout -
name: Logout of the Docker Registry name: Build and push the image with '${{ matrix.build_cmd }}'
run: docker logout "${DOCKER_REGISTRY}" run: ${{ matrix.build_cmd }} --push
env: env:
DOCKER_REGISTRY: quay.io DOCKER_REGISTRY: ghcr.io
DOCKER_ORG: netbox-community
GH_ACTION: enable
if: steps.docker-build.outputs.skipped != 'true' if: steps.docker-build.outputs.skipped != 'true'

1
.gitignore vendored
View File

@ -13,3 +13,4 @@ configuration/ldap/*
!configuration/plugins.py !configuration/plugins.py
prometheus.yml prometheus.yml
super-linter.log super-linter.log
.buildx-cache

View File

@ -1,44 +1,31 @@
ARG FROM ARG FROM
FROM ${FROM} as builder FROM ${FROM} as builder
RUN apk add --no-cache \ ENV DEBIAN_FRONTEND=noninteractive
bash \ RUN apt-get update -qq \
build-base \ && apt-get install \
cargo \ --yes -qq --no-install-recommends \
build-essential \
ca-certificates \ ca-certificates \
cmake \
cyrus-sasl-dev \
git \
graphviz \ graphviz \
jpeg-dev \
libevent-dev \ libevent-dev \
libffi-dev \ libffi-dev \
libxslt-dev \ libjpeg-dev \
make \ libldap-dev \
musl-dev \ libsasl2-dev \
openldap-dev \ libxslt1-dev \
postgresql-dev \ libxml2-dev \
py3-pip \ postgresql-13 \
python3-dev \ python3-dev \
python3-pip \
python3-venv \
&& python3 -m venv /opt/netbox/venv \ && python3 -m venv /opt/netbox/venv \
&& /opt/netbox/venv/bin/python3 -m pip install --upgrade \ && /opt/netbox/venv/bin/python3 -m pip install --upgrade \
pip \ pip \
setuptools \ setuptools \
wheel wheel
# Build libcrc32c for google-crc32c python module WORKDIR /opt/netbox/
RUN git clone https://github.com/google/crc32c \
&& cd crc32c \
&& git submodule update --init --recursive \
&& mkdir build \
&& cd build \
&& cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCRC32C_BUILD_TESTS=no \
-DCRC32C_BUILD_BENCHMARKS=no \
-DBUILD_SHARED_LIBS=yes \
.. \
&& make all install
ARG NETBOX_PATH ARG NETBOX_PATH
COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt / COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt /
@ -53,34 +40,39 @@ RUN /opt/netbox/venv/bin/pip install \
ARG FROM ARG FROM
FROM ${FROM} as main FROM ${FROM} as main
RUN apk add --no-cache \ ENV DEBIAN_FRONTEND=noninteractive
bash \ RUN . /etc/os-release \
&& apt-get update -qq \
&& apt-get upgrade \
--yes -qq --no-install-recommends \
&& apt-get install \
--yes -qq --no-install-recommends \
ca-certificates \ ca-certificates \
curl \ curl \
graphviz \
libevent \
libffi \
libjpeg-turbo \
libxslt \
openssl \ openssl \
postgresql-libs \
py3-pip \
python3 \ python3 \
tini \ python3-distutils \
&& curl -sL https://nginx.org/keys/nginx_signing.key | \
tee /etc/apt/trusted.gpg.d/nginx.asc \
&& echo "deb https://packages.nginx.org/unit/debian/ ${VERSION_CODENAME} unit" | \
tee /etc/apt/sources.list.d/unit.list \
&& apt-get update -qq \
&& apt-get install \
--yes -qq --no-install-recommends \
unit \ unit \
unit-python3 unit-python3.9 \
tini \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /opt WORKDIR /opt
COPY --from=builder /usr/local/lib/libcrc32c.* /usr/local/lib/
COPY --from=builder /usr/local/include/crc32c /usr/local/include
COPY --from=builder /usr/local/lib/cmake/Crc32c /usr/local/lib/cmake/
COPY --from=builder /opt/netbox/venv /opt/netbox/venv COPY --from=builder /opt/netbox/venv /opt/netbox/venv
ARG NETBOX_PATH ARG NETBOX_PATH
COPY ${NETBOX_PATH} /opt/netbox 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 docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py
COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh
COPY docker/housekeeping.sh /opt/netbox/housekeeping.sh COPY docker/housekeeping.sh /opt/netbox/housekeeping.sh
COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh
@ -89,17 +81,18 @@ COPY initializers/ /opt/netbox/initializers/
COPY configuration/ /etc/netbox/config/ COPY configuration/ /etc/netbox/config/
COPY docker/nginx-unit.json /etc/unit/ COPY docker/nginx-unit.json /etc/unit/
WORKDIR /opt/netbox/netbox WORKDIR /opt/netbox
# Must set permissions for '/opt/netbox/netbox/media' directory # Must set permissions for '/opt/netbox/netbox/media' directory
# to g+w so that pictures can be uploaded to netbox. # to g+w so that pictures can be uploaded to netbox.
RUN mkdir -p static /opt/unit/state/ /opt/unit/tmp/ \ RUN mkdir -p static /opt/unit/state/ /opt/unit/tmp/ \
&& chmod -R g+w media /opt/unit/ \ && chmod -R g+w /opt/netbox/netbox/media /opt/unit/ \
&& cd /opt/netbox/ && /opt/netbox/venv/bin/python -m mkdocs build \ && /opt/netbox/venv/bin/python -m mkdocs build \
--config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \ --config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \
&& SECRET_KEY="dummy" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input && SECRET_KEY="dummy" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input
ENTRYPOINT [ "/sbin/tini", "--" ] WORKDIR /opt/netbox/netbox
ENTRYPOINT [ "/usr/bin/tini", "--" ]
CMD [ "/opt/netbox/docker-entrypoint.sh", "/opt/netbox/launch-netbox.sh" ] CMD [ "/opt/netbox/docker-entrypoint.sh", "/opt/netbox/launch-netbox.sh" ]
@ -107,18 +100,6 @@ LABEL ORIGINAL_TAG="" \
NETBOX_GIT_BRANCH="" \ NETBOX_GIT_BRANCH="" \
NETBOX_GIT_REF="" \ NETBOX_GIT_REF="" \
NETBOX_GIT_URL="" \ NETBOX_GIT_URL="" \
# See http://label-schema.org/rc1/#build-time-labels
# Also https://microbadger.com/labels
org.label-schema.schema-version="1.0" \
org.label-schema.build-date="" \
org.label-schema.name="NetBox Docker" \
org.label-schema.description="A container based distribution of NetBox, the free and open IPAM and DCIM solution." \
org.label-schema.vendor="The netbox-docker contributors." \
org.label-schema.url="https://github.com/netbox-community/netbox-docker" \
org.label-schema.usage="https://github.com/netbox-community/netbox-docker/wiki" \
org.label-schema.vcs-url="https://github.com/netbox-community/netbox-docker.git" \
org.label-schema.vcs-ref="" \
org.label-schema.version="snapshot" \
# See https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys # See https://github.com/opencontainers/image-spec/blob/master/annotations.md#pre-defined-annotation-keys
org.opencontainers.image.created="" \ org.opencontainers.image.created="" \
org.opencontainers.image.title="NetBox Docker" \ org.opencontainers.image.title="NetBox Docker" \
@ -131,16 +112,3 @@ LABEL ORIGINAL_TAG="" \
org.opencontainers.image.source="https://github.com/netbox-community/netbox-docker.git" \ org.opencontainers.image.source="https://github.com/netbox-community/netbox-docker.git" \
org.opencontainers.image.revision="" \ org.opencontainers.image.revision="" \
org.opencontainers.image.version="snapshot" org.opencontainers.image.version="snapshot"
#####
## LDAP specific configuration
#####
FROM main as ldap
RUN apk add --no-cache \
libsasl \
libldap \
util-linux
COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py

View File

@ -3,6 +3,8 @@
echo "▶️ $0 $*" echo "▶️ $0 $*"
source ./build-functions/gh-functions.sh
### ###
# Checking for the presence of GITHUB_OAUTH_CLIENT_ID # Checking for the presence of GITHUB_OAUTH_CLIENT_ID
# and GITHUB_OAUTH_CLIENT_SECRET # and GITHUB_OAUTH_CLIENT_SECRET
@ -67,10 +69,7 @@ if [ "${PRERELEASE}" == "true" ]; then
echo "❎ Latest unstable version '${VERSION}' is not higher than the latest stable version '$STABLE_VERSION'." echo "❎ Latest unstable version '${VERSION}' is not higher than the latest stable version '$STABLE_VERSION'."
if [ -z "$DEBUG" ]; then if [ -z "$DEBUG" ]; then
if [ -n "${GH_ACTION}" ]; then gh_echo "::set-output name=skipped::true"
echo "::set-output name=skipped::true"
fi
exit 0 exit 0
else else
echo "⚠️ Would exit here with code '0', but DEBUG is enabled." echo "⚠️ Would exit here with code '0', but DEBUG is enabled."

333
build.sh
View File

@ -6,87 +6,138 @@ echo "▶️ $0 $*"
set -e 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]" cat <<END_OF_DOCS
echo " branch The branch or tag to build. Required." Usage: ${0} <branch> [--push|--push-only]
echo " --push Pushes the built Docker image to the registry." branch The branch or tag to build. Required.
echo " --push-only Only pushes the Docker image to the registry, but does not build it." --push Pushes the built Docker image to the registry.
echo "" --push-only Only pushes the Docker image to the registry, but does not build it.
echo "You can use the following ENV variables to customize the build:"
echo " SRC_ORG Which fork of netbox to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})." You can use the following ENV variables to customize the build:
echo " Default: netbox-community" SRC_ORG Which fork of netbox to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO}).
echo " SRC_REPO The name of the repository to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO})." Default: 'netbox-community'
echo " Default: netbox" SRC_REPO The name of the repository to use (i.e. github.com/\${SRC_ORG}/\${SRC_REPO}).
echo " URL Where to fetch the code from." Default: 'netbox'
echo " Must be a git repository. Can be private." URL Where to fetch the code from.
echo " Default: https://github.com/\${SRC_ORG}/\${SRC_REPO}.git" Must be a git repository. Can be private.
echo " NETBOX_PATH The path where netbox will be checkout out." Default: 'https://github.com/\${SRC_ORG}/\${SRC_REPO}.git'
echo " Must not be outside of the netbox-docker repository (because of Docker)!" NETBOX_PATH The path where netbox will be checkout out.
echo " Default: .netbox" Must not be outside of the netbox-docker repository (because of Docker)!
echo " SKIP_GIT If defined, git is not invoked and \${NETBOX_PATH} will not be altered." Default: '.netbox'
echo " This may be useful, if you are manually managing the NETBOX_PATH." SKIP_GIT If defined, git is not invoked and \${NETBOX_PATH} will not be altered.
echo " Default: undefined" This may be useful, if you are manually managing the NETBOX_PATH.
echo " TAG The version part of the docker tag." Example: 'on'
echo " Default:" Default: undefined
echo " When <branch>=master: latest" TAG The version part of the docker tag.
echo " When <branch>=develop: snapshot" Default:
echo " Else: same as <branch>" When <branch>=master: 'latest'
echo " DOCKER_REGISTRY The Docker repository's registry (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" When <branch>=develop: 'snapshot'
echo " Used for tagging the image." Else: same as <branch>
echo " Default: docker.io" DOCKER_REGISTRY
echo " DOCKER_ORG The Docker repository's organisation (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" The Docker repository's registry (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')
echo " Used for tagging the image." Used for tagging the image.
echo " Default: netboxcommunity" Default: 'docker.io'
echo " DOCKER_REPO The Docker repository's name (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')" DOCKER_ORG The Docker repository's organisation (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')
echo " Used for tagging the image." Used for tagging the image.
echo " Default: netbox" Default: 'netboxcommunity'
echo " DOCKER_TAG The name of the tag which is applied to the image." DOCKER_REPO The Docker repository's name (i.e. '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}'')
echo " Useful for pushing into another registry than hub.docker.com." Used for tagging the image.
echo " Default: \${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:\${TAG}" Default: 'netbox'
echo " DOCKER_SHORT_TAG The name of the short tag which is applied to the" DOCKER_TAG The name of the tag which is applied to the image.
echo " image. This is used to tag all patch releases to their" Useful for pushing into another registry than hub.docker.com.
echo " containing version e.g. v2.5.1 -> v2.5" Default: '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:\${TAG}'
echo " Default: \${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:<MAJOR>.<MINOR>" DOCKER_SHORT_TAG
echo " DOCKERFILE The name of Dockerfile to use." The name of the short tag which is applied to the image.
echo " Default: Dockerfile" This is used to tag all patch releases to their containing version, e.g. v2.5.1 -> v2.5.
echo " DOCKER_FROM The base image to use." Default: '\${DOCKER_REGISTRY}/\${DOCKER_ORG}/\${DOCKER_REPO}:<MAJOR>.<MINOR>'
echo " Default: 'alpine:3.14'" DOCKERFILE The name of Dockerfile to use.
echo " DOCKER_TARGET A specific target to build." Default: 'Dockerfile'
echo " It's currently not possible to pass multiple targets." DOCKER_FROM The base image to use.
echo " Default: main ldap" Default: 'debian:11-slim'
echo " HTTP_PROXY The proxy to use for http requests." DOCKER_TARGET
echo " Example: http://proxy.domain.tld:3128" A specific target to build.
echo " Default: undefined" It's currently not possible to pass multiple targets.
echo " NO_PROXY Comma-separated list of domain extensions proxy should not be used for." Default: 'main ldap'
echo " Example: .domain1.tld,.domain2.tld" BUILDX_PLATFORMS
echo " Default: undefined" Specifies the platform(s) to build the image for.
echo " DEBUG If defined, the script does not stop when certain checks are unsatisfied." Example: 'linux/amd64,linux/arm64'
echo " Default: undefined" Default: 'linux/amd64'
echo " DRY_RUN Prints all build statements instead of running them." BUILDX_BUILDER_NAME
echo " Default: undefined" If defined, the image build will be assigned to the given builder.
echo " GH_ACTION If defined, special 'echo' statements are enabled that set the" If you specify this variable, make sure that the builder exists.
echo " following environment variables in Github Actions:" If this value is not defined, a new builx builder with the directory name of the
echo " - FINAL_DOCKER_TAG: The final value of the DOCKER_TAG env variable" current directory (i.e. '$(basename "${PWD}")') is created.
echo " Default: undefined" Example: 'clever_lovelace'
echo "" Default: undefined
echo "Examples:" BUILDX_REMOVE_BUILDER
echo " ${0} master" If defined (and only if BUILDX_BUILDER_NAME is undefined),
echo " This will fetch the latest 'master' branch, build a Docker Image and tag it" then the buildx builder created by this script will be removed after use.
echo " 'netboxcommunity/netbox:latest'." This is useful if you build NetBox Docker on an automated system that does
echo " ${0} develop" not manage the builders for you.
echo " This will fetch the latest 'develop' branch, build a Docker Image and tag it" Example: 'on'
echo " 'netboxcommunity/netbox:snapshot'." Default: undefined
echo " ${0} v2.6.6" BUILDX_LOCAL_CACHE
echo " This will fetch the 'v2.6.6' tag, build a Docker Image and tag it" The directory to use for reading and writign the local buildx cache.
echo " 'netboxcommunity/netbox:v2.6.6' and 'netboxcommunity/netbox:v2.6'." Default: '.buildx-cache'
echo " ${0} develop-2.7" BUILDX_CACHE_FROM_DOCKER_TAG
echo " This will fetch the 'develop-2.7' branch, build a Docker Image and tag it" The tag used for pulling the remote cache.
echo " 'netboxcommunity/netbox:develop-2.7'." Default: '\${DOCKER_TAG}-cache'
echo " SRC_ORG=cimnine ${0} feature-x" BUILDX_CACHE_TO_DOCKER_TAG
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git," The tag used for pushing the remote cache.
echo " build a Docker Image and tag it 'netboxcommunity/netbox:feature-x'." Default: '\${DOCKER_TAG}-cache'
echo " SRC_ORG=cimnine DOCKER_ORG=cimnine ${0} feature-x" BUILDX_PULL_REMOTE_CACHE
echo " This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git," If defined, buildx will try pulling a remote cache from the registry.
echo " build a Docker Image and tag it 'cimnine/netbox:feature-x'." Example: 'on'
Default: undefined
BUILDX_PUSH_REMOTE_CACHE
If defined, buildx will be configured to push it's cache the remote registry
after a successful build.
Example: 'on'
Default: undefined
HTTP_PROXY The proxy to use for http requests.
Example: 'http://proxy.domain.tld:3128'
Default: undefined
NO_PROXY Comma-separated list of domain extensions proxy should not be used for.
Example: '.domain1.tld,.domain2.tld'
Default: undefined
DEBUG If defined, the script does not stop when certain checks are not satisfied.
Example: 'on'
Default: undefined
DRY_RUN Prints all build statements instead of running them.
Example: 'on'
Default: undefined
GH_ACTION If defined, special 'echo' statements are enabled that set the
following environment variables in Github Actions:
- FINAL_DOCKER_TAG: The final value of the DOCKER_TAG env variable
Default: undefined
Examples:
${0} master
This will fetch the latest 'master' branch, build a Docker Image and tag it
'netboxcommunity/netbox:latest'.
${0} develop
This will fetch the latest 'develop' branch, build a Docker Image and tag it
'netboxcommunity/netbox:snapshot'.
${0} v2.6.6
This will fetch the 'v2.6.6' tag, build a Docker Image and tag it
'netboxcommunity/netbox:v2.6.6' and 'netboxcommunity/netbox:v2.6'.
${0} develop-2.7
This will fetch the 'develop-2.7' branch, build a Docker Image and tag it
'netboxcommunity/netbox:develop-2.7'.
SRC_ORG=cimnine ${0} feature-x
This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,
build a Docker Image and tag it 'netboxcommunity/netbox:feature-x'.
SRC_ORG=cimnine DOCKER_ORG=cimnine ${0} feature-x
This will fetch the 'feature-x' branch from https://github.com/cimnine/netbox.git,
build a Docker Image and tag it 'cimnine/netbox:feature-x'.
PLATFORMS=linux/amd64,linux/arm64 ${0} master
This will fetch the latest 'master' branch, build a Docker Image and tag it
'netboxcommunity/netbox:latest'.
It will produce an ARM64 and an AMD64 version of the image.
DRY_RUN=on ${0} master
This will print all the commands that it would run to
fetch the latest 'master' branch, build a Docker Image and tag it
'netboxcommunity/netbox:latest'.
END_OF_DOCS
if [ "${1}x" == "x" ]; then if [ "${1}x" == "x" ]; then
exit 1 exit 1
@ -104,7 +155,7 @@ if [ -z "${DRY_RUN}" ]; then
DRY="" DRY=""
else else
echo "⚠️ DRY_RUN MODE ON ⚠️" echo "⚠️ DRY_RUN MODE ON ⚠️"
DRY="echo" DRY="echo >>>> "
fi fi
gh_echo "::group::⤵️ Fetching the NetBox source code" gh_echo "::group::⤵️ Fetching the NetBox source code"
@ -135,7 +186,7 @@ if [ "${2}" != "--push-only" ] && [ -z "${SKIP_GIT}" ]; then
( (
$DRY cd "${NETBOX_PATH}" $DRY cd "${NETBOX_PATH}"
# shellcheck disable=SC2030 # shellcheck disable=SC2031
if [ -n "${HTTP_PROXY}" ]; then if [ -n "${HTTP_PROXY}" ]; then
git config http.proxy "${HTTP_PROXY}" git config http.proxy "${HTTP_PROXY}"
fi fi
@ -170,7 +221,7 @@ fi
# Determining the value for DOCKER_FROM # Determining the value for DOCKER_FROM
### ###
if [ -z "$DOCKER_FROM" ]; then if [ -z "$DOCKER_FROM" ]; then
DOCKER_FROM="alpine:3.14" DOCKER_FROM="debian:11-slim"
fi fi
### ###
@ -222,7 +273,7 @@ esac
### ###
# Determine targets to build # Determine targets to build
### ###
DEFAULT_DOCKER_TARGETS=("main" "ldap") DEFAULT_DOCKER_TARGETS=("main")
DOCKER_TARGETS=("${DOCKER_TARGET:-"${DEFAULT_DOCKER_TARGETS[@]}"}") DOCKER_TARGETS=("${DOCKER_TARGET:-"${DEFAULT_DOCKER_TARGETS[@]}"}")
echo "🏭 Building the following targets:" "${DOCKER_TARGETS[@]}" echo "🏭 Building the following targets:" "${DOCKER_TARGETS[@]}"
@ -231,7 +282,6 @@ gh_echo "::endgroup::"
### ###
# Build each target # Build each target
### ###
export DOCKER_BUILDKIT=${DOCKER_BUILDKIT-1}
for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
gh_echo "::group::🏗 Building the target '${DOCKER_TARGET}'" gh_echo "::group::🏗 Building the target '${DOCKER_TARGET}'"
echo "🏗 Building the target '${DOCKER_TARGET}'" echo "🏗 Building the target '${DOCKER_TARGET}'"
@ -248,6 +298,12 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
gh_env "FINAL_DOCKER_TAG=${TARGET_DOCKER_TAG_PROJECT}" gh_env "FINAL_DOCKER_TAG=${TARGET_DOCKER_TAG_PROJECT}"
gh_echo "::set-output name=skipped::false" gh_echo "::set-output name=skipped::false"
###
# composing the final CACHE_FROM_DOCKER_TAG and CACHE_TO_DOCKER_TAG
###
CACHE_FROM_DOCKER_TAG="${BUILDX_CACHE_FROM_DOCKER_TAG-${TARGET_DOCKER_TAG}-cache}"
CACHE_TO_DOCKER_TAG="${BUILDX_CACHE_TO_DOCKER_TAG-${TARGET_DOCKER_TAG}-cache}"
### ###
# composing the additional DOCKER_SHORT_TAG, # composing the additional DOCKER_SHORT_TAG,
# i.e. "v2.6.1" becomes "v2.6", # i.e. "v2.6.1" becomes "v2.6",
@ -271,9 +327,19 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
fi fi
### ###
# Proceeding to buils stage, except if `--push-only` is passed # If `--push-only` is passed, just push and then quit
### ###
if [ "${2}" != "--push-only" ]; then if [ "${2}" == "--push-only" ]; then
source ./build-functions/docker-functions.sh
push_image_to_registry "${TARGET_DOCKER_TAG}"
if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then
push_image_to_registry "${TARGET_DOCKER_SHORT_TAG}"
push_image_to_registry "${TARGET_DOCKER_LATEST_TAG}"
fi
exit 0
fi
### ###
# Checking if the build is necessary, # Checking if the build is necessary,
# meaning build only if one of those values changed: # meaning build only if one of those values changed:
@ -302,7 +368,7 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${PYTHON_LAST_LAYER}\$"; then if ! printf '%s\n' "${IMAGES_LAYERS_OLD[@]}" | grep -q -P "^${PYTHON_LAST_LAYER}\$"; then
SHOULD_BUILD="true" SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} alpine" BUILD_REASON="${BUILD_REASON} upstream-docker"
fi fi
if [ "${NETBOX_GIT_REF}" != "${NETBOX_GIT_REF_OLD}" ]; then if [ "${NETBOX_GIT_REF}" != "${NETBOX_GIT_REF_OLD}" ]; then
SHOULD_BUILD="true" SHOULD_BUILD="true"
@ -316,6 +382,16 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
SHOULD_BUILD="true" SHOULD_BUILD="true"
BUILD_REASON="${BUILD_REASON} no-check" BUILD_REASON="${BUILD_REASON} no-check"
fi fi
###
# Building the docker image
###
if [ "${SHOULD_BUILD}" != "true" ]; then
echo "⏯ Build skipped because sources didn't change"
gh_echo "::set-output name=skipped::true"
continue
fi
### ###
# Composing all arguments for `docker build` # Composing all arguments for `docker build`
### ###
@ -367,7 +443,6 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
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
# shellcheck disable=SC2031
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}")
DOCKER_BUILD_ARGS+=(--build-arg "https_proxy=${HTTPS_PROXY}") DOCKER_BUILD_ARGS+=(--build-arg "https_proxy=${HTTPS_PROXY}")
@ -376,37 +451,69 @@ for DOCKER_TARGET in "${DOCKER_TARGETS[@]}"; do
DOCKER_BUILD_ARGS+=(--build-arg "no_proxy=${NO_PROXY}") DOCKER_BUILD_ARGS+=(--build-arg "no_proxy=${NO_PROXY}")
fi fi
### # --platform
# Building the docker image DOCKER_BUILD_ARGS+=(--platform "${BUILDX_PLATFORMS-linux/amd64}")
###
if [ "${SHOULD_BUILD}" == "true" ]; then # --cache-from / --cache-to
echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG_PROJECT}'." if [ -n "${BUILDX_PULL_REMOTE_CACHE}" ]; then
echo " Build reason set to: ${BUILD_REASON}" echo "📥 Pulling cache from '${CACHE_TO_DOCKER_TAG}' before build"
$DRY docker build "${DOCKER_BUILD_ARGS[@]}" . DOCKER_BUILD_ARGS+=("--cache-from=type=registry,ref=${CACHE_FROM_DOCKER_TAG},mode=max")
echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG_PROJECT}'" elif [ -n "${GH_ACTION}" ]; then
echo "🔎 Inspecting labels on '${TARGET_DOCKER_TAG_PROJECT}'" echo "📥 Pulling from GitHub Action cache before build"
$DRY docker inspect "${TARGET_DOCKER_TAG_PROJECT}" --format "{{json .Config.Labels}}"
else else
echo "Build skipped because sources didn't change" echo "📥 Pulling buildx cache from '${BUILDX_LOCAL_CACHE-.buildx-cache}' before build"
echo "::set-output name=skipped::true" DOCKER_BUILD_ARGS+=("--cache-from=type=local,src=${BUILDX_LOCAL_CACHE-.buildx-cache},mode=max")
fi fi
if [ -n "${BUILDX_PUSH_REMOTE_CACHE}" ]; then
echo "📤 Pushing buildx cache to '${CACHE_TO_DOCKER_TAG}' after build"
DOCKER_BUILD_ARGS+=("--cache-to=type=registry,ref=${CACHE_TO_DOCKER_TAG},mode=max")
elif [ -n "${GH_ACTION}" ]; then
echo "📤 Pushing to GitHub Action cache after build"
DOCKER_BUILD_ARGS+=("--cache-to=type=gha")
else
echo "📤 Pushing buildx cache to '${BUILDX_LOCAL_CACHE-.buildx-cache}' after build"
DOCKER_BUILD_ARGS+=("--cache-to=type=local,dest=${BUILDX_LOCAL_CACHE-.buildx-cache},mode=max")
fi fi
### ###
# Pushing the docker images if either `--push` or `--push-only` are passed # Pushing the docker images if `--push` is passed
### ###
if [ "${2}" == "--push" ] || [ "${2}" == "--push-only" ]; then if [ "${2}" == "--push" ]; then
source ./build-functions/docker-functions.sh # output type=docker does not work with pushing
push_image_to_registry "${TARGET_DOCKER_TAG}" DOCKER_BUILD_ARGS+=(
push_image_to_registry "${TARGET_DOCKER_TAG_PROJECT}" --output=type=image
--push
)
else
DOCKER_BUILD_ARGS+=(
--output=type=docker
)
fi
if [ -n "${TARGET_DOCKER_SHORT_TAG}" ]; then if [ -z "${BUILDX_BUILDER_NAME}" ]; then
push_image_to_registry "${TARGET_DOCKER_SHORT_TAG}" BUILDX_BUILDER_NAME="$(basename "${PWD}")"
push_image_to_registry "${TARGET_DOCKER_SHORT_TAG_PROJECT}" if ! docker buildx ls | grep --quiet --word-regexp "${BUILDX_BUILDER_NAME}"; then
push_image_to_registry "${TARGET_DOCKER_LATEST_TAG}" echo "👷 Creating new Buildx Builder '${BUILDX_BUILDER_NAME}'"
push_image_to_registry "${TARGET_DOCKER_LATEST_TAG_PROJECT}" $DRY docker buildx create --name "${BUILDX_BUILDER_NAME}"
BUILDX_BUILDER_CREATED="yes"
fi fi
fi fi
gh_echo "::endgroup::" echo "🐳 Building the Docker image '${TARGET_DOCKER_TAG}' on '${BUILDX_BUILDER_NAME}'."
echo " Build reason set to: ${BUILD_REASON}"
$DRY docker buildx \
--builder "${BUILDX_BUILDER_NAME}" \
build \
"${DOCKER_BUILD_ARGS[@]}" \
.
echo "✅ Finished building the Docker images '${TARGET_DOCKER_TAG}'"
echo "🔎 Inspecting labels on '${TARGET_DOCKER_TAG}'"
$DRY docker inspect "${TARGET_DOCKER_TAG}" --format "{{json .Config.Labels}}"
if [ -n "${BUILDX_REMOVE_BUILDER}" ] && [ "${BUILDX_BUILDER_CREATED}" == "yes" ]; then
echo "👷 Removing Buildx Builder '${BUILDX_BUILDER_NAME}'"
$DRY docker buildx rm "${BUILDX_BUILDER_NAME}"
fi
done done