Unable to build the Docker image - docker

The below image couldn't be built because this image doesn't support shell form and supports only exec form, hence RUN as well as ENTRYPOINT support only vector form. Please suggest how to build the exact image as it is important to use this one.
FROM gcr.io/distroless/java:8
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /aaa/bbb/*
COPY target/${JAR_FILE} /xyz/yy.jar
ENTRYPOINT exec java $JAVA_OPTS -Djdk.tls.client.protocols="tls" -jar /xyz/yy.jar $0 $#
Also, When I try to specify RUN in vector form I get "exec: "apt-get" executable file not found in $PATH".

The exec ... $# use seems a bit strange here...
ENTRYPOINT is configuring your container to run as the executable, allowing your CMD to provide default arguments to your executable, so the use of $0 $# is 100% unnecessary.
Although I don't have any Java lying around to use, something like this should in theory work:
ARG JAR_FILE=build/*.jar
FROM gcr.io/distroless/java:8
RUN export DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
&& apt-get install -qqy --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*```
COPY ${JAR_FILE} app.jar
ENV JAVA_OPTS="-Djdk.tls.client.protocols=tls"
ENTRYPOINT ["java", "-jar", "$JAVA_OPTS", "-jar", "app.jar"]
# By providing an entrypoint above, your CMD can optionally define any default
# arguments you might want to fallback to.
# CMD [ "--java", "--things" ]
The preferred usage however is to leverage your CMD as the exec and not include the ENTRYPOINT in this type of use at all. Then, your entirely CMD is customizable and you can remove the need for $JAVA_OPTS:
ARG JAR_FILE=build/*.jar
FROM gcr.io/distroless/java:8
RUN export DEBIAN_FRONTEND=noninteractive \
&& apt-get update \
&& apt-get install -qqy --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*```
COPY ${JAR_FILE} app.jar
ENV JAVA_OPTS="-Djdk.tls.client.protocols=tls"
# By providing an entrypoint above, your CMD can optionally define any default
# arguments you might want to fallback to.
CMD ["java", "-jar", "$JAVA_OPTS", "-jar", "app.jar"]
If you did keep it the same, an additional change I made was moving your JAVA_OPTS to an ARG. The simple rule of thumb here is: ARG is for build, ENV is for runtime.
Warning: The above over simplification is overly simple.
But, this would change your build command (if you needed to overwrite the JAR_FILE to this:
docker build -t jarjar/binks --build-arg JAR_FILE=another/file.jar .
And you would run it quite similarly:
JAVA_OPTS="-Djdk.tls.client.protocols='TLSv1,TLSv1.1' -Xms#G -Xmx#G" &&
docker run jarjar/binksjarjar/binks --args=here
I do encourage you to read further into both CMD and `ENTRYPOINT to understand the pros/cons of using them together/separately.
https://docs.docker.com/engine/reference/builder/#cmd
https://docs.docker.com/engine/reference/builder/#entrypoint
Edit: Follow up
Unfortunately I wasn't actually able to run any of these before posting my answer, and reviewing the comment from koorkevani, that's 100% more the issue you're going to be running into over my feedback.
Take his answer and let us know if you run into any other issues :)

Related

Docker exits container

I am trying to build my own docker image for apache2 and PHP. Can anyone tell my why my container exits after run when it supposes to run ["apache2ctl", "-D", "FOREGROUND"]?
FROM ubuntu:latest
RUN apt update -y && apt upgrade -y
RUN apt install software-properties-common -y
RUN add-apt-repository ppa:ondrej/php -y
RUN apt update -y && apt upgrade -y
ARG DEBIAN_FRONTEND=noninteractive
RUN DEBIAN_FRONTEND=noninteractive apt install -y nano vim iputils-ping sudo git curl php php-cli php-fpm
RUN apt install -y php-json php-mysql
RUN apt install -y php-zip php-mbstring php-curl php-xml php-pear php-bcmath
RUN apt install psmisc -y
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOF_DIR /var/log/apache2
# RUN useradd -ms /bin/bash devwl
EXPOSE 80/tcp
ENTRYPOINT ["/bin/sh", "-c"]
CMD ["apache2ctl", "-D", "FOREGROUND"]
Build command:
docker build -t www .
Run command:
docker run -itd -p 80:80 www
Ouput docker ps:
Just tried to build your Dockerfile. docker logs shows a problem with start command. Running container without -D option works well...
CMD ["apache2ctl", "start"]
Do you need to use <IfDefine ...> in conf files?
You need to delete the ENTRYPOINT line.
Since you have both an ENTRYPOINT and a CMD, they get combined together into a single argument list. That means you have an effective command like
ENTRYPOINT+CMD ["/bin/sh", "-c", "apache2ctl", "-D", "FOREGROUND"]
But sh -c only reads in the single next argument and executes it. The remaining arguments would be accessible inside that string as positional parameters $0, $1, ... but unless you refer to one of those then the command you're eventually running is only apachectl with no arguments.
You only need to invoke a shell at all if your command uses shell features (referencing environment variables or running multiple commands). Yours doesn't, so you don't need anything that mentions a shell; just delete the ENTRYPOINT and have the existing CMD start Apache.
In a Dockerfile, you shouldn't usually need to say sh -c at all. If you do need to invoke a shell to run some command, you can use Docker shell syntax as a plain string without the JSON-array syntax; for example
# needs a shell because of $VARIABLE and command; command syntax
CMD touch "$APACHE_LOG_DIR/started"; exec apache2ctl -DFOREGROUND
(If you do need to override this command with docker run arguments or in a Compose command:, these syntaxes will not automatically insert a shell wrapper and there you do need to specifically say sh -c 'some command' if you need a shell to process the command string; again note the single quotes to make the command string a single argument.)

Extending a docker image to run a diff command

I have a docker file as below.
FROM registry.access.redhat.com/ubi8/ubi
ENV JAVA_HOME /usr/lib/jvm/zulu11
RUN \
set -xeu && \
yum -y -q install https://cdn.azul.com/zulu/bin/zulu-repo-1.0.0-1.noarch.rpm && \
yum -y -q install python3 zulu11-jdk less && \
yum -q clean all && \
rm -rf /var/cache/yum && \
alternatives --set python /usr/bin/python3 && \
groupadd trino --gid 1000 && \
useradd trino --uid 1000 --gid 1000 && \
mkdir -p /usr/lib/trino /data/trino && \
chown -R "trino:trino" /usr/lib/trino /data/trino
ARG TRINO_VERSION
COPY trino-cli-${TRINO_VERSION}-executable.jar /usr/bin/trino
COPY --chown=trino:trino trino-server-${TRINO_VERSION} /usr/lib/trino
COPY --chown=trino:trino default/etc /etc/trino
EXPOSE 8080
USER trino:trino
ENV LANG en_US.UTF-8
CMD ["/usr/lib/trino/bin/run-trino"]
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s \
CMD /usr/lib/trino/bin/health-check
I would like to extend this Dockerfile and run a run a couple of instructions before running the main command in the Dockerfile? Not sure how to to that.
If you want to run those commands when the container starts, you can use an entrypoint to leave the original command untouched.
The exec $# will execute the arguments that were passed to the entrypoint with PID 1. Whatever arguments were provided as CMD, those will be in $#, so you essentially execute the CMD after the ENTRYPOINT, doesn't matter what this command might be.
Create an entrypoint script:
#!/usr/bin/env sh
# run some preperation
exec "$#"
And then you copy that into your build and use it.
FROM baseimage
COPY --chmod=755 ./entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
If you want to run those commands on build, use a FROM instruction and add your RUN instructions. The new image will use the CMD from the base image. So you don't need to set any CMD.
FROM baseimage
RUN more
RUN stuff
Since you can only have one CMD statement in a Dockerfile (if you have more than one, only the last one is executed), you need to get all your commands into a single CMD statement.
You can use the ability of the shell to chain commands using the && operator, like this
CMD my-first-command && \
my-second-command && \
/usr/lib/trino/bin/run-trino
That will run your commands first before running run-trino which is the current CMD.
Whenever you are using a base image, docker throw's away the last layer of the image. So you can extend that image, by writing your own image.
for example: this is my first image (that i get from a third party, just like you)
FROM alpine:latest
CMD echo "hello"
I want to extend it, to output hello world instead of hello, so I extend write another docker file like this
FROM first:latest
CMD echo "hello world"
and when I build the image and run it,
docker build -t second .
docker run second
I get my expected output
hello world
Hopefully that helps

what is the lightest docker image to be used for automation test?

I need to create a docker image to run the UI automation test in headless mode.
it should contain:
NodeJs, JDK, chrome browser.
I have created the one below, which is 1.6 GB, is there a better way to make it lighter and optimized
FROM node:slim
ENV DEBIAN_FRONTEND noninteractive
WORKDIR /project
#=============================
# Install Dependenices
#=============================
SHELL ["/bin/bash", "-c"]
RUN apt update && apt install -y wget bzip2 openjdk-11-jre xvfb libnotify-dev
#==============================
# install chrome
#==============================
RUN wget https://dl.google.com/linux/direct/${CHROME_PACKAGE} && \
dpkg-deb -x ${CHROME_PACKAGE} / && \
apt-get install -f -y
#=========================
# Copying Scripts to root
#=========================
COPY . /project
RUN chmod a+x ./execute_test.sh
#=======================
# framework entry point
#=======================
CMD [ "/bin/bash" ]
Your build will fail if not use SHELL ["/bin/bash", "-c"]? Otherwise eliminate this line can save you a layer. You can combine the 2 RUN into one which save you a few more. Then try --squash flag when building your image. Note your docker daemon needs to have experiment enabled to use this flag. You should get a smaller image using these steps.

How can I extend unregistered docker images or dockerfiles?

Or maybe instead of using FROM there is a way to inject the contents of another dockerfile into the start of my own.
In any case you will need a base Operating System image to source from and then you can use the content of the "other" Dockerfile you want to use and append your own command and form a complete file.
For example the below line will just include the base OS layer:
FROM ubuntu
MAINTAINER Prasanjit Singh
And then add stuff from the borrowed docker file, say the below lines:
ENV USER root ENV PASS aiPeekai0AeZ2meephoolais7doo1thu
RUN \ apt-get update && \ apt-get -y install \
mysql-server-5.5 && \ rm -rf /var/lib/apt/lists/*
COPY my.cnf /etc/mysql/my.cnf COPY start.sh start.sh
VOLUME ["/var/lib/mysql"]
RUN rm /usr/sbin/policy-rc.d CMD ["/start.sh"]
EXPOSE 3306
And finally add your append your own(if any) and the file looks like this now:
FROM ubuntu
MAINTAINER Prasanjit Singh
ENV USER root
ENV PASS aiPeekai0AeZ2meephoolais7doo1thu
RUN \
apt-get update && \
apt-get -y install \
mysql-server-5.5 && \
rm -rf /var/lib/apt/lists/*
COPY my.cnf /etc/mysql/my.cnf
COPY start.sh start.sh
VOLUME ["/var/lib/mysql"]
RUN rm /usr/sbin/policy-rc.d
RUN rm /your/shell/script_or_command.sh # Add your stuff
CMD ["/start.sh"]
EXPOSE 3306
And you are done with the Dockerfile. Just build it and get your container launched. Let me know if it you need anything.

Dockerfile supervisord cannot find path

For some reason supervisord cannot start up when executing docker run... If I log out the path where the configuration is stored for supervisord I can clearly see that the file is present.
Below is the part of my Dockerfile thats not currently commented out.
FROM ubuntu:16.04
MAINTAINER Kevin Gilbert
# Update Packages
RUN apt-get -y update
# Install basics
RUN apt-get -y install curl wget make gcc build-essential
# Setup Supervisor
RUN apt-get -y install supervisor
RUN mkdir -p /var/log/supervisor
COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
CMD ["/usr/bin/supervisord", "-c /etc/supervisor/conf.d/supervisord.conf"]
Here is the error I get in terminal after running.
remote-testing:analytics-portal kgilbert$ docker run kmgilbert/portal
Error: could not find config file /etc/supervisor/conf.d/supervisord.conf
For help, use /usr/bin/supervisord -h
Try with the exec form of CMD:
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
or with the shell form
CMD /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
Depending on the OS used by the base image, you might not even have to specify the supervisord.conf in the command line (see this example, or the official documentation)
It happended to me on Alpine linux 3.9, but eventually ran successfully with
CMD ["supervisord", "-c", "<path_to_conf_file>"]

Resources