Skip to content

Instantly share code, notes, and snippets.

@zudsniper
Last active April 16, 2023 07:34
Show Gist options
  • Save zudsniper/349cefaeb1f990eb20aa3c9f556efc9e to your computer and use it in GitHub Desktop.
Save zudsniper/349cefaeb1f990eb20aa3c9f556efc9e to your computer and use it in GitHub Desktop.
[DEPRECATED] check @zudsniper/bashbits | [ChatGPT-4] A tool to merge docker images simply on the command line via a multilayer Dockerfile.

Docker Image Merger

This repository contains two versions of a script that merges multiple Docker images into a single image by layering them on top of each other. It supports both local and Docker Hub images and provides options to reverse the layer order, disable cache when building, and output a Dockerfile instead of creating the merged image.

V1 Deprecated

Version 1 (v1)

Filename: docker_merge_old.sh

Usage

./docker_merge_old.sh [-r] [-f] -i <image_names> -o <origins> -n <output_name>

Options

  • -r, --reverse: Reverse the order of provided Docker images
  • -f, --file-only: Output a Dockerfile instead of exporting the image
  • -i, --images <image_names>: Comma-separated list of Docker image names
  • -o, --origins <origins>: Comma-separated list of origins (0 for local, 1 for Docker Hub)
  • -n, --name <output_name>: Name of the output merged image

Version 2 (v2)

Filename: docker_merge.sh

Usage

./docker_merge.sh [-r] [-f] [-nc] [-ad|-al] -i <image_names> [-o <origins>] -n <output_name>

Options

  • -r, --reverse: Reverse the order of provided Docker images
  • -f, --file-only: Output a Dockerfile instead of exporting the image
  • -nc, --no-cache: Disable cache when building the image
  • -ad, --all-dockerhub: Treat all images as Docker Hub images
  • -al, --all-local: Treat all images as local images
  • -i, --images <image_names>: Comma-separated list of Docker image names
  • -o, --origins <origins>: Comma-separated list of origins (0 for local, 1 for Docker Hub, optional with -ad or -al)
  • -n, --name <output_name>: Name of the output merged image

Examples

Merging Docker Hub images

./docker_merge.sh -ad -i user/image1,user/image2,user/image3 -n merged_image

Merging mixed images

./docker_merge.sh -i local_image,user/docker_hub_image -o 0,1 -n merged_image

Merging images and outputting a Dockerfile

./docker_merge.sh -f -ad -i user/image1,user/image2,user/image3 -n merged_image

Merging images with reversed order and no cache

./docker_merge.sh -r -nc -al -i local_image1,local_image2,local_image3 -n merged_image
#!/bin/bash
# docker_merge.sh v2 by ChatGPT-4
# used to merge 2 or more docker images into a single new image via a multilayered Dockerfile being constructed then built.
# !! new to v2 -- added new CLI options to avoid inputting origins array if input is simple enough to warrant doing so.
# ----------------------------- #
# Human: @zudsniper
# i'm afraid
set -e
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
echo "Error: Docker is required but not installed. Please install Docker and try again."
exit 1
fi
# Define colors for logs
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# ProgressBar function
function progress_bar {
local width=40
local percent=$1
local filled=$((width * percent / 100))
local empty=$((width - filled))
printf "${GREEN}["
for ((i = 0; i < filled; i++)); do printf "#"; done
for ((i = 0; i < empty; i++)); do printf " "; done
printf "]${NC} %3d%%\r" $percent
}
function usage {
echo -e "Usage: $0 [-r] [-f] [-nc] [-ad|-al] -i <image_names> [-o <origins>] -n <output_name>"
echo -e "\n HINT - The FIRST image provided in both lists will be the OUTERMOST image, unless -r is used.\n"
echo " -r, --reverse Reverse the order of provided docker images"
echo " -f, --file-only Output a Dockerfile instead of exporting the image"
echo " -nc, --no-cache Disable cache when building the image"
echo " -ad, --all-dockerhub Treat all images as Docker Hub images"
echo " -al, --all-local Treat all images as local images"
echo " -i, --images <image_names> Comma-separated list of docker image names"
echo " -o, --origins <origins> Comma-separated list of origins (0 for local, 1 for Docker Hub, optional with -ad or -al)"
echo " -n, --name <output_name> Name of the output merged image"
exit 1
}
if [ $# -eq 0 ]; then
usage
fi
REVERSE=false
FILE_ONLY=false
NO_CACHE=false
ALL_DOCKERHUB=false
ALL_LOCAL=false
ORIGINS=""
while [[ $# -gt 0 ]]; do
case "$1" in
-r|--reverse)
REVERSE=true
shift
;;
-f|--file-only)
FILE_ONLY=true
shift
;;
-nc|--no-cache)
NO_CACHE=true
shift
;;
-ad|--all-dockerhub)
ALL_DOCKERHUB=true
shift
;;
-al|--all-local)
ALL_LOCAL=true
shift
;;
-i|--images)
IMAGES="$2"
shift 2
;;
-o|--origins)
ORIGINS="$2"
shift 2
;;
-n|--name)
OUTPUT_NAME="$2"
shift 2
;;
-h|--help)
usage
;;
*)
usage
;;
esac
done
if [ -z "$IMAGES" ] || [ -z "$OUTPUT_NAME" ]; then
usage
fi
if [ "$ALL_DOCKERHUB" = true ] && [ "$ALL_LOCAL" = true ]; then
echo -e "${RED}Error: You cannot use both --all-dockerhub and --all-local at the same time.${NC}"
exit 1
fi
IFS=',' read -ra IMAGE_ARRAY <<< "$IMAGES"
if [ -z "$ORIGINS" ]; then
if [ "$ALL_DOCKERHUB" = true ]; then
ORIGINS=$(printf '1%.0s' $(seq 1 ${#IMAGE_ARRAY[@]}))
elif [ "$ALL_LOCAL" = true ]; then
ORIGINS=$(printf '0%.0s' $(seq 1 ${#IMAGE_ARRAY[@]}))
else
echo -e "${RED}Error: You must provide either --all-dockerhub, --all-local, or -o flag with origins.${NC}"
exit 1
fi
fi
IFS=',' read -ra ORIGIN_ARRAY <<< "$ORIGINS"
if [ ${#IMAGE_ARRAY[@]} -ne ${#ORIGIN_ARRAY[@]} ]; then
echo -e "${RED}Error: The length of image_names and origins must be equal.${NC}"
exit 1
fi
if [ "$REVERSE" = true ]; then
IMAGE_ARRAY=("${IMAGE_ARRAY[@]}" | tac)
ORIGIN_ARRAY=("${ORIGIN_ARRAY[@]}" | tac)
fi
DOCKERFILE="Dockerfile.$OUTPUT_NAME"
echo "FROM ${IMAGE_ARRAY[0]}" > $DOCKERFILE
for ((i = 1; i < ${#IMAGE_ARRAY[@]}; i++)); do
if [ ${ORIGIN_ARRAY[$i]} -eq 1 ]; then
docker pull "${IMAGE_ARRAY[$i]}"
fi
echo "COPY --from=${IMAGE_ARRAY[$i]} / /" >> $DOCKERFILE
progress=$((100 * i / ${#IMAGE_ARRAY[@]}))
progress_bar $progress
done
progress_bar 100
echo
BUILD_OPTIONS=""
if [ "$NO_CACHE" = true ]; then
BUILD_OPTIONS="--no-cache"
fi
if [ "$FILE_ONLY" = true ]; then
echo -e "${GREEN}Dockerfile generated:${NC} $DOCKERFILE"
else
docker build $BUILD_OPTIONS -t "$OUTPUT_NAME" -f $DOCKERFILE .
echo -e "${GREEN}Merged image created:${NC} $OUTPUT_NAME"
fi
#!/bin/bash
# **** DEPRECATED ****
# docker_merge.sh v1 by ChatGPT-4
# used to merge 2 or more docker images into a single new image via a multilayered Dockerfile being constructed then built.
# ----------------------------- #
# Human: @zudsniper
set -e
# Check if Docker is installed
if ! command -v docker &> /dev/null; then
echo "Error: Docker is required but not installed. Please install Docker and try again."
exit 1
fi
# Define colors for logs
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m'
# ProgressBar function
function progress_bar {
local width=40
local percent=$1
local filled=$((width * percent / 100))
local empty=$((width - filled))
printf "${GREEN}["
for ((i = 0; i < filled; i++)); do printf "#"; done
for ((i = 0; i < empty; i++)); do printf " "; done
printf "]${NC} %3d%%\r" $percent
}
function usage {
echo -e "Usage: $0 [-r] [-f] -i <image_names> -o <origins> -n <output_name>"
echo " -r, --reverse Reverse the order of provided docker images"
echo " -f, --file-only Output a Dockerfile instead of exporting the image"
echo " -i, --images <image_names> Comma-separated list of docker image names"
echo " -o, --origins <origins> Comma-separated list of origins (0 for local, 1 for Docker Hub)"
echo " -n, --name <output_name> Name of the output merged image"
exit 1
}
if [ $# -eq 0 ]; then
usage
fi
REVERSE=false
FILE_ONLY=false
while [[ $# -gt 0 ]]; do
case "$1" in
-r|--reverse)
REVERSE=true
shift
;;
-f|--file-only)
FILE_ONLY=true
shift
;;
-i|--images)
IMAGES="$2"
shift 2
;;
-o|--origins)
ORIGINS="$2"
shift 2
;;
-n|--name)
OUTPUT_NAME="$2"
shift 2
;;
*)
usage
;;
esac
done
if [ -z "$IMAGES" ] || [ -z "$ORIGINS" ] || [ -z "$OUTPUT_NAME" ]; then
usage
fi
IFS=',' read -ra IMAGE_ARRAY <<< "$IMAGES"
IFS=',' read -ra ORIGIN_ARRAY <<< "$ORIGINS"
if [ ${#IMAGE_ARRAY[@]} -ne ${#ORIGIN_ARRAY[@]} ]; then
echo -e "${RED}Error: The length of image_names and origins must be equal.${NC}"
exit 1
fi
if [ "$REVERSE" = true ]; then
IMAGE_ARRAY=("${IMAGE_ARRAY[@]}" | tac)
ORIGIN_ARRAY=("${ORIGIN_ARRAY[@]}" | tac)
fi
DOCKERFILE="Dockerfile.$OUTPUT_NAME"
echo "FROM ${IMAGE_ARRAY[0]}" > $DOCKERFILE
for ((i = 1; i < ${#IMAGE_ARRAY[@]}; i++)); do
if [ ${ORIGIN_ARRAY[$i]} -eq 1 ]; then
docker pull "${IMAGE_ARRAY[$i]}"
fi
echo "COPY --from=${IMAGE_ARRAY[$i]} / /" >> $DOCKERFILE
progress=$((100 * i / ${#IMAGE_ARRAY[@]}))
progress_bar $progress
progress=$((100 * i / ${#IMAGE_ARRAY[@]}))
progress_bar $progress
done
progress_bar 100
echo
if [ "$FILE_ONLY" = true ]; then
echo -e "${GREEN}Dockerfile generated:${NC} $DOCKERFILE"
else
docker build -t "$OUTPUT_NAME" -f $DOCKERFILE .
echo -e "${GREEN}Merged image created:${NC} $OUTPUT_NAME"
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment