DEV Community

Purnima Upadhyaya
Purnima Upadhyaya

Posted on

How to generate a Dockerfile from the Docker Image

We always build Docker images from Dockerfile,but in some scenarios when the same Dockerfile got deleted accidentally or when we have the docker image and we are curious to know that how would the Dockerfile for that docker image would look like, then there are some workarounds with which we can get to this goal very close.

In this tutorial we will demonstrate one of the work around with which we can reverse the docker image to generate the Dockerfile.

  1. Creating a Dockerfile : This is a sample Hello World Dockerfile with which we have created a Docker Image out of it.

Dockerfile

2.The above Dockerfile is built and pushed as a docker image in the AWS ECR (Elastic Container Repository) , as below image

3.Now, let us assume that the original Dockerfile is deleted and if we need to recover the steps for the Dockerfile based on the image we have then we can do by following below steps :

     |. Download the Docker image from AWS ECR 
Enter fullscreen mode Exit fullscreen mode

     ||. Identify the docker image and pull
Enter fullscreen mode Exit fullscreen mode

     |||. Now examine the layers with docker history command
Enter fullscreen mode Exit fullscreen mode

When we run the docker history command it will shows us how the docker image is built by layers. Here we notice that the last command that ran in Dockerfile CMD [tomcat.sh] is shown first. Therefore, we need to build the steps from the bottom, before the docker running its custom steps. For our example , it will be from the tomcat image at the bottom and then get the Tomcat and Java version which is "9.0.111" and "temurin-jdk-17"

` docker history --no-trunc --format {{.CreatedBy}} 1f78027aab6d

CMD ["tomcat.sh"]
USER tomcat
EXPOSE map[8080/tcp:{}]
WORKDIR /usr/local/tomcat
RUN /bin/sh -c chown -R tomcat:tomcat /usr/local/tomcat/* # buildkit
COPY .deployment/myapp/HelloWorld.war /usr/local/tomcat/webapps # buildkit
RUN /bin/sh -c groupadd -g 980 -r tomcat && useradd -u 980 -g tomcat -d ${CATALINA_HOME} -s /sbin/nologin -c "Tomcat user" tomcat && chown -R tomcat:tomcat ${CATALINA_HOME} # buildkit
RUN /bin/sh -c chmod +x ${CATALINA_HOME}/bin/sh # buildkit
RUN /bin/sh -c chmod +x $CATALINA_HOME/scripts/
.sh # buildkit
ADD .deployment/myapp/tomcat.sh /usr/local/tomcat/scripts/tomcat.sh # buildkit
COPY .deployment/myapp/tomcat.sh ./ # buildkit
ENV LANG=en_US.UTF-8
ENV PATH=/usr/local/tomcat/bin:/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/java/openjdk/bin:/usr/local/tomcat/scripts
ENV CATALINA_HOME=/usr/local/tomcat
RUN /bin/sh -c mkdir -p /usr/local/tomcat/scripts # buildkit
CMD ["catalina.sh" "run"]
ENTRYPOINT []
EXPOSE map[8080/tcp:{}]
RUN /bin/sh -c set -eux; nativeLines="$(catalina.sh configtest 2>&1)"; nativeLines="$(echo "$nativeLines" | grep 'Apache Tomcat Native')"; nativeLines="$(echo "$nativeLines" | sort -u)"; if ! echo "$nativeLines" | grep -E 'INFO: Loaded( APR based)? Apache Tomcat Native library' >&2; then echo >&2 "$nativeLines"; exit 1; fi # buildkit
RUN /bin/sh -c set -eux; savedAptMark="$(apt-mark showmanual)"; apt-get update; apt-get install -y --no-install-recommends ca-certificates curl gnupg ; ddist() { local f="$1"; shift; local distFile="$1"; shift; local mvnFile="${1:-}"; local success=; local distUrl=; for distUrl in "https://dlcdn.apache.org/$distFile" "https://archive.apache.org/dist/$distFile" ${mvnFile:+"https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"} ; do if curl -fL -o "$f" "$distUrl" && [ -s "$f" ]; then success=1; break; fi; done; [ -n "$success" ]; }; ddist 'tomcat.tar.gz' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz"; echo "$TOMCAT_SHA512 tomcat.tar.gz" | sha512sum --strict --check -; ddist 'tomcat.tar.gz.asc' "tomcat/tomcat-$TOMCAT_MAJOR/v$TOMCAT_VERSION/bin/apache-tomcat-$TOMCAT_VERSION.tar.gz.asc" "$TOMCAT_VERSION/tomcat-$TOMCAT_VERSION.tar.gz.asc"; GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; curl -fL -o upstream-KEYS 'https://www.apache.org/dist/tomcat/tomcat-9/KEYS'; gpg --batch --import upstream-KEYS; printf '' > filtered-KEYS; for key in 'DCFD35E0BF8CA7344752DE8B6FB21E8933C60243' 'A9C5DF4D22E99998D9875A5110C01C5A2F6059E7' '48F8E69F6390C9F25CFEDCD268248959359E722B' ; do gpg --batch --fingerprint "$key"; gpg --batch --export --armor "$key" >> filtered-KEYS; done; gpgconf --kill all; rm -rf "$GNUPGHOME"; GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; gpg --batch --import filtered-KEYS; gpg --batch --verify tomcat.tar.gz.asc tomcat.tar.gz; tar -xf tomcat.tar.gz --strip-components=1; rm bin/.bat; rm tomcat.tar.gz*; gpgconf --kill all; rm -rf "$GNUPGHOME"; mv webapps webapps.dist; mkdir webapps; nativeBuildDir="$(mktemp -d)"; tar -xf bin/tomcat-native.tar.gz -C "$nativeBuildDir" --strip-components=1; apt-get install -y --no-install-recommends dpkg-dev gcc libapr1-dev libssl-dev make ; ( export CATALINA_HOME="$PWD"; cd "$nativeBuildDir/native"; gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)"; aprConfig="$(command -v apr-1-config)"; ./configure --build="$gnuArch" --libdir="$TOMCAT_NATIVE_LIBDIR" --prefix="$CATALINA_HOME" --with-apr="$aprConfig" --with-java-home="$JAVA_HOME" --with-ssl ; nproc="$(nproc)"; make -j "$nproc"; make install; ); rm -rf "$nativeBuildDir"; rm bin/tomcat-native.tar.gz; apt-mark auto '.' > /dev/null; [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark > /dev/null; find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';' | awk '/=>/ { print $(NF-1) }' | xargs -rt readlink -e | sort -u | xargs -rt dpkg-query --search | cut -d: -f1 | sort -u | tee "$TOMCAT_NATIVE_LIBDIR/.dependencies.txt" | xargs -r apt-mark manual ; apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; rm -rf /var/lib/apt/lists/; find ./bin/ -name '.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +; chmod -R +rX .; chmod 1777 logs temp work; catalina.sh version # buildkit
ENV TOMCAT_SHA512=2a955d97c6ed7d01fbf0392f3e2920129bcd541b259e894f441e411bac3bbe65576bcb3a314f06d624c9d70040828d26aa8a2c4f39d225d73f6a3db7523aa3ba
ENV **TOMCAT_VERSION=9.0.111
*
ENV TOMCAT_MAJOR=9
ENV LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib
ENV TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib
WORKDIR /usr/local/tomcat
RUN /bin/sh -c mkdir -p "$CATALINA_HOME" # buildkit
ENV PATH=/usr/local/tomcat/bin:/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV CATALINA_HOME=/usr/local/tomcat
CMD ["jshell"]
ENTRYPOINT ["/cacert_entrypoint.sh"]
COPY --chmod=755 entrypoint.sh /
cacert_entrypoint.sh # buildkit
RUN /bin/sh -c set -eux; echo "Verifying install ..."; fileEncoding="$(echo 'System.out.println(System.getProperty("file.encoding"))' | jshell -s -)"; [ "$fileEncoding" = 'UTF-8' ]; rm -rf ~/.java; echo "javac --version"; javac --version; echo "java --version"; java --version; echo "Complete." # buildkit
RUN /bin/sh -c set -eux; ARCH="$(dpkg --print-architecture)"; case "${ARCH}" in amd64) ESUM='166774efcf0f722f2ee18eba0039de2d685b350ee14d7b69e6f83437dafd2af1'; BINARY_URL='https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz'; ;; arm64) ESUM='423416447885d9e45f96dd9e0b2c1367da5e1b0353e187cfdf9388c9820ac147'; BINARY_URL='https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.16_8.tar.gz'; ;; armhf) ESUM='bc8ba665df25378cfca76b2d2ca6821ba32c4d45934aa5beea5b542d6658f5d6'; BINARY_URL='https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_arm_linux_hotspot_17.0.16_8.tar.gz'; ;; ppc64el) ESUM='eb020f74e00870379522be0b44fc6322c2214e77971c258400c8b5af704d5c0a'; BINARY_URL='https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.16_8.tar.gz'; ;; s390x) ESUM='03dd99d34d2d1b88395765df3acbec2cb81de286f64b1d9e6df3682bee365168'; BINARY_URL='https://github.com/**adoptium/temurin17**-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.16_8.tar.gz'; ;; ) echo "Unsupported arch: ${ARCH}"; exit 1; ;; esac; wget --progress=dot:giga -O /tmp/openjdk.tar.gz ${BINARY_URL}; wget --progress=dot:giga -O /tmp/openjdk.tar.gz.sig ${BINARY_URL}.sig; export GNUPGHOME="$(mktemp -d)"; gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 3B04D753C9050D9A5D343F39843C48A565F8F04B; gpg --batch --verify /tmp/openjdk.tar.gz.sig /tmp/openjdk.tar.gz; rm -rf "${GNUPGHOME}" /tmp/openjdk.tar.gz.sig; echo "${ESUM} */tmp/openjdk.tar.gz" | sha256sum -c -; mkdir -p "$JAVA_HOME"; tar --extract --file /tmp/openjdk.tar.gz --directory "$JAVA_HOME" --strip-components 1 --no-same-owner ; rm -f /tmp/openjdk.tar.gz ${JAVA_HOME}/lib/src.zip; find "$JAVA_HOME/lib" -name '.so' -exec dirname '{}' ';' | sort -u > /etc/ld.so.conf.d/docker-openjdk.conf; ldconfig; java -Xshare:dump; # buildkit
ENV JAVA_VERSION=jdk-17.0.16+8
RUN /bin/sh -c set -eux; apt-get update; DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends curl wget gnupg fontconfig ca-certificates p11-kit binutils tzdata locales ; echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; locale-gen en_US.UTF-8; rm -rf /var/lib/apt/lists/* # buildkit
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8
ENV PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV JAVA_HOME=/opt/java/openjdk
/bin/sh -c #(nop) CMD ["/bin/bash"]
/bin/sh -c #(nop) ADD file:32d41b6329e8f89fa4ac92ef97c04b7cfd5e90fb74e1509c3e27d7c91195b7c7 in /
/bin/sh -c #(nop) LABEL org.opencontainers.image.version=22.04
/bin/sh -c #(nop) LABEL org.opencontainers.image.ref.name=ubuntu
/bin/sh -c #(nop) ARG LAUNCHPAD_BUILD_ARCH
/bin/sh -c #(nop) ARG RELEASE

`

4.Generated Dockerfile from the above docker image by removing the # buildkit which is close enough with the original Dockerfile.
Some steps can be tweaked or adjusted.

Generated Dockerfile from the above docker history layers

5.Conclusion : From the above generated Dockerfile we can now build the Docker Image again by running the below command.

docker build . -t new-image

Top comments (0)