How to fix "Illegal option" error when compiling a dockerfile? - docker

I have an application in dockerfile where it is necessary to call a .sh file to download packages, but there is always an error when calling this file.
My dockerfile is:
FROM alpine:3.12 as builder
ARG VERSION=7.16.0
ARG DISTRO=tomcat
ARG SNAPSHOT=true
ARG JMX_PROMETHEUS_VERSION=0.12.0
RUN apk add --no-cache \
bash \
ca-certificates \
maven \
tar \
wget \
xmlstarlet
COPY settings.xml download.sh camunda-run.sh camunda-tomcat.sh camunda-wildfly.sh /tmp/
RUN /tmp/download.sh
FROM alpine:3.12
RUN apk add --no-cache \
bash \
ca-certificates \
curl \
openjdk11-jre-headless \
tzdata \
tini \
xmlstarlet \
&& curl -o /usr/local/bin/wait-for-it.sh \
"https://raw.githubusercontent.com/vishnubob/wait-for-it/a454892f3c2ebbc22bd15e446415b8fcb7c1cfa4/wait-for-it.sh" \
&& chmod +x /usr/local/bin/wait-for-it.sh
RUN addgroup -g 1000 -S camunda && \
adduser -u 1000 -S camunda -G camunda -h /camunda -s /bin/bash -D camunda
WORKDIR /camunda
USER camunda
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["./camunda.sh"]
COPY --chown=camunda:camunda --from=builder /camunda .
My download.sh file looks exactly like this: https://github.com/camunda/docker-camunda-bpm-platform/blob/next/download.sh
When running the command: docker build . -t servicecamundadocker/latest i get the error:
=> ERROR [builder 4/4] RUN /tmp/download.sh 0.2s ------
> [builder 4/4] RUN /tmp/download.sh:
#11 0.216 /bin/sh: illegal option -
------
Does anyone know how to fix this error? Thanks

After a lot of research, I found the solution.
The problem is that Windows uses \r\n as an end of line, whereas unix only uses \n. So, inside my download.sh file, there was a ^M character that led to the error /bin/sh: illegal option
The solution was to copy the code from the downlod.sh file and convert it to LF:
Use the text editor such as Notepad++ at the Windows machine to convert
Go to menu Edit -> EOL Conversion -> Unix (LF)
Once that is done, the docker build works correctly.
Thank you all for the support.

Related

Edit / hide Nginx Server header under Alpine Linux

When I use curl --head to test my website, it returns the server information.
I followed this tutorial to hide the nginx server header.
But when I run the command yum install nginx-module-security-headers
, it returns yum: not found.
I also tried apk add nginx-module-security-headers, and it shows that the package is missing.
I have used nginx:1.17.6-alpine as my base docker image. Does anyone know how to hide the server from header under this Alpine?
I think I have an easier solution here: https://gist.github.com/hermanbanken/96f0ff298c162a522ddbba44cad31081. Big thanks to hermanbanken on Github for sharing this gist.
The idea is to create a multi stage build with the nginx alpine image to be a base for compiling the module. This turns into the following Dockerfile:
ARG VERSION=alpine
FROM nginx:${VERSION} as builder
ENV MORE_HEADERS_VERSION=0.33
ENV MORE_HEADERS_GITREPO=openresty/headers-more-nginx-module
# Download sources
RUN wget "http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz" -O nginx.tar.gz && \
wget "https://github.com/${MORE_HEADERS_GITREPO}/archive/v${MORE_HEADERS_VERSION}.tar.gz" -O extra_module.tar.gz
# For latest build deps, see https://github.com/nginxinc/docker-nginx/blob/master/mainline/alpine/Dockerfile
RUN apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
make \
openssl-dev \
pcre-dev \
zlib-dev \
linux-headers \
libxslt-dev \
gd-dev \
geoip-dev \
perl-dev \
libedit-dev \
mercurial \
bash \
alpine-sdk \
findutils
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN rm -rf /usr/src/nginx /usr/src/extra_module && mkdir -p /usr/src/nginx /usr/src/extra_module && \
tar -zxC /usr/src/nginx -f nginx.tar.gz && \
tar -xzC /usr/src/extra_module -f extra_module.tar.gz
WORKDIR /usr/src/nginx/nginx-${NGINX_VERSION}
# Reuse same cli arguments as the nginx:alpine image used to build
RUN CONFARGS=$(nginx -V 2>&1 | sed -n -e 's/^.*arguments: //p') && \
sh -c "./configure --with-compat $CONFARGS --add-dynamic-module=/usr/src/extra_module/*" && make modules
# Production container starts here
FROM nginx:${VERSION}
COPY --from=builder /usr/src/nginx/nginx-${NGINX_VERSION}/objs/*_module.so /etc/nginx/modules/
.... skipped inserting config files and stuff ...
# Validate the config
RUN nginx -t
Alpine repo probably doesn't have the ngx_security_headers module but, the mentioned tutorial also provides an option of using Headers More module. You should be able to install this module in your alpine distro using the command:
apk add nginx-mod-http-headers-more
Hope it helps.
Source
I found the alternate solution. The reason that it shows binary not compatible is because I have one nginx pre-installed under the target route, and it is not compatible with the header-more module I am using. That means I cannot simply install the third party library from Alpine package.
So I prepare a clean Alpine OS, and follow the GitHub repository to build Nginx from the source with additional feature. The path of build result is the prefix path you specified.

Cannot configure code with echo in docker with alpine os but can in ubuntu

I have a Dockerfile which was originally pulling from ubuntu and I recently came across alpine which is more lightweight so would like to pull from that instead. Part of the code I'm trying to build is called Healpix which depends on cfitsio. When I originally built the ubuntu version I found this Dockerfile https://github.com/MilesCranmer/dockers/blob/master/dockerfiles/healpix.
Essentially the problem is the following works in ubuntu but not with alpine:
RUN echo "3\ngfortran\n\nY\n\n\ngcc\n\n\n\n\nN\n1\nY\nN\nN\n0\n" |
./configure && make
The error I get is
Something went wrong ...
Quitting configuration script !
./configure: exit: line 162: Illegal number: -1
The command '/bin/sh -c echo "3\ngfortran\n\nY\n\n\ngcc\n\n\n\n\nN\n1\nY\nN\nN\n0\n" | ./configure && make' returned a non-zero code: 2
somewhat confusingly the configure script in question isn't 162 lines long https://sourceforge.net/p/healpix/code/HEAD/tree/branches/branch_v350r1006/configure. I have tried installing bash and changing script to that but that didn't work.
ubuntu Dockerfile
FROM ubuntu
RUN apt-get update && apt-get install -y gcc g++ gfortran make wget
WORKDIR /home
RUN wget \
http://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/cfitsio_latest.tar.gz \
&& tar xzf cfitsio_latest.tar.gz
WORKDIR cfitsio
RUN ./configure --prefix=/usr && make && make install
WORKDIR /home
RUN wget \
https://sourceforge.net/projects/healpix/files/Healpix_3.50/Healpix_3.50_2018Dec10.tar.gz \
&& tar xzf Healpix*.tar.gz
WORKDIR Healpix_3.50
RUN echo \
"3\ngfortran\n\nY\n\n\ngcc\n\n\n\n\nN\n1\nY\nN\nN\n0\n" | ./configure \
&& make
alpine Dockerfile
FROM alpine
RUN apk --no-cache add gcc g++ gfortran make wget
WORKDIR /home
RUN wget \
http://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/cfitsio_latest.tar.gz \
&& tar xzf cfitsio_latest.tar.gz
WORKDIR cfitsio
RUN ./configure --prefix=/usr && make && make install
WORKDIR /home
RUN wget \
https://sourceforge.net/projects/healpix/files/Healpix_3.50/Healpix_3.50_2018Dec10.tar.gz \
&& tar xzf Healpix*.tar.gz
WORKDIR Healpix_3.50
RUN echo \
"3\ngfortran\n\nY\n\n\ngcc\n\n\n\n\nN\n1\nY\nN\nN\n0\n" | ./configure \
&& make
TL;DR
In your Dockerfile, use :
RUN /bin/echo -e "3\ngfortran\n[...]" | ./configure && make
to have the same behavior on Ubuntu and Alpine.
Explanations
The ./configure script is executed with /bin/sh (see the shebang). On Ubuntu, /bin/sh is a link to /bin/dash, while on Alpine, /bin/sh is a link to /bin/busybox.
The following small example reproduces your problem.
Consider the following ./configure script :
#!/bin/sh
read -p "1st prompt : " first
read -p "2nd prompt : " second
echo "$first-$second"
On Ubuntu :
docker run --rm -v $PWD/configure:/configure ubuntu:18.04 \
/bin/sh -c 'echo "a\nb" | ./configure'
prints :
a-b
While, on Alpine :
docker run --rm -v $PWD/configure:/configure alpine:3.8 \
/bin/sh -c 'echo "a\nb" | ./configure'
prints :
anb-
On Alpine (busybox), the echoed string (a\nb) is interpreted as a single argument, while on Ubuntu (dash), the \n is used to separate both arguments.
To have the same behavior as Ubuntu on Alpine, you can run :
docker run --rm -v $PWD/configure:/configure alpine:3.8 /bin/sh -c 'echo "a
b
" | ./configure'
or :
docker run --rm -v $PWD/configure:/configure alpine:3.8 /bin/sh -c \
'echo -e "a\nb" | ./configure'
(see the -e parameter of echo)
These 2 commands print :
a-b
As for your Dockerfile, you should write something like :
RUN /bin/echo -e "3\ngfortran\n[...]" | ./configure && make
/bin/echo is used instead of echo because on Ubuntu, echo -e "3\ngfortran\n[...]" will print -e 3\nngfortran\n[...].
This is because echo is parsed a shell built-in, while /bin/echo is explicitly not (source : https://github.com/moby/moby/issues/8949#issuecomment-61682684).

Create alpine linux iso from docker - libburn permission denied

I have been trying to build an iso-image for alpine-linux inside a docker container following the standard instructions here however i seem to be unable to actually write the .iso back into the mounted volume due to libburn :
>>> mkimage-x86_64: Creating alpine-standard-edge-x86_64.iso
xorriso 1.4.8 : RockRidge filesystem manipulator, libburnia project.
libburn : SORRY : Failed to open device (a pseudo-drive) : Permission denied
libburn : FATAL : Burn run failed
xorriso : FATAL : -abort_on 'FAILURE' encountered 'FATAL' during image writing
libisofs: MISHAP : Image write cancelled
xorriso : FAILURE : libburn indicates failure with writing.
This is the standard result of trying to run the downloaded script from the tutorial:
sh aports/scripts/mkimage.sh --tag edge --outdir /build2/ --arch x86_64 --repository http://dl-cdn.alpinelinux.org/alpine/edge/main --profile standard
The docker image im using:
FROM alpine:latest
RUN addgroup root abuild
RUN apk add --update \
alpine-sdk \
# build-base \
apk-tools \
alpine-conf \
busybox \
git \
fakeroot \
syslinux \
xorriso \
squashfs-tools \
mtools \
dosfstools \
grub-efi \
&& rm -rf /var/cache/apk/*
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN mkdir /usr/src/app/build
RUN touch /usr/src/app/build/worked.txt
RUN adduser -G abuild -g "Alpine Package Builder" -s /bin/sh -u 12345 -D builder
RUN echo "builder:newpass"|chpasswd
RUN chgrp -R abuild /usr/local; \
find /usr/local -type d | xargs chmod g+w; \
echo "builder ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/builder; \
chmod 0440 /etc/sudoers.d/builder
WORKDIR /build2/
RUN git clone git://git.alpinelinux.org/aports
RUN chmod +x aports/scripts/mkimage.sh
RUN abuild-keygen -i -a
USER builder
I have looked over the official forum however only one post mentioned something similar but did not allude to any actual resolution.
Failing to find a solution for this, can anyone else recommend a good alternative minimal distro that can be build an iso via script for x_86, x_64 and rpi?
You can easily create your own Alpine Linux ISO image using script alpine-make-vm-image.
Example:
sudo ./alpine-make-vm-image \
--image-format qcow2 \
--image-size 5G \
--packages "ca-certificates git ssl_client" \
--script-chroot \
alpine-$(date +%Y-%m-%d).qcow2 -- ./configure.sh
You're getting a permission denied error because the user you created can't access the pseudo device needed by xorriso. I removed all the user creation parts and just ran the whole thing as root and it works.
Here's the Dockerfile I used:
FROM alpine:latest
RUN apk add --no-cache \
alpine-conf \
alpine-sdk \
apk-tools \
dosfstools \
grub-efi \
mtools \
squashfs-tools \
syslinux \
xorriso
WORKDIR /src
RUN git clone git://git.alpinelinux.org/aports
RUN chmod +x aports/scripts/mkimage.sh
RUN addgroup root abuild
RUN abuild-keygen -i -a -n
WORKDIR /build
ENTRYPOINT /src/aports/scripts/mkimage.sh
CMD "--tag edge --arch x86_64 --repository http://dl-cdn.alpinelinux.org/alpine/edge/main --profile standard"
Then build and run.
docker build -t alpine-iso .
docker run -v "$(pwd):/build" -it alpine-iso

Why do I get "unzip: short read" when I try to build an image from Dockerfile?

From Spring Microservices in Action book: I am trying to use the Docker Maven Plugin to build a docker image for deploy a Java microservice as Docker container to the cloud.
Dockerfile:
FROM openjdk:8-jdk-alpine
RUN mkdir -p /usr/local/configserver
ADD jce_policy-8.zip /tmp/
RUN unzip /tmp/jce_policy-8.zip && \
rm /tmp/jce_policy-8.zip && \
yes | cp -v /tmp/UnlimitedJCEPolicyJDK8/*.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/
ADD #project.build.finalName#.jar /usr/local/configserver/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.sh
Output related to step 4 in Dockerfile:
...
---> Using cache
---> dd33d4c12d29
Step 4/8 : RUN unzip /tmp/jce_policy-8.zip && rm /tmp/jce_policy-8.zip && yes | cp -v /tmp/UnlimitedJCEPolicyJDK8/*.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/
---> Running in 1071273ceee5
Archive: /tmp/jce_policy-8.zip
unzip: short read
Why do I get unzip: short read when I try to build the image?
Somehow, curl on alpine linux distro can't set cookie headers correctly while downloading jce zip file. It seems it downloads a zip file but in fact it is an html error page. If you view the file you can see that it is an html file. I've used wget instead of curl and it successfully downloaded file. Then unzip operation worked as expected.
FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd
RUN mkdir -p /usr/local/configserver
RUN cd /tmp/ && \
wget 'http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip' --header "Cookie: oraclelicense=accept-securebackup-cookie" && \
unzip jce_policy-8.zip && \
rm jce_policy-8.zip && \
yes |cp -v /tmp/UnlimitedJCEPolicyJDK8/*.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/
ADD #project.build.finalName#.jar /usr/local/configserver/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.sh
It's possible your jce_policy-8.zip archive is being recognized as a compressed archive and expanded by the ADD instruction. If so, you can skip unzipping on the next line. Or, switch to the COPY instruction, which does no special processing of local archives.
In general, I recommend always using the COPY instruction to bring in files and directories from the build context. Only use ADD when you specifically want the extra unpacking behaviour.
I'm find solved link
FROM openjdk:8-jdk-alpine
RUN apk update && apk upgrade && apk add netcat-openbsd && apk add curl
RUN mkdir -p /usr/local/configserver
RUN cd /tmp/ && \
**curl -L -b "oraclelicense=a" http://download.oracle.com/otn-pub/java/jce/8/jce_policy-8.zip -O** && \
unzip jce_policy-8.zip && \
rm jce_policy-8.zip && \
yes |cp -v /tmp/UnlimitedJCEPolicyJDK8/*.jar /usr/lib/jvm/java-1.8-openjdk/jre/lib/security/
ADD #project.build.finalName#.jar /usr/local/configserver/
ADD run.sh run.sh
RUN chmod +x run.sh
CMD ./run.sh
Maybe it is related to the fact that the unzip command in alpine is provided busybox and not the standard unzip tool.
Busybox do have bugs related to this error:
https://bugs.busybox.net/show_bug.cgi?id=8821
Here is a related issue with more details:
https://github.com/wahern/luaossl/issues/103
As a workaround installing the standard unzip command should work.

python and oracle client on docker image

I want to create a docker image with oracle client and cx_oracle of python. I am using multi stage docker to build the image but I am missing an env variable due to which cx_oracle is not able to find an oracle client library.
FROM oraclelinux:7-slim
RUN curl -o /etc/yum.repos.d/public-yum-ol7.repo https://yum.oracle.com/public-yum-ol7.repo && \
yum-config-manager --enable ol7_oracle_instantclient && \
yum -y install oracle-instantclient18.3-basic oracle-instantclient18.3-devel oracle-instantclient18.3-sqlplus && \
rm -rf /var/cache/yum && \
echo /usr/lib/oracle/18.3/client64/lib > /etc/ld.so.conf.d/oracle-instantclient18.3.conf && \
ldconfig
ENV PATH=$PATH:/usr/lib/oracle/18.3/client64/bin
FROM python:slim
COPY ./requirement.txt ./requirement.txt
RUN pip install -r ./requirement.txt
COPY --from=0 /usr/lib/oracle/18.3/client64/lib /root/usr/lib/oracle/18.3/client64/lib
COPY --from=0 /usr/lib/oracle/18.3/client64/bin /root/usr/lib/oracle/18.3/client64/bin
ENV PATH=$PATH:/root/usr/lib/oracle/18.3/client64/bin:/root/usr/lib/oracle/18.3/client64/lib
ENV ORACLE_HOME=/root/usr/lib/oracle/18.3/client64/:$ORACLE_HOME
ENV LD_LIBRARY_PATH=/root/usr/lib/oracle/18.3/client64/:$LD_LIBRARY_PATH
RUN echo $PATH
RUN echo $ORACLE_HOME
RUN chmod 755 /root/usr/lib/oracle/18.3/client64/lib/*
RUN ls -l /root/usr/lib/oracle/18.3/client64/lib
CMD ["chmod","755","/root/usr/lib/oracle/18.3/client64/lib/*"]
CMD ["ls", "-l" ,"/root/usr/lib/oracle/18.3/client64/lib"]
CMD ["python","test.py"]
Below is the error
DPI-1047: 64-bit Oracle Client library cannot be loaded: "libclntsh.so: cannot open shared object file: No such file or directory". See https://oracle.github.io/odpi/doc/installation.html#linux
Oracle has Python Dockerfiles at https://github.com/oracle/docker-images/tree/main/OracleLinuxDevelopers
Also see https://blogs.oracle.com/opal/docker-for-oracle-database-applications-in-nodejs-and-python-part-1

Resources