Installed rrdtool during build, but not found later in build proces

Hi,

Just started with Docker. Running on a Synology 918+, docker version 17.05.0-ce.

My goal is to build an image based on alpine with nginx and the mod_rrd_graph module. The module can be linked to nginx during compile. According to the author of the module, rrdtool needs to be installed.

So, I started with alpine:3.9 on github and added stuff to the Dockerfile. The part between LABEL and RUN GPG_KEYS has been added by me. In the CONFIG= part one line has been added by me:
–add-module=/tmp/mod_rrd_graph

Some links in the dockerfile have been removed by me, cause as a new user in the forum my first post(s) may contain no more than two links :face_with_raised_eyebrow:

FROM alpine:3.9

LABEL maintainer=“NGINX Docker Maintainers”

ENV NGINX_VERSION=1.15.8 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/share

RUN apk --no-cache add rrdtool

RUN mkdir /tmp/mod_rrd_graph
COPY config /tmp/mod_rrd_graph
COPY ngx_http_rrd_graph_module.c /tmp/mod_rrd_graph

RUN rrdtool

RUN GPG_KEYS=B0F4253373F8F6F510D42178520A9993A1C052F8
&& CONFIG="
–prefix=/etc/nginx
–sbin-path=/usr/sbin/nginx
–modules-path=/usr/lib/nginx/modules
–add-module=/tmp/mod_rrd_graph
–conf-path=/etc/nginx/nginx.conf
–error-log-path=/var/log/nginx/error.log
–http-log-path=/var/log/nginx/access.log
–pid-path=/var/run/nginx.pid
–lock-path=/var/run/nginx.lock
–http-client-body-temp-path=/var/cache/nginx/client_temp
–http-proxy-temp-path=/var/cache/nginx/proxy_temp
–http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp
–http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp
–http-scgi-temp-path=/var/cache/nginx/scgi_temp
–user=nginx
–group=nginx
–with-http_ssl_module
–with-http_realip_module
–with-http_addition_module
–with-http_sub_module
–with-http_dav_module
–with-http_flv_module
–with-http_mp4_module
–with-http_gunzip_module
–with-http_gzip_static_module
–with-http_random_index_module
–with-http_secure_link_module
–with-http_stub_status_module
–with-http_auth_request_module
–with-http_xslt_module=dynamic
–with-http_image_filter_module=dynamic
–with-http_geoip_module=dynamic
–with-threads
–with-stream
–with-stream_ssl_module
–with-stream_ssl_preread_module
–with-stream_realip_module
–with-stream_geoip_module=dynamic
–with-http_slice_module
–with-mail
–with-mail_ssl_module
–with-compat
–with-file-aio
–with-http_v2_module
"
&& addgroup -S nginx
&& adduser -D -S -h /var/cache/nginx -s /sbin/nologin -G nginx nginx
&& apk add --no-cache --virtual .build-deps
gcc
libc-dev
make
openssl-dev
pcre-dev
zlib-dev
linux-headers
curl
gnupg1
libxslt-dev
gd-dev
geoip-dev
&& curl -fSL -o nginx.tar.gz
&& curl -fSL.asc -o nginx.tar.gz.asc
&& export GNUPGHOME=“$(mktemp -d)”
&& found=‘’;
for server in

hkp://keyserver.ubuntu.com:80
hkp://p80.pool.sks-keyservers.net:80
pgp.mit.edu
; do
echo “Fetching GPG key $GPG_KEYS from $server”;
gpg --keyserver “$server” --keyserver-options timeout=10 --recv-keys “$GPG_KEYS” && found=yes && break;
done;
test -z “$found” && echo >&2 “error: failed to fetch GPG key $GPG_KEYS” && exit 1;
gpg --batch --verify nginx.tar.gz.asc nginx.tar.gz
&& rm -rf “$GNUPGHOME” nginx.tar.gz.asc
&& mkdir -p /usr/src
&& tar -zxC /usr/src -f nginx.tar.gz
&& rm nginx.tar.gz
&& cd /usr/src/nginx-$NGINX_VERSION
&& ./configure $CONFIG --with-debug
&& make -j$(getconf _NPROCESSORS_ONLN)
&& mv objs/nginx objs/nginx-debug
&& mv objs/ngx_http_xslt_filter_module.so objs/ngx_http_xslt_filter_module-debug.so
&& mv objs/ngx_http_image_filter_module.so objs/ngx_http_image_filter_module-debug.so
&& mv objs/ngx_http_geoip_module.so objs/ngx_http_geoip_module-debug.so
&& mv objs/ngx_stream_geoip_module.so objs/ngx_stream_geoip_module-debug.so
&& ./configure $CONFIG
&& make -j$(getconf _NPROCESSORS_ONLN)
&& make install
&& rm -rf /etc/nginx/html/
&& mkdir /etc/nginx/conf.d/
&& mkdir -p /usr/share/nginx/html/
&& install -m644 html/index.html /usr/share/nginx/html/
&& install -m644 html/50x.html /usr/share/nginx/html/
&& install -m755 objs/nginx-debug /usr/sbin/nginx-debug
&& install -m755 objs/ngx_http_xslt_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_xslt_filter_module-debug.so
&& install -m755 objs/ngx_http_image_filter_module-debug.so /usr/lib/nginx/modules/ngx_http_image_filter_module-debug.so
&& install -m755 objs/ngx_http_geoip_module-debug.so /usr/lib/nginx/modules/ngx_http_geoip_module-debug.so
&& install -m755 objs/ngx_stream_geoip_module-debug.so /usr/lib/nginx/modules/ngx_stream_geoip_module-debug.so
&& ln -s …/…/usr/lib/nginx/modules /etc/nginx/modules
&& strip /usr/sbin/nginx*
&& strip /usr/lib/nginx/modules/.so
&& rm -rf /usr/src/nginx-$NGINX_VERSION

# Bring in gettext so we can get envsubst, then throw
# the rest away. To do this, we need to install gettext
# then move envsubst out of the way so gettext can
# be deleted completely, then move envsubst back.
&& apk add --no-cache --virtual .gettext gettext
&& mv /usr/bin/envsubst /tmp/

&& runDeps="$(
scanelf --needed --nobanner --format ‘%n#p’ /usr/sbin/nginx /usr/lib/nginx/modules/
.so /tmp/envsubst
| tr ‘,’ ‘\n’
| sort -u
| awk ‘system(“[ -e /usr/local/lib/” $1 " ]") == 0 { next } { print “so:” $1 }’
)"
&& apk add --no-cache --virtual .nginx-rundeps $runDeps
&& apk del .build-deps
&& apk del .gettext
&& mv /tmp/envsubst /usr/local/bin/

# Bring in tzdata so users could set the timezones through the environment
# variables
&& apk add --no-cache tzdata

# forward request and error logs to docker log collector
&& ln -sf /dev/stdout /var/log/nginx/access.log
&& ln -sf /dev/stderr /var/log/nginx/error.log

COPY nginx.conf /etc/nginx/nginx.conf
COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf

EXPOSE 80

STOPSIGNAL SIGTERM

CMD [“nginx”, “-g”, “daemon off;”]

The “RUN rrdtool” part from the Dockerfile is working:

RRDtool 1.7.0  Copyright by Tobias Oetiker <tobi@oetiker.ch>
               Compiled Nov 22 2018 22:13:07
[skipped rest]

When it wants to add the module to nginx, things go wrong:

configuring additional modules
adding module in /tmp/mod_rrd_graph
checking for RRDtool ... not found
./configure: error: ngx_rrd_graph requires RRDtool 1.3 or later.

How should I troubleshoot this? It’s unclear to me why it thinks that RRDtool is not available.

Hi

Display the docker images right after your build fails.
You should see the image(s) (layers) that were created when the build failed.
The 1st image displayed will be the most recent image (layer) that was being built at the time the build failed.
You can then bring up a container from that image with a shell prompt and debug.

Example:

I’m building a simple HelloWorld C application on the Docker Official Alpine Linux docker image.
The build fails in step 8.

I purposely removed the install for the GCC compiler in my Dockerfile to cause the failure to illustrate how to debug a docker image build failure.

🐳  gforghetti:[~/GitHub/helloworld-c] $ docker image build -t gforghetti/helloworld-c:latest .
Sending build context to Docker daemon  8.192kB
Step 1/8 : FROM alpine:latest
latest: Pulling from library/alpine
6c40cc604d8e: Pull complete
Digest: sha256:b3dbf31b77fd99d9c08f780ce6f5282aba076d70a513a8be859d8d3a4d0c92b8
Status: Downloaded newer image for alpine:latest
 ---> caf27325b298
Step 2/8 : ARG BUILDDIR="/HelloWorld"
 ---> Running in cc6fda709fc8
Removing intermediate container cc6fda709fc8
 ---> b289a9247989
Step 3/8 : WORKDIR ${BUILDDIR}
 ---> Running in c192af6c7196
Removing intermediate container c192af6c7196
 ---> d4f39eef7593
Step 4/8 : LABEL description="HelloWorld C Application"
 ---> Running in 9e2b59ed4413
Removing intermediate container 9e2b59ed4413
 ---> e1c2e3e97c10
Step 5/8 : LABEL maintainer="Gary Forghetti, Docker Inc."
 ---> Running in 54f8fb0a72e1
Removing intermediate container 54f8fb0a72e1
 ---> be63d49c4440
Step 6/8 : CMD /HelloWorld/HelloWorld
 ---> Running in bec5a073c41e
Removing intermediate container bec5a073c41e
 ---> b402b0207eab
Step 7/8 : COPY ./HelloWorld.c ${BUILDDIR}
 ---> e68c8b34ee79
Step 8/8 : RUN apk update && gcc HelloWorld.c -o HelloWorld && chmod ugo+rx HelloWorld && rm -f HelloWorld.c && apk del gcc libc-dev && { apk cache clean --purge > /dev/null @>&1 || true; }
 ---> Running in e709e3032c43
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz
v3.9.0-17-g8b92b92a30 [http://dl-cdn.alpinelinux.org/alpine/v3.9/main]
v3.9.0-16-gfe0ab7c606 [http://dl-cdn.alpinelinux.org/alpine/v3.9/community]
OK: 9750 distinct packages available
/bin/sh: gcc: not found
The command '/bin/sh -c apk update && gcc HelloWorld.c -o HelloWorld && chmod ugo+rx HelloWorld && rm -f HelloWorld.c && apk del gcc libc-dev && { apk cache clean --purge > /dev/null @>&1 || true; }' returned a non-zero code: 127

I run a docker image ls command and see that the most recent image (layer) being built was e68c8b34ee79. Notice it has no name because the build failed and it was not tagged.

🐳  gforghetti:[~/GitHub/helloworld-c] $ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              e68c8b34ee79        10 seconds ago      5.53MB
alpine              latest              caf27325b298        9 days ago          5.53MB

So I can now run a container from that image (layer) and bring up a command shell (sh).
I can then run commands inside the shell to debug.

🐳  gforghetti:[~/GitHub/helloworld-c] $ docker container run -it e68c8b34ee79 sh
/HelloWorld # uname -a
Linux 6a7277eb91f5 4.9.125-linuxkit #1 SMP Fri Sep 7 08:20:28 UTC 2018 x86_64 Linux
/HelloWorld # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.9.0
PRETTY_NAME="Alpine Linux v3.9"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
/HelloWorld # ls -la
total 12
drwxr-xr-x    1 root     root          4096 Feb  9 18:05 .
drwxr-xr-x    1 root     root          4096 Feb  9 18:28 ..
-rwxr-xr-x    1 root     root          1742 Feb  9 17:34 HelloWorld.c
/HelloWorld # gcc
sh: gcc: not found
/HelloWorld # find / -name gcc*
/HelloWorld #

So I install the GCC compiler and headers and libraries inside the shell

/HelloWorld # apk add gcc libc-dev
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/alpine/v3.9/community/x86_64/APKINDEX.tar.gz
(1/12) Installing binutils (2.31.1-r2)
(2/12) Installing gmp (6.1.2-r1)
(3/12) Installing isl (0.18-r0)
(4/12) Installing libgomp (8.2.0-r2)
(5/12) Installing libatomic (8.2.0-r2)
(6/12) Installing libgcc (8.2.0-r2)
(7/12) Installing mpfr3 (3.1.5-r1)
(8/12) Installing mpc1 (1.0.3-r1)
(9/12) Installing libstdc++ (8.2.0-r2)
(10/12) Installing gcc (8.2.0-r2)
(11/12) Installing musl-dev (1.1.20-r3)
(12/12) Installing libc-dev (0.7.1-r0)
Executing busybox-1.29.3-r10.trigger
OK: 103 MiB in 26 packages
/HelloWorld #

I can then re-run the command that failed inside the shell by doing a copy/paste.

/HelloWorld # gcc HelloWorld.c -o HelloWorld && chmod ugo+rx HelloWorld && rm -f HelloWorld.c && apk del gcc libc-dev && { apk cache clean --purge > /dev/null @>&1 || true; }
(1/12) Purging gcc (8.2.0-r2)
(2/12) Purging binutils (2.31.1-r2)
(3/12) Purging libatomic (8.2.0-r2)
(4/12) Purging libgomp (8.2.0-r2)
(5/12) Purging libc-dev (0.7.1-r0)
(6/12) Purging musl-dev (1.1.20-r3)
(7/12) Purging mpc1 (1.0.3-r1)
(8/12) Purging mpfr3 (3.1.5-r1)
(9/12) Purging isl (0.18-r0)
(10/12) Purging gmp (6.1.2-r1)
(11/12) Purging libstdc++ (8.2.0-r2)
(12/12) Purging libgcc (8.2.0-r2)
Executing busybox-1.29.3-r10.trigger
OK: 6 MiB in 14 packages

C Compile worked.

/HelloWorld # ls -la
total 28
drwxr-xr-x    1 root     root          4096 Feb  9 18:33 .
drwxr-xr-x    1 root     root          4096 Feb  9 18:28 ..
-rwxr-xr-x    1 root     root         18816 Feb  9 18:33 HelloWorld
/HelloWorld #

I can also run the program.

/HelloWorld # ./HelloWorld
Hello World!
I am running on Linux x86_64.
It is Saturday February 09, 2019 and the time is 06:19:46 PM.
/HelloWorld #

You then fix your Dockerfile and retry your build.

1 Like

Hi,

Thanks for your elaborate explanation! It’s helpful to know you can actually run the last built layer and interactively troubleshoot it.

I guess my problem is not related to docker, but more with how to do this (compiling Nginx from scratch in Linux). Not sure if I should ask for help here or somewhere else.

The command that goes wrong is ./configure $CONFIG --with-debug. It gives the following output:

/usr/src/nginx-1.15.8 # ./configure $CONFIG --with-debug
checking for OS
+Linux 4.4.59+ x86_64
checking for C compiler … found
+using GNU C compiler
+gcc version: 8.2.0 (Alpine 8.2.0)
checking for gcc -pipe switch … found
checking for -Wl,-E switch … found
checking for gcc builtin atomic operations … found
checking for C99 variadic macros … found
checking for gcc variadic macros … found
checking for gcc builtin 64 bit byteswap … found

skipped some lines

checking for struct dirent.d_namlen … not found
checking for struct dirent.d_type … found
checking for sysconf(_SC_NPROCESSORS_ONLN) … found
checking for sysconf(_SC_LEVEL1_DCACHE_LINESIZE) … not found
checking for openat(), fstatat() … found
checking for getaddrinfo() … found
configuring additional modules
adding module in /tmp/mod_rrd_graph
checking for RRDtool … not found
./configure: error: ngx_rrd_graph requires RRDtool 1.3 or later.

It can’t find RRDtool? Strange:

/usr/src/nginx-1.15.8 # rrdtool
RRDtool 1.7.0  Copyright by Tobias Oetiker <tobi@oetiker.ch>
               Compiled Nov 22 2018 22:13:07

Also, module files seem to be where the need to be:

/usr/src/nginx-1.15.8 # ls /tmp/mod_rrd_graph/
config                       ngx_http_rrd_graph_module.c

Are there more troubleshooting tips for this particular case? Or should I report this to the author of the module?

Thanks!

Sorry, I’m not familiar with the rrdtool. If I was in your shoes I would google for that error, and/or go to the support site for that tool and post a question/issue.

I would go here and post an issue -> https://github.com/hajuuk/nginx-bundles

Thanks for that pointer. I posted an issue and also send a message to the author of the module. If a solution is found, I will post it here as well for informational purposes.

I managed a succesful build by adding rrdtool-dev to the list of installed packages in the Dockerfile (the part that starts with && apk add --no-cache --virtual .build-deps followed by a list of packages). So that part of the Dockerfile now looks like this with the last line being added:

&& apk add --no-cache --virtual .build-deps \
        gcc \
        libc-dev \
        make \
        openssl-dev \
        pcre-dev \
        zlib-dev \
        linux-headers \
        curl \
        gnupg1 \
        libxslt-dev \
        gd-dev \
        geoip-dev \
        rrdtool-dev \

While all this isn’t related to Docker, this solution might be of interest to those reading this thread.