<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Purnima Upadhyaya</title>
    <description>The latest articles on Forem by Purnima Upadhyaya (@purnima_upadhyaya).</description>
    <link>https://forem.com/purnima_upadhyaya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3594514%2F8186e2e5-20d3-4b82-9584-84a8309ea249.png</url>
      <title>Forem: Purnima Upadhyaya</title>
      <link>https://forem.com/purnima_upadhyaya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/purnima_upadhyaya"/>
    <language>en</language>
    <item>
      <title>How to generate a Dockerfile from the Docker Image</title>
      <dc:creator>Purnima Upadhyaya</dc:creator>
      <pubDate>Mon, 10 Nov 2025 16:44:14 +0000</pubDate>
      <link>https://forem.com/purnima_upadhyaya/how-to-generate-a-dockerfile-from-the-docker-image-3k5d</link>
      <guid>https://forem.com/purnima_upadhyaya/how-to-generate-a-dockerfile-from-the-docker-image-3k5d</guid>
      <description>&lt;p&gt;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. &lt;/p&gt;

&lt;p&gt;In this tutorial we will demonstrate one of the work around with which we can reverse the docker image to generate the Dockerfile.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Creating a Dockerfile :&lt;/strong&gt; This is a sample Hello World Dockerfile with which we have created a Docker Image out of it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Dockerfile&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxxtibnlzdszh7k0x5k0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxxtibnlzdszh7k0x5k0.png" alt=" " width="800" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiv9ogd97lc9xo7n8svj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiv9ogd97lc9xo7n8svj.png" alt=" " width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 :&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     |. Download the Docker image from AWS ECR 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1ybhqu3de64tz1vugqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj1ybhqu3de64tz1vugqp.png" alt=" " width="800" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     ||. Identify the docker image and pull
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpd276bek5sh330kyuqhx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpd276bek5sh330kyuqhx.png" alt=" " width="800" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     |||. Now examine the layers with docker history command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;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 &lt;strong&gt;CMD [tomcat.sh]&lt;/strong&gt; 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"&lt;/p&gt;

&lt;p&gt;`    &lt;strong&gt;docker history --no-trunc --format {{.CreatedBy}} 1f78027aab6d&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CMD ["tomcat.sh"]&lt;br&gt;
USER tomcat&lt;br&gt;
EXPOSE map[8080/tcp:{}]&lt;br&gt;
WORKDIR /usr/local/tomcat&lt;br&gt;
RUN /bin/sh -c chown -R tomcat:tomcat /usr/local/tomcat/* # buildkit&lt;br&gt;
COPY .deployment/myapp/HelloWorld.war /usr/local/tomcat/webapps # buildkit&lt;br&gt;
RUN /bin/sh -c groupadd -g 980  -r tomcat &amp;amp;&amp;amp;  useradd -u 980  -g tomcat -d ${CATALINA_HOME} -s /sbin/nologin  -c "Tomcat user" tomcat &amp;amp;&amp;amp;  chown -R tomcat:tomcat ${CATALINA_HOME} # buildkit&lt;br&gt;
RUN /bin/sh -c chmod +x ${CATALINA_HOME}/bin/&lt;em&gt;sh # buildkit&lt;br&gt;
RUN /bin/sh -c chmod +x $CATALINA_HOME/scripts/&lt;/em&gt;.sh # buildkit&lt;br&gt;
ADD .deployment/myapp/tomcat.sh /usr/local/tomcat/scripts/tomcat.sh # buildkit&lt;br&gt;
COPY .deployment/myapp/tomcat.sh ./ # buildkit&lt;br&gt;
ENV LANG=en_US.UTF-8&lt;br&gt;
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&lt;br&gt;
ENV CATALINA_HOME=/usr/local/tomcat&lt;br&gt;
RUN /bin/sh -c mkdir -p /usr/local/tomcat/scripts # buildkit&lt;br&gt;
CMD ["catalina.sh" "run"]&lt;br&gt;
ENTRYPOINT []&lt;br&gt;
EXPOSE map[8080/tcp:{}]&lt;br&gt;
RUN /bin/sh -c set -eux;  nativeLines="$(catalina.sh configtest 2&amp;gt;&amp;amp;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' &amp;gt;&amp;amp;2; then   echo &amp;gt;&amp;amp;2 "$nativeLines";   exit 1;  fi # buildkit&lt;br&gt;
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    "&lt;a href="https://dlcdn.apache.org/$distFile" rel="noopener noreferrer"&gt;https://dlcdn.apache.org/$distFile&lt;/a&gt;"    "&lt;a href="https://archive.apache.org/dist/$distFile" rel="noopener noreferrer"&gt;https://archive.apache.org/dist/$distFile&lt;/a&gt;"    ${mvnFile:+"&lt;a href="https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile%22" rel="noopener noreferrer"&gt;https://repo1.maven.org/maven2/org/apache/tomcat/tomcat/$mvnFile"&lt;/a&gt;}   ; do    if curl -fL -o "$f" "$distUrl" &amp;amp;&amp;amp; [ -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 &lt;em&gt;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 '&lt;a href="https://www.apache.org/dist/tomcat/tomcat-9/KEYS" rel="noopener noreferrer"&gt;https://www.apache.org/dist/tomcat/tomcat-9/KEYS&lt;/a&gt;';  gpg --batch --import upstream-KEYS;  printf '' &amp;gt; filtered-KEYS;  for key in   'DCFD35E0BF8CA7344752DE8B6FB21E8933C60243'   'A9C5DF4D22E99998D9875A5110C01C5A2F6059E7'   '48F8E69F6390C9F25CFEDCD268248959359E722B'  ; do   gpg --batch --fingerprint "$key";   gpg --batch --export --armor "$key" &amp;gt;&amp;gt; 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/&lt;/em&gt;.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 '.&lt;em&gt;' &amp;gt; /dev/null;  [ -z "$savedAptMark" ] || apt-mark manual $savedAptMark &amp;gt; /dev/null;  find "$TOMCAT_NATIVE_LIBDIR" -type f -executable -exec ldd '{}' ';'   | awk '/=&amp;gt;/ { 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/&lt;/em&gt;;   find ./bin/ -name '&lt;em&gt;.sh' -exec sed -ri 's|^#!/bin/sh$|#!/usr/bin/env bash|' '{}' +;   chmod -R +rX .;  chmod 1777 logs temp work;   catalina.sh version # buildkit&lt;br&gt;
ENV TOMCAT_SHA512=2a955d97c6ed7d01fbf0392f3e2920129bcd541b259e894f441e411bac3bbe65576bcb3a314f06d624c9d70040828d26aa8a2c4f39d225d73f6a3db7523aa3ba&lt;br&gt;
ENV **TOMCAT_VERSION=9.0.111&lt;/em&gt;*&lt;br&gt;
ENV TOMCAT_MAJOR=9&lt;br&gt;
ENV LD_LIBRARY_PATH=/usr/local/tomcat/native-jni-lib&lt;br&gt;
ENV TOMCAT_NATIVE_LIBDIR=/usr/local/tomcat/native-jni-lib&lt;br&gt;
WORKDIR /usr/local/tomcat&lt;br&gt;
RUN /bin/sh -c mkdir -p "$CATALINA_HOME" # buildkit&lt;br&gt;
ENV PATH=/usr/local/tomcat/bin:/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&lt;br&gt;
ENV CATALINA_HOME=/usr/local/tomcat&lt;br&gt;
CMD ["jshell"]&lt;br&gt;
ENTRYPOINT ["/&lt;strong&gt;cacert_entrypoint.sh"]&lt;br&gt;
COPY --chmod=755 entrypoint.sh /&lt;/strong&gt;cacert_entrypoint.sh # buildkit&lt;br&gt;
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&lt;br&gt;
RUN /bin/sh -c set -eux;     ARCH="$(dpkg --print-architecture)";     case "${ARCH}" in        amd64)          ESUM='166774efcf0f722f2ee18eba0039de2d685b350ee14d7b69e6f83437dafd2af1';          BINARY_URL='&lt;a href="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz" rel="noopener noreferrer"&gt;https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_x64_linux_hotspot_17.0.16_8.tar.gz&lt;/a&gt;';          ;;        arm64)          ESUM='423416447885d9e45f96dd9e0b2c1367da5e1b0353e187cfdf9388c9820ac147';          BINARY_URL='&lt;a href="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.16_8.tar.gz" rel="noopener noreferrer"&gt;https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_aarch64_linux_hotspot_17.0.16_8.tar.gz&lt;/a&gt;';          ;;        armhf)          ESUM='bc8ba665df25378cfca76b2d2ca6821ba32c4d45934aa5beea5b542d6658f5d6';          BINARY_URL='&lt;a href="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_arm_linux_hotspot_17.0.16_8.tar.gz" rel="noopener noreferrer"&gt;https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_arm_linux_hotspot_17.0.16_8.tar.gz&lt;/a&gt;';          ;;        ppc64el)          ESUM='eb020f74e00870379522be0b44fc6322c2214e77971c258400c8b5af704d5c0a';          BINARY_URL='&lt;a href="https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.16_8.tar.gz" rel="noopener noreferrer"&gt;https://github.com/adoptium/temurin17-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_ppc64le_linux_hotspot_17.0.16_8.tar.gz&lt;/a&gt;';          ;;        s390x)          ESUM='03dd99d34d2d1b88395765df3acbec2cb81de286f64b1d9e6df3682bee365168';          BINARY_URL='&lt;a href="https://github.com/**adoptium/temurin17**-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.16_8.tar.gz" rel="noopener noreferrer"&gt;https://github.com/**adoptium/temurin17**-binaries/releases/download/jdk-17.0.16%2B8/OpenJDK17U-jdk_s390x_linux_hotspot_17.0.16_8.tar.gz&lt;/a&gt;';          ;;        &lt;em&gt;)          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 '&lt;/em&gt;.so' -exec dirname '{}' ';' | sort -u &amp;gt; /etc/ld.so.conf.d/docker-openjdk.conf;     ldconfig;     java -Xshare:dump; # buildkit&lt;br&gt;
ENV JAVA_VERSION=jdk-17.0.16+8&lt;br&gt;
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" &amp;gt;&amp;gt; /etc/locale.gen;     locale-gen en_US.UTF-8;     rm -rf /var/lib/apt/lists/* # buildkit&lt;br&gt;
ENV LANG=en_US.UTF-8 LANGUAGE=en_US:en LC_ALL=en_US.UTF-8&lt;br&gt;
ENV PATH=/opt/java/openjdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin&lt;br&gt;
ENV JAVA_HOME=/opt/java/openjdk&lt;br&gt;
/bin/sh -c #(nop)  CMD ["/bin/bash"]&lt;br&gt;
/bin/sh -c #(nop) ADD file:32d41b6329e8f89fa4ac92ef97c04b7cfd5e90fb74e1509c3e27d7c91195b7c7 in / &lt;br&gt;
/bin/sh -c #(nop)  LABEL org.opencontainers.image.version=22.04&lt;br&gt;
/bin/sh -c #(nop)  LABEL org.opencontainers.image.ref.name=ubuntu&lt;br&gt;
/bin/sh -c #(nop)  ARG LAUNCHPAD_BUILD_ARCH&lt;br&gt;
/bin/sh -c #(nop)  ARG RELEASE&lt;/p&gt;

&lt;p&gt;`&lt;/p&gt;

&lt;p&gt;4.Generated Dockerfile from the above docker image by removing the &lt;strong&gt;# buildkit&lt;/strong&gt; which is close enough with the original Dockerfile.&lt;br&gt;
Some steps can be tweaked or adjusted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generated Dockerfile from the above docker history layers&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltx9zepmu8arhkbpisz9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltx9zepmu8arhkbpisz9.png" alt=" " width="800" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;5.&lt;strong&gt;Conclusion&lt;/strong&gt; : From the above generated Dockerfile we can now build the Docker Image again by running the below command.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker build . -t new-image&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>aws</category>
      <category>software</category>
    </item>
  </channel>
</rss>
