Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactoring 2021-05 #19

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 123 additions & 113 deletions bin/strip-docker-image
Original file line number Diff line number Diff line change
@@ -1,154 +1,164 @@
#!/bin/bash
#!/usr/bin/env bash

# NAME
# strip-docker-image - strips the bare essentials from an image and exports them
# strip-docker-image - strips the bare essentials from an image and exports them
#
# SYNOPSIS
# strip-docker-image -i image-name -t target-image-name -t [-p package | -f file] [-d Dockerfile] [-x expose-port] [-v]
# strip-docker-image -i image-name -t target-image-name -t [-p package | -f file] [-d Dockerfile] [-x expose-port] [-v] [-k]
#
#
# OPTIONS
# -i image-name to strip
# -t target-image-name the image name of the stripped image
# -p package package to include from image, multiple -p allowed.
# -f file file to include from image, multiple -f allowed.
# -x port to expose.
# -d Dockerfile to incorporate in the stripped image.
# -v verbose
# -i image-name - name of the image to strip
# -t target-image-name - name of the image after stripping
# -p package - package to include from image, multiple parameters allowed
# -f file - file to include from image, multiple parameters allowed
# -x port - port to expose
# -d Dockerfile - Dockerfile to incorporate in the stripped image
# -v - verbose output
# -k - keep stripped container files incl. Dockerfile (for manual editing)
#
# DESCRIPTION
# creates a new Docker image based on the scratch which contains
# only the the source image of selected packages and files.
# "strip-docker-image" creates a new Docker image based on the scratch which contains
# only the the source image of selected packages and files.
#
# EXAMPLE
# The following example strips the nginx installation from the default NGiNX docker image,
# The following example strips the nginx installation from the default NGiNX docker image,
#
# strip-docker-image -i nginx -t stripped-nginx \
# -v \
# -p nginx \
# -f /bin/cat \
# -f /bin/ls \
# -f /bin/mkdir \
# -f /bin/ps \
# -f /bin/sh \
# -f /etc/group \
# -f /etc/nsswitch.conf \
# -f /etc/passwd \
# -f /var/cache/nginx \
# -f /var/log/nginx \
# -f /var/run \
# -f '/lib/*/libnss*'
#
# strip-docker-image -i nginx -t stripped-nginx \
# -p nginx \
# -f /etc/passwd \
# -f /etc/group \
# -f '/lib/*/libnss*' \
# -f /bin/ls \
# -f /bin/cat \
# -f /bin/sh \
# -f /bin/mkdir \
# -f /bin/ps \
# -f /var/run \
# -f /var/log/nginx
# CAVEATS
# requires an image that has awk, bash, grep, ldd, readlink, sort & tar installed.
#
# AUTHOR
# Mark van Holsteijn
# Mark van Holsteijn
#
# COPYRIGHT
#
# Copyright 2015 Xebia Nederland B.V.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# Copyright 2015 Xebia Nederland B.V.
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

function usage() {
echo "usage: $(basename $0) -i image-name -t stripped-image-name [-d Dockerfile] [-p package | -f file] [-v]" >&2
echo " $@" >&2
echo "usage: ${BASH_SOURCE[0]} -i image-name -t stripped-image-name [-d Dockerfile] [-p package | -f file] [-v] [-k]" >&2
echo " $@" >&2
}

function parse_commandline() {

while getopts "vi:t:p:f:x:d:" OPT; do
case "$OPT" in
v)
VERBOSE=-v
;;
p)
PACKAGES="$PACKAGES -p $OPTARG"
;;
f)
FILES="$FILES -f $OPTARG"
;;
i)
IMAGE_NAME="$OPTARG"
;;
t)
TARGET_IMAGE_NAME="$OPTARG"
;;
x)
EXPOSE_PORTS="$EXPOSE_PORTS $OPTARG"
;;
d)
DOCKERFILES="$DOCKERFILES \"$OPTARG\""
;;
*)
usage
exit 1
;;
esac
done
shift $((OPTIND-1))

if [ -z "$IMAGE_NAME" ] ; then
usage "image name is missing."
exit 1
fi

if [ -z "$TARGET_IMAGE_NAME" ] ; then
usage "target image name -t missing."
exit 1
fi

if [ -z "$PACKAGES" -a -z "$FILES" ] ; then
usage "Missing -p or -f options"
exit 1
fi
export PACKAGES FILES VERBOSE
while getopts "vki:t:p:f:x:d:" OPT; do
case "$OPT" in
v)
VERBOSE=-v
;;
k)
KEEP=1
;;
p)
PACKAGES+=(-p "$OPTARG")
;;
f)
FILES+=(-f "$OPTARG")
;;
i)
IMAGE_NAME="$OPTARG"
;;
t)
TARGET_IMAGE_NAME="$OPTARG"
;;
x)
EXPOSE_PORTS+=("$OPTARG")
;;
d)
DOCKERFILES+=("$OPTARG")
;;
*)
usage
exit 1
;;
esac
done
shift $((OPTIND-1))

if [ -z "$IMAGE_NAME" ]; then
usage "Image name -i is missing."
exit 1
fi

if [ -z "$TARGET_IMAGE_NAME" ]; then
usage "Target image name -t missing."
exit 1
fi

if ! (( "${#PACKAGES[@]}" + "${#FILES[@]}" )); then
usage "Missing options -p or -f"
exit 1
fi
}

parse_commandline "$@"

DIR=strip-docker-image-$$
mkdir -p $DIR/export
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
mkdir -p "$DIR"/export
SCRIPT_DIR="$PWD"

docker run -v $PWD/$DIR/export:/export \
-v $SCRIPT_DIR:/mybin \
--entrypoint="/bin/bash" \
$IMAGE_NAME \
/mybin/strip-docker-image-export -d /export $VERBOSE $PACKAGES $FILES
docker run --rm -v "$PWD"/"$DIR"/export:/export \
-v "$SCRIPT_DIR":/mybin \
--entrypoint="/bin/bash" \
"$IMAGE_NAME" \
/mybin/strip-docker-image-export -d /export \
"$VERBOSE" "${PACKAGES[@]}" "${FILES[@]}"

cat > $DIR/Dockerfile <<!
cat << EOF > "$DIR"/Dockerfile
FROM scratch
ADD export /
!
EOF

for DOCKERFILE in $DOCKERFILES ; do
sed ':x; /\\$/ { N; s/\\\n//; tx }' "$(eval echo $DOCKERFILE)" \
| grep -v '^\(FROM\|RUN\|ADD\|COPY\)' \
>> $DIR/Dockerfile
for DOCKERFILE in "${DOCKERFILES[@]}"; do
sed ':x; /\\$/ { N; s/\\\n//; tx }' "$DOCKERFILE" \
| grep -v '^\(FROM\|RUN\|ADD\|COPY\)' \
>> "$DIR"/Dockerfile
done

for PORT in $EXPOSE_PORTS ; do
echo EXPOSE $PORT >> $DIR/Dockerfile
for PORT in "${EXPOSE_PORTS[@]}"; do
echo "EXPOSE ${PORT#" "}" >> "$DIR"/Dockerfile
done

EXPOSE=$(docker inspect -f '{{range $key, $value := .Config.ExposedPorts}}{{$key}} {{end}}' $IMAGE_NAME | sed -e 's/\/[a-z]* / /g')
ENTRYPOINT=$(docker inspect --format='{{if .Config.Entrypoint}}ENTRYPOINT {{json .Config.Entrypoint}}{{end}}' $IMAGE_NAME)
CMD=$(docker inspect --format='{{if .Config.Cmd}}CMD {{json .Config.Cmd}}{{end}}' $IMAGE_NAME)
EXPOSE=$(docker inspect --format='{{range $key, $value := .Config.ExposedPorts}}{{$key}} {{end}}' "$IMAGE_NAME" | sed -e 's/\/[a-z]* / /g')
ENTRYPOINT=$(docker inspect --format='{{if .Config.Entrypoint}}ENTRYPOINT {{json .Config.Entrypoint}}{{end}}' "$IMAGE_NAME")
CMD=$(docker inspect --format='{{if .Config.Cmd}}CMD {{json .Config.Cmd}}{{end}}' "$IMAGE_NAME")

[ -z "$EXPOSE" ] || echo "EXPOSE $EXPOSE" >> $DIR/Dockerfile
[ -z "$ENTRYPOINT" ] || echo $ENTRYPOINT >> $DIR/Dockerfile
[ -z "$CMD" ] || echo $CMD >> $DIR/Dockerfile
[ -z "$EXPOSE" ] || echo "EXPOSE $EXPOSE" >> "$DIR"/Dockerfile
[ -z "$ENTRYPOINT" ] || echo "$ENTRYPOINT" >> "$DIR"/Dockerfile
[ -z "$CMD" ] || echo "$CMD" >> "$DIR"/Dockerfile

(
cd $DIR
docker build --no-cache -t $TARGET_IMAGE_NAME .
)
pushd "$DIR" &>/dev/null && {
docker build --no-cache -t "$TARGET_IMAGE_NAME" .
popd &>/dev/null
}

rm -rf $DIR
if [ -z "$KEEP" ]; then
rm -rf "$DIR"
fi
Loading