Skip to content

Commit 2063d2b

Browse files
authored
Merge pull request #10505 from Icinga/docker-v2
Rework docker images build
2 parents 9f980bd + 8ea1112 commit 2063d2b

File tree

5 files changed

+583
-36
lines changed

5 files changed

+583
-36
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Container Image
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
pull_request: {}
8+
release:
9+
types:
10+
- published
11+
12+
concurrency:
13+
group: container-image-${{ github.event_name == 'push' && github.sha || github.ref }}
14+
cancel-in-progress: true
15+
16+
jobs:
17+
container-image:
18+
# Required by the base Container Image Action [^1].
19+
# [^1]: https://github.com/Icinga/github-actions/blob/main/.github/workflows/container-image.yml#L54-L58
20+
permissions:
21+
contents: read
22+
packages: write
23+
attestations: write
24+
id-token: write
25+
26+
name: Container Image
27+
uses: icinga/github-actions/.github/workflows/container-image.yml@main
28+
with:
29+
documentation_url: https://icinga.com/docs/icinga2
30+
secrets:
31+
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
32+
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}

.github/workflows/docker.yml

Lines changed: 0 additions & 36 deletions
This file was deleted.

Containerfile

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# Icinga 2 Docker image | (c) 2025 Icinga GmbH | GPLv2+
2+
3+
FROM debian:trixie-slim AS build-base
4+
5+
# Install all the necessary build dependencies for building Icinga 2 and the plugins.
6+
#
7+
# This stage includes the build dependencies for the plugins as well, so that they can share the same base
8+
# image, since Docker builds common stages only once [^1] even if they are used in multiple build stages.
9+
# This eliminates the need to have a separate base image for the plugins, that basically has kind of the
10+
# same dependencies as the Icinga 2 build stage (ok, not exactly the same, but some of them are shared).
11+
#
12+
# [^1]: https://docs.docker.com/build/building/best-practices/#create-reusable-stages
13+
RUN apt-get update && \
14+
apt-get upgrade -y && \
15+
apt-get install -y --no-install-recommends --no-install-suggests \
16+
autoconf \
17+
automake \
18+
bison \
19+
ccache \
20+
cmake \
21+
flex \
22+
g++ \
23+
git \
24+
libboost1.83-dev \
25+
libboost-context1.83-dev \
26+
libboost-coroutine1.83-dev \
27+
libboost-date-time1.83-dev \
28+
libboost-filesystem1.83-dev \
29+
libboost-iostreams1.83-dev \
30+
libboost-program-options1.83-dev \
31+
libboost-regex1.83-dev \
32+
libboost-system1.83-dev \
33+
libboost-thread1.83-dev \
34+
libboost-test1.83-dev \
35+
libedit-dev \
36+
libmariadb-dev \
37+
libpq-dev \
38+
libssl-dev \
39+
libsystemd-dev \
40+
make && \
41+
rm -rf /var/lib/apt/lists/*
42+
43+
# Set the default working directory for subsequent commands of the next stages.
44+
WORKDIR /icinga2-build
45+
46+
FROM build-base AS build-plugins
47+
48+
# Install all the plugins that are not included in the monitoring-plugins package.
49+
ADD https://github.com/lausser/check_mssql_health.git#747af4c3c261790341da164b58d84db9c7fa5480 /check_mssql_health
50+
ADD https://github.com/lausser/check_nwc_health.git#a5295475c9bbd6df9fe7432347f7c5aba16b49df /check_nwc_health
51+
ADD https://github.com/bucardo/check_postgres.git#58de936fdfe4073413340cbd9061aa69099f1680 /check_postgres
52+
ADD https://github.com/matteocorti/check_ssl_cert.git#341b5813108fb2367ada81e866da989ea4fb29e7 /check_ssl_cert
53+
54+
WORKDIR /check_mssql_health
55+
RUN mkdir bin && \
56+
autoconf && \
57+
autoreconf && \
58+
./configure "--build=$(uname -m)-unknown-linux-gnu" --libexecdir=/usr/lib/nagios/plugins && \
59+
make && \
60+
make install DESTDIR="$(pwd)/bin"
61+
62+
WORKDIR /check_nwc_health
63+
RUN mkdir bin && \
64+
autoreconf && \
65+
./configure "--build=$(uname -m)-unknown-linux-gnu" --libexecdir=/usr/lib/nagios/plugins && \
66+
make && \
67+
make install DESTDIR="$(pwd)/bin"
68+
69+
WORKDIR /check_postgres
70+
RUN mkdir bin && \
71+
perl Makefile.PL INSTALLSITESCRIPT=/usr/lib/nagios/plugins && \
72+
make && \
73+
make install DESTDIR="$(pwd)/bin" && \
74+
# This is necessary because of this build error: cannot copy to non-directory: /var/lib/docker/.../merged/usr/local/man
75+
rm -rf bin/usr/local/man
76+
77+
FROM build-base AS build-icinga2
78+
79+
# To access the automated build arguments in the Dockerfile originated from the Docker BuildKit [^1],
80+
# we need to declare them here as build arguments. This is necessary because we want to use unique IDs
81+
# for the mount cache below for each platform to avoid conflicts between multi arch builds. Otherwise,
82+
# the build targets will invalidate the cache one another, leading to strange build errors.
83+
#
84+
# [^1]: https://docs.docker.com/reference/dockerfile/#automatic-platform-args-in-the-global-scope
85+
ARG TARGETPLATFORM
86+
87+
# Icinga 2 build arguments.
88+
#
89+
# These arguments are used to configure the build of Icinga 2 and can be overridden
90+
# by the user when building the image. All of them have a default value suitable for our official image.
91+
ARG CMAKE_BUILD_TYPE=RelWithDebInfo
92+
ARG ICINGA2_UNITY_BUILD=ON
93+
ARG ICINGA2_BUILD_TESTING=ON
94+
95+
# The number of jobs to run in parallel when building Icinga 2.
96+
# By default, it is set to the number of available CPU cores on the build machine.
97+
ARG MAKE_JOBS=auto
98+
99+
# Create the directory where the final Icinga 2 files will be installed.
100+
#
101+
# This directory will be used as the destination for the `make install` command below and will be
102+
# copied to the final image. Other than that, this directory will not be used for anything else.
103+
RUN mkdir /icinga2-install
104+
105+
# Mount the source code as a bind mount instead of copying it, so that we can use the cache effectively.
106+
# Additionally, add the ccache and CMake build directories as cache mounts to speed up rebuilds.
107+
RUN --mount=type=bind,source=.,target=/icinga2,readonly \
108+
--mount=type=cache,id=ccache-${TARGETPLATFORM},target=/root/.ccache \
109+
--mount=type=cache,id=icinga2-build-${TARGETPLATFORM},target=/icinga2-build \
110+
PATH="/usr/lib/ccache:$PATH" \
111+
cmake -S /icinga2 -B /icinga2-build \
112+
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
113+
# Podman supports forwarding notifications from containers to systemd, so build Icinga 2 with systemd support.
114+
-DUSE_SYSTEMD=ON \
115+
-DBUILD_TESTING=${ICINGA2_BUILD_TESTING} \
116+
-DICINGA2_UNITY_BUILD=${ICINGA2_UNITY_BUILD} \
117+
# The command group name below is required for the prepare-dirs script to work, as it expects
118+
# the command group name, which by default is `icingacmd` to exist on the system. Since we
119+
# don't create the `icingacmd` command group in this image, we need to override it with icinga.
120+
-DICINGA2_COMMAND_GROUP=icinga \
121+
-DCMAKE_INSTALL_PREFIX=/usr \
122+
-DCMAKE_INSTALL_SYSCONFDIR=/data/etc \
123+
-DCMAKE_INSTALL_LOCALSTATEDIR=/data/var \
124+
-DICINGA2_SYSCONFIGFILE=/etc/sysconfig/icinga2 \
125+
-DICINGA2_RUNDIR=/run \
126+
-DICINGA2_WITH_COMPAT=OFF \
127+
-DICINGA2_WITH_LIVESTATUS=OFF && \
128+
make -j$([ "$MAKE_JOBS" = auto ] && nproc || echo "$MAKE_JOBS") && \
129+
CTEST_OUTPUT_ON_FAILURE=1 make test && \
130+
make install DESTDIR=/icinga2-install
131+
132+
RUN rm -rf /icinga2-install/etc/icinga2/features-enabled/mainlog.conf \
133+
/icinga2-install/usr/share/doc/icinga2/markdown && \
134+
strip -g /icinga2-install/usr/lib/*/icinga2/sbin/icinga2 && \
135+
strip -g /icinga2-install/usr/lib/nagios/plugins/check_nscp_api
136+
137+
# Prepare the final image with the necessary configuration files and runtime dependencies.
138+
FROM debian:trixie-slim AS icinga2
139+
140+
# The real UID of the Icinga user to be used in the final image.
141+
ARG ICINGA_USER_ID=5665
142+
143+
# Install the necessary runtime dependencies for the Icinga 2 binary and the monitoring-plugins.
144+
RUN apt-get update && \
145+
apt-get upgrade -y && \
146+
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends --no-install-suggests \
147+
bc \
148+
ca-certificates \
149+
curl \
150+
dumb-init \
151+
file \
152+
libboost-context1.83.0 \
153+
libboost-coroutine1.83.0 \
154+
libboost-date-time1.83.0 \
155+
libboost-filesystem1.83.0 \
156+
libboost-iostreams1.83.0 \
157+
libboost-program-options1.83.0 \
158+
libboost-regex1.83.0 \
159+
libboost-system1.83.0 \
160+
libboost-thread1.83.0 \
161+
libcap2-bin \
162+
libedit2 \
163+
libldap-common \
164+
libmariadb3 \
165+
libmoosex-role-timer-perl \
166+
libpq5 \
167+
libssl3 \
168+
libsystemd0 \
169+
mailutils \
170+
monitoring-plugins \
171+
msmtp \
172+
msmtp-mta \
173+
openssh-client \
174+
openssl && \
175+
# Official Debian images automatically run `apt-get clean` after every install, so we don't need to do it here.
176+
rm -rf /var/lib/apt/lists/*
177+
178+
# Create the icinga user and group with a specific UID as recommended by Docker best practices.
179+
# The user has a home directory at /var/lib/icinga2, and if configured, that directory will also
180+
# be used to store the ".msmtprc" file created by the entrypoint script.
181+
RUN adduser \
182+
--system \
183+
--group \
184+
--home /var/lib/icinga2 \
185+
--disabled-login \
186+
--no-create-home \
187+
--uid ${ICINGA_USER_ID} icinga
188+
189+
COPY --from=build-plugins /check_mssql_health/bin/ /
190+
COPY --from=build-plugins /check_nwc_health/bin/ /
191+
COPY --from=build-plugins /check_postgres/bin/ /
192+
COPY --from=build-plugins /check_ssl_cert/check_ssl_cert /usr/lib/nagios/plugins/check_ssl_cert
193+
194+
COPY --from=build-icinga2 /icinga2-install/ /
195+
196+
# Create a corresponding symlink in the root filesystem for all Icinga 2 directories in /data.
197+
# This is necessary because we want to maintain the compatibility with containers built with the
198+
# legacy Dockerfile, which expects the Icinga 2 directories to be in the root directory.
199+
RUN for dir in /etc/icinga2 /var/cache/icinga2 /var/lib/icinga2 /var/log/icinga2 /var/spool/icinga2; do \
200+
ln -vs "/data$dir" "$dir"; \
201+
done
202+
203+
# The below prepare-dirs script will not fix any permissions issues for the actuall /var/lib/icinga2 or
204+
# /etc/icinga2 directories, so we need to set the correct ownership for the /data directory recursively.
205+
RUN chown -R icinga:icinga /data
206+
207+
# Run the prepare-dirs script to create non-existing directories and set the correct permissions for them.
208+
# It's invoked in the same way as in the systemd unit file in a Debian package, so this will ensure that
209+
# all the necessary directories are created with the correct permissions and ownership.
210+
RUN /usr/lib/icinga2/prepare-dirs /etc/sysconfig/icinga2
211+
212+
# Well, since the /data directory is intended to be used as a volume, we should also declare it as such.
213+
# This will allow users to mount their own directories or even specific files to the /data directory
214+
# without any issues. We've already filled the /data directory with the necessary configuration files,
215+
# so users can simply mount their own files or directories if they want to override the default ones and
216+
# they will be able to do so without any issues.
217+
VOLUME ["/data"]
218+
219+
COPY --chmod=0755 tools/container/entrypoint.sh /usr/local/bin/entrypoint.sh
220+
ENTRYPOINT ["/usr/bin/dumb-init", "-c", "--", "/usr/local/bin/entrypoint.sh"]
221+
222+
EXPOSE 5665
223+
USER icinga
224+
225+
CMD ["icinga2", "daemon"]

0 commit comments

Comments
 (0)