I want to create a few images where each dockerfile will include some common layers. Its all mixed and no consistent sequence for all of the images. E.g. some will need to have java on them, and I want to define the below lines (taken from the official java 8 dockerfile) as a building block (layer) that will be referenced in other dockerfiles.
In some cases it could be more than one layer that I would want to reuse - making this requirement recursive in nature (building blocks constructed of building blocks).
RUN \
echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections && \
add-apt-repository -y ppa:webupd8team/java && \
apt-get update && \
apt-get install -y oracle-java8-installer && \
rm -rf /var/lib/apt/lists/* && \
rm -rf /var/cache/oracle-jdk8-installer
Is that supported by Docker today? Is it a good practice to install e.g. Java separately as a layer that way ... or should I merge it with other installs (to keep the image minimal)? What are the best practices around such a scenario please?
=========== UPDATE ==============
Seems like the feature of referencing/including is not supported. But I am still not sure about the best practices ...
@Sri pointed out below to the best practices: https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#run
Where is it encouraged to use "RUN apt-get update && apt-get install -y" for all package installation.
But does it also mean that we are not encouraged to use different layers for different packages? like the below example:
RUN apt-get update && apt-get install -y package-foo
RUN apt-get update && apt-get install -y package-bar
With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don't want in the final image.
Each layer contains the filesystem changes to the image for the state before the execution of the command and the state after the execution of the command. Docker uses a layer cache to optimize and speed up the process of building Docker images.
The WORKDIR command is used to define the working directory of a Docker container at any given time. The command is specified in the Dockerfile. Any RUN , CMD , ADD , COPY , or ENTRYPOINT command will be executed in the specified working directory.
When copying a single file to an existing LOCALPATH, the docker cp command will either overwrite the contents of LOCALPATH if it is a file or place it into LOCALPATH if it is a directory, overwriting an existing file of the same name if one exists. For example, this command: $ docker cp sharp_ptolemy:/tmp/foo/myfile.
Based on further reading:
There is no INCLUDE like feature currently. https://github.com/docker/docker/issues/735
Best practices encourage to use "RUN apt-get update && apt-get install -y" for all package installation. But it doesn't mean that you can not use that same technique to separate package installs (e.g. package-foo and package-bar) due to maintainability. It is a tradeoff with minimizing the number of layers. https://docs.docker.com/engine/userguide/eng-image/dockerfile_best-practices/#/minimize-the-number-of-layers (see also how the build cache operates, identifying it as different layers)
Thank you @Sri for some lead pointers.
Docker has the concept of base image. This can be provided in the Dockerfile as "FROM < base-image >". This should be the first line in the Dockerfile. The base image can contain all the commons and individual containers can deal with specific functionalities.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With