]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
docker: generate dockerfiles from templates
authorMatthew Newton <matthew-git@newtoncomputing.co.uk>
Wed, 24 Apr 2024 16:18:41 +0000 (17:18 +0100)
committerMatthew Newton <matthew-git@newtoncomputing.co.uk>
Wed, 1 May 2024 23:02:52 +0000 (00:02 +0100)
.dockerignore [new file with mode: 0644]
Makefile
scripts/docker/docker.mk [new file with mode: 0644]
scripts/docker/etc/docker-entrypoint.sh.deb [new file with mode: 0755]
scripts/docker/etc/docker-entrypoint.sh.rpm [new file with mode: 0755]
scripts/docker/m4/docker.deb.m4 [new file with mode: 0644]
scripts/docker/m4/docker.rpm.m4 [new file with mode: 0644]

diff --git a/.dockerignore b/.dockerignore
new file mode 100644 (file)
index 0000000..f2c5ac5
--- /dev/null
@@ -0,0 +1,2 @@
+scripts/docker/build/
+scripts/docker/m4/
index 77bb24bb99a0ebe9e191a72a15c74af0431da356..7c5553f280dc97e07e538ef41997c80087720f9c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ endif
 #  there's no point in requiring the developer to run configure
 #  *before* making packages.
 #
-ifeq "$(filter deb rpm pkg_version crossbuild.% freeradius-server-%,$(MAKECMDGOALS))" ""
+ifeq "$(filter deb rpm pkg_version dist-check% crossbuild.% docker.% freeradius-server-%,$(MAKECMDGOALS))" ""
   $(if $(wildcard Make.inc),,$(error Missing 'Make.inc' Run './configure [options]' and retry))
   include Make.inc
 else
@@ -114,7 +114,7 @@ PROTOCOLS    := \
 #  If we're building packages or crossbuilding, just do that.
 #  Don't try to do a local build.
 #
-ifeq "$(filter deb rpm pkg_version crossbuild.% freeradius-server-%,$(MAKECMDGOALS))" ""
+ifeq "$(filter deb rpm pkg_version dist-check% crossbuild.% docker.% freeradius-server-%,$(MAKECMDGOALS))" ""
 
 #
 #  Include all of the autoconf definitions into the Make variable space
@@ -463,13 +463,15 @@ freeradius-server-$(PKG_VERSION).tar.bz2: freeradius-server-$(PKG_VERSION).tar
        gpg --default-key packages@freeradius.org -b $<
 
 # high-level targets
-.PHONY: dist-check
-dist-check: redhat/freeradius.spec debian/changelog
+.PHONY: dist-check-rpm
+dist-check-rpm: redhat/freeradius.spec
        @if [ `grep '^%global _version' redhat/freeradius.spec | cut -d' ' -f3` != "$(PKG_VERSION)" ]; then \
                sed 's/^%global _version .*/%global _version $(PKG_VERSION)/' redhat/freeradius.spec > redhat/.foo; \
                mv redhat/.foo redhat/freeradius.spec; \
                echo Updated redhat/freeradius.spec '_version' to $(PKG_VERSION); \
        fi
+.PHONY: dist-check
+dist-check: dist-check-rpm debian/changelog
        @if [ `head -n 1 doc/ChangeLog | awk '/^FreeRADIUS/{print $$2}'` != "$(PKG_VERSION)" ]; then \
                echo doc/ChangeLog needs to be updated; \
                exit 1; \
@@ -554,6 +556,13 @@ ifneq "$(findstring crossbuild,$(MAKECMDGOALS))" ""
   include scripts/docker/crossbuild.mk
 endif
 
+#
+#  Conditionally include the docker make file
+#
+ifneq "$(findstring docker,$(MAKECMDGOALS))" ""
+  include scripts/docker/docker.mk
+endif
+
 #
 #  Clean gcov files, too.
 #
diff --git a/scripts/docker/docker.mk b/scripts/docker/docker.mk
new file mode 100644 (file)
index 0000000..0ac7e56
--- /dev/null
@@ -0,0 +1,126 @@
+#
+#  Docker targets to create Docker images that run FreeRADIUS
+#
+ifeq ($(shell which docker 2> /dev/null),)
+.PHONY: docker docker.help
+docker docker.help :
+       @echo docker targets require Docker to be installed
+else
+
+#
+#  Short list of common builds
+#
+DOCKER_COMMON:=ubuntu22
+
+# Top level of where all crossbuild and docker files are
+CB_DIR:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
+
+# Where the docker directories are
+DT:=$(CB_DIR)/build
+
+# Location of top-level m4 template
+DOCKER_TMPL:=$(CB_DIR)/m4/Dockerfile.m4
+
+# List of all the docker images (sorted for "docker.info")
+IMAGES:=$(sort $(patsubst $(DT)/%,%,$(wildcard $(DT)/*)))
+
+# Don't use the Docker cache if asked
+ifneq "$(NOCACHE)" ""
+    DOCKER_BUILD_OPTS += " --no-cache"
+endif
+
+# Docker image name prefix
+D_IPREFIX:=freeradius4
+
+#
+#  This Makefile is included in-line, and not via the "boilermake"
+#  wrapper.  But it's still useful to use the same process for
+#  seeing commands that are run.
+#
+ifeq "${VERBOSE}" ""
+    Q=@
+else
+    Q=
+endif
+
+#
+#  Enter here: This builds everything
+#
+.PHONY: docker docker.common
+docker: docker.info $(foreach IMG,${IMAGES},docker.${IMG})
+docker.common: docker.info $(foreach IMG,${DOCKER_COMMON},docker.${IMG})
+
+#
+#  Dump out some useful information on what images we're going to test
+#
+.PHONY: docker.info docker.info_header docker.help
+docker.info: docker.info_header $(foreach IMG,${IMAGES},docker.${IMG}.status)
+       @echo All images: $(IMAGES)
+       @echo Common images: $(DOCKER_COMMON)
+
+docker.info_header:
+       @echo Built images:
+
+docker.help:
+       @echo ""
+       @echo "Make targets:"
+       @echo "    docker                   - build all images"
+       @echo "    docker.common            - build and test common images"
+       @echo "    docker.info              - list images"
+       @echo "    docker.regen             - regenerate all Dockerfiles"
+       @echo ""
+       @echo "Per-image targets:"
+       @echo "    docker.IMAGE.build       - build image as $(D_IPREFIX)/<IMAGE>"
+       @echo "    docker.IMAGE.regen       - regenerate Dockerfile from template"
+       @echo ""
+       @echo "Use 'make NOCACHE=1 ...' to disregard the Docker cache on build"
+
+#
+#  Regenerate all Dockerfiles from m4 templates
+#
+docker.regen: $(foreach IMG,${IMAGES},docker.${IMG}.regen)
+
+#
+#  Define rules for building a particular image
+#
+define CROSSBUILD_IMAGE_RULE
+
+.PHONY: docker.${1}.status
+docker.${1}.status:
+       ${Q}docker image ls --format "\t{{.Repository}} \t{{.CreatedAt}}" $(D_IPREFIX)/${1}
+
+#
+#  Build the docker image
+#
+.PHONY: docker.${1}.build
+docker.${1}.build:
+       ${Q}echo "BUILD ${1} ($(D_IPREFIX)/${1}) from $(DT)/${1}/Dockerfile"
+
+       ${Q}docker buildx build \
+               $(DOCKER_BUILD_OPTS) \
+               --progress=plain \
+               . \
+               -f $(DT)/${1}/Dockerfile \
+               -t $(D_IPREFIX)/${1}
+
+#
+#  Regenerate the image Dockerfile from the m4 templates
+#
+.PHONY: docker.${1}.regen
+docker.${1}.regen: $(DT)/${1}/Dockerfile
+
+$(DT)/${1}/Dockerfile: $(DOCKER_TMPL) $(CB_DIR)/m4/docker.deb.m4 $(CB_DIR)/m4/docker.rpm.m4
+       ${Q}echo REGEN ${1} "->" $$@
+       ${Q}m4 -I $(CB_DIR)/m4 -D D_NAME=${1} -D D_TYPE=docker $$< > $$@
+
+endef
+
+#
+#  Add all the image building rules
+#
+$(foreach IMAGE,$(IMAGES),\
+  $(eval $(call CROSSBUILD_IMAGE_RULE,$(IMAGE))))
+
+
+# if docker is defined
+endif
diff --git a/scripts/docker/etc/docker-entrypoint.sh.deb b/scripts/docker/etc/docker-entrypoint.sh.deb
new file mode 100755 (executable)
index 0000000..93141b0
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -e
+
+# this if will check if the first argument is a flag
+# but only works if all arguments require a hyphenated flag
+# -v; -SL; -f arg; etc will work, but not arg1 arg2
+if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
+    set -- freeradius "$@"
+fi
+
+# check for the expected command
+if [ "$1" = 'freeradius' ]; then
+    shift
+    exec freeradius -f "$@"
+fi
+
+# many people are likely to call "radiusd" as well, so allow that
+if [ "$1" = 'radiusd' ]; then
+    shift
+    exec freeradius -f "$@"
+fi
+
+# else default to run whatever the user wanted like "bash" or "sh"
+exec "$@"
diff --git a/scripts/docker/etc/docker-entrypoint.sh.rpm b/scripts/docker/etc/docker-entrypoint.sh.rpm
new file mode 100755 (executable)
index 0000000..900ad6b
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -e
+
+# this if will check if the first argument is a flag
+# but only works if all arguments require a hyphenated flag
+# -v; -SL; -f arg; etc will work, but not arg1 arg2
+if [ "$#" -eq 0 ] || [ "${1#-}" != "$1" ]; then
+    set -- radiusd "$@"
+fi
+
+# check for the expected command
+if [ "$1" = 'radiusd' ]; then
+    shift
+    exec radiusd -f "$@"
+fi
+
+# debian people are likely to call "freeradius" as well, so allow that
+if [ "$1" = 'freeradius' ]; then
+    shift
+    exec radiusd -f "$@"
+fi
+
+# else default to run whatever the user wanted like "bash" or "sh"
+exec "$@"
diff --git a/scripts/docker/m4/docker.deb.m4 b/scripts/docker/m4/docker.deb.m4
new file mode 100644 (file)
index 0000000..6e6b051
--- /dev/null
@@ -0,0 +1,98 @@
+ARG from=DOCKER_IMAGE
+FROM ${from} as build
+
+ARG DEBIAN_FRONTEND=noninteractive
+
+#
+#  Install build tools
+#
+RUN apt-get update
+RUN apt-get install -y devscripts equivs git quilt gcc curl
+
+#
+#  Set up NetworkRADIUS extras repository
+#
+RUN install -d -o root -g root -m 0755 /etc/apt/keyrings \
+ && curl -o /etc/apt/keyrings/packages.networkradius.com.asc "https://packages.networkradius.com/pgp/packages%40networkradius.com" \
+ && echo "deb [signed-by=/etc/apt/keyrings/packages.networkradius.com.asc] http://packages.networkradius.com/extras/OS_NAME/OS_CODENAME OS_CODENAME main" > /etc/apt/sources.list.d/networkradius-extras.list \
+ && apt-get update
+
+#
+#  Create build directory
+#
+RUN mkdir -p /usr/local/src/repositories/freeradius-server
+WORKDIR /usr/local/src/repositories/freeradius-server/
+
+#
+#  Copy the FreeRADIUS directory in
+#
+COPY . .
+
+#
+#  Clean up tree - we want to build from the latest commit, not from
+#  any cruft left around on the local system
+#
+RUN git clean -fdxx \
+ && git reset --hard HEAD
+
+#
+#  Install build dependencies
+#
+RUN if [ -e ./debian/control.in ]; then \
+        debian/rules debian/control; \
+    fi; \
+    echo 'y' | mk-build-deps -irt'apt-get -yV' debian/control
+
+#
+#  Build the server
+#
+RUN make -j$(nproc) deb
+
+#
+#  Clean environment and run the server
+#
+FROM ${from}
+ARG DEBIAN_FRONTEND=noninteractive
+
+COPY --from=build /usr/local/src/repositories/*.deb /tmp/
+
+#
+#  We need curl to get the signing key
+#
+RUN apt-get update \
+ && apt-get install -y curl \
+ && apt-get clean \
+ && rm -r /var/lib/apt/lists/*
+
+#
+#  Set up NetworkRADIUS extras repository
+#
+RUN install -d -o root -g root -m 0755 /etc/apt/keyrings \
+ && curl -o /etc/apt/keyrings/packages.networkradius.com.asc "https://packages.networkradius.com/pgp/packages%40networkradius.com" \
+ && echo "deb [signed-by=/etc/apt/keyrings/packages.networkradius.com.asc] http://packages.networkradius.com/extras/OS_NAME/OS_CODENAME OS_CODENAME main" > /etc/apt/sources.list.d/networkradius-extras.list
+
+ifelse(ifelse(
+       D_NAME, `debian10', no,
+       D_NAME, `ubuntu18', no,
+       D_NAME, `ubuntu20', no,
+       yes), yes, `dnl
+ARG freerad_uid=101
+ARG freerad_gid=101
+
+RUN groupadd -g ${freerad_gid} -r freerad \
+ && useradd -u ${freerad_uid} -g freerad -r -M -d /etc/freeradius -s /usr/sbin/nologin freerad \
+ && apt-get update \',
+`RUN apt-get update \')
+ && apt-get install -y /tmp/*.deb \
+ && apt-get clean \
+ && rm -r /var/lib/apt/lists/* /tmp/*.deb \
+    \
+ && ln -s /etc/freeradius /etc/raddb
+
+WORKDIR /
+COPY scripts/docker/etc/docker-entrypoint.sh.PKG_TYPE docker-entrypoint.sh
+RUN chmod +x docker-entrypoint.sh
+
+EXPOSE 1812/udp 1813/udp
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["freeradius"]
diff --git a/scripts/docker/m4/docker.rpm.m4 b/scripts/docker/m4/docker.rpm.m4
new file mode 100644 (file)
index 0000000..d75f821
--- /dev/null
@@ -0,0 +1,176 @@
+ARG from=DOCKER_IMAGE
+FROM ${from} as build
+
+ifelse(OS_VER, 8, `dnl
+RUN rpmkeys --import /etc/pki/rpm-gpg/RPM-GPG-KEY-rockyofficial
+')dnl
+ifelse(OS_VER, 9, `dnl
+RUN rpmkeys --import /etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
+')
+#
+#  Install build tools
+#
+RUN yum groupinstall -y "Development Tools"
+ifelse(OS_VER, 7,`dnl
+RUN yum install -y rpmdevtools
+RUN yum install -y openssl
+',`
+RUN yum install -y rpmdevtools openssl dnf-utils
+')
+
+#
+#  Set up NetworkRADIUS extras repository
+#
+RUN echo $'[networkradius-extras]\n\
+name=NetworkRADIUS-extras-$releasever\n\
+baseurl=http://packages.networkradius.com/extras/OS_NAME/$releasever/\n\
+enabled=1\n\
+gpgcheck=1\n\
+gpgkey=https://packages.networkradius.com/pgp/packages@networkradius.com'\
+> /etc/yum.repos.d/networkradius-extras.repo
+RUN rpm --import https://packages.networkradius.com/pgp/packages@networkradius.com
+
+#
+#  Create build directory
+#
+RUN mkdir -p /usr/local/src/repositories/freeradius-server
+WORKDIR /usr/local/src/repositories/freeradius-server/
+
+#
+#  Copy the FreeRADIUS directory in
+#
+COPY . .
+
+#
+#  Clean up tree - we want to build from the latest commit, not from
+#  any cruft left around on the local system
+#
+RUN git clean -fdxx \
+ && git reset --hard HEAD
+
+#
+#  Other requirements
+#
+changequote(`{', `}')dnl
+ifelse(ifelse(OS_VER, 8, yes, no), yes, {
+#  Use LTB's openldap packages instead of the distribution version to avoid linking against NSS
+RUN echo $'[ltb-project]\n\
+name=LTB project packages\n\
+baseurl=https://ltb-project.org/rpm/$releasever/$basearch\n\
+enabled=1\n\
+gpgcheck=1\n\
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-LTB-project'\
+> /etc/yum.repos.d/ltb-project.repo
+RUN rpm --import https://ltb-project.org/lib/RPM-GPG-KEY-LTB-project
+})dnl
+changequote({`}, {'})dnl
+
+#  Enable EPEL repository for freetds and hiredis
+RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-OS_VER.noarch.rpm
+ifelse(OS_VER, 8, `
+#  Enable powertools repo
+RUN yum config-manager --enable powertools
+
+#  Enable epel-testing, currently needed for hiredis-devel
+RUN yum config-manager --enable epel-testing
+')dnl
+ifelse(OS_VER, 9, `
+#  Enable Code Ready Builder repo (CentOS powertools equivalent)
+RUN yum install -y yum-utils
+RUN yum config-manager --enable crb
+')dnl
+
+#
+#  Install build dependencies
+#
+#  Run twice, it doesn't always get everything with one invocation
+RUN [ -e redhat/freeradius.spec ] && \
+       yum-builddep -y redhat/freeradius.spec && \
+       yum-builddep -y redhat/freeradius.spec
+
+#
+#  Create RPM build environment
+#
+ENV BUILDDIR=/root/rpmbuild
+RUN rpmdev-setuptree
+
+RUN ./configure
+RUN make pkg_version > /VERSION
+RUN cat /VERSION
+RUN make freeradius-server-$(cat /VERSION).tar.bz2
+RUN cp freeradius-server-$(cat /VERSION).tar.bz2 $BUILDDIR/SOURCES/
+RUN cp -r redhat/* $BUILDDIR/SOURCES/
+RUN make dist-check-rpm
+RUN cp -r redhat/freeradius.spec $BUILDDIR/SPECS/
+WORKDIR $BUILDDIR
+
+#
+#  Build the server
+#
+ENV QA_RPATHS=0x0003
+RUN rpmbuild -bb --define "_release $(cat /VERSION)" "$BUILDDIR/SPECS/freeradius.spec"
+
+RUN mkdir /root/rpms
+RUN mv $BUILDDIR/RPMS/*/*.rpm /root/rpms/
+
+#
+#  Clean environment and run the server
+#
+FROM ${from}
+
+COPY --from=build /root/rpms /tmp/
+
+#
+#  Set up NetworkRADIUS extras repository
+#
+RUN echo $'[networkradius-extras]\n\
+name=NetworkRADIUS-extras-$releasever\n\
+baseurl=http://packages.networkradius.com/extras/OS_NAME/$releasever/\n\
+enabled=1\n\
+gpgcheck=1\n\
+gpgkey=https://packages.networkradius.com/pgp/packages@networkradius.com'\
+> /etc/yum.repos.d/networkradius-extras.repo
+RUN rpm --import https://packages.networkradius.com/pgp/packages@networkradius.com
+
+#
+#  Other requirements
+#
+changequote(`{', `}')dnl
+ifelse(ifelse(OS_VER, 8, yes, no), yes, {dnl
+# Use LTB's openldap packages instead of the distribution version to avoid linking against NSS
+RUN echo $'[ltb-project]\n\
+name=LTB project packages\n\
+baseurl=https://ltb-project.org/rpm/$releasever/$basearch\n\
+enabled=1\n\
+gpgcheck=1\n\
+gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-LTB-project'\
+> /etc/yum.repos.d/ltb-project.repo \
+    && rpm --import https://ltb-project.org/lib/RPM-GPG-KEY-LTB-project
+})dnl
+changequote({`}, {'})dnl
+
+ifelse(OS_VER, 9, `dnl
+#  Needed for mysql-libs on Rocky 9
+RUN yum install -y yum-utils
+RUN yum config-manager --enable crb
+')dnl
+
+#  EPEL repository for freetds and hiredis
+RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-OS_VER.noarch.rpm \
+    && yum install -y dnf-utils \
+    && yum config-manager --enable epel-testing
+
+ARG radiusd_uid=95
+ARG radiusd_gid=95
+
+RUN groupadd -g ${radiusd_gid} -r radiusd \
+    && useradd -u ${radiusd_uid} -g radiusd -r -M -d /home/radiusd -s /sbin/nologin radiusd \
+    && yum install -y /tmp/*.rpm
+
+WORKDIR /
+COPY scripts/docker/etc/docker-entrypoint.sh.PKG_TYPE docker-entrypoint.sh
+RUN chmod +x docker-entrypoint.sh
+
+EXPOSE 1812/udp 1813/udp
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["radiusd"]