Skip to content

Commit

Permalink
Merge pull request #34 from dokku-community/fix-package-building
Browse files Browse the repository at this point in the history
fix: use new triggers for image cache management
  • Loading branch information
josegonzalez authored Sep 6, 2019
2 parents 314e6d2 + 97602e3 commit 2cb9141
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 97 deletions.
63 changes: 63 additions & 0 deletions builder-create-dokku-image
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
export DOCKER_BIN=${DOCKER_BIN:="docker"}
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"

hook-apt-builder-create-dokku-image() {
declare BUILDER_TYPE="$1" APP="$2" SOURCECODE_WORK_DIR="$3" DOKKU_IMAGE="$4"
local IMAGE="dokku/$APP" DIR=/tmp/apt
local COMMAND CONTENT_SHA DOCKER_COMMIT_LABEL_ARGS DOCKER_RUN_LABEL_ARGS

if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
dokku_log_info1 "Rebuilding extended app image due to dpkg-packages usage"
return
fi

CONTENT_SHA="$(fn-apt-fetch-sha "$SOURCECODE_WORK_DIR")"
if [[ -z "$CONTENT_SHA" ]]; then
return
fi

local TMP_WORK_DIR=$(mktemp -d "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
trap "rm -rf '$TMP_WORK_DIR' >/dev/null" RETURN
fn-apt-populate-work-dir "$SOURCECODE_WORK_DIR" "$TMP_WORK_DIR"

if [[ "$("$DOCKER_BIN" images --quiet "dokku/$APP:$CONTENT_SHA" 2>/dev/null)" != "" ]]; then
dokku_log_info1 "Compatible extended app image found, skipping system package installation"
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
return
fi

dokku_log_info1 "Creating extended app image with custom system packages"
pushd "$TMP_WORK_DIR" >/dev/null
CID=$(tar -c . | "$DOCKER_BIN" run "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -i -a stdin "$DOKKU_IMAGE" /bin/bash -c "mkdir -p /tmp/apt && tar -xC /tmp/apt")
popd >/dev/null
if test "$("$DOCKER_BIN" wait "$CID")" -ne 0; then
dokku_log_warn "Failure extracting apt files"
return 1
fi

DOCKER_COMMIT_LABEL_ARGS=("--change" "LABEL org.label-schema.schema-version=1.0" "--change" "LABEL org.label-schema.vendor=dokku" "--change" "LABEL com.dokku.app-name=$APP" "--change" "LABEL $DOKKU_CONTAINER_LABEL=")
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "$IMAGE:apt" >/dev/null
"$DOCKER_BIN" rm "$CID" &>/dev/null || true

COMMAND="$(fn-apt-command "$APP" "$DOKKU_IMAGE" "/tmp/apt")"
DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP"
CID=$("$DOCKER_BIN" run "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -d "$IMAGE:apt" /bin/bash -e -c "$COMMAND")

"$DOCKER_BIN" attach "$CID"
if test "$("$DOCKER_BIN" wait "$CID")" -ne 0; then
dokku_log_warn "Failure installing system packages"
return 1
fi

DOCKER_COMMIT_LABEL_ARGS=("--change" "LABEL org.label-schema.schema-version=1.0" "--change" "LABEL org.label-schema.vendor=dokku" "--change" "LABEL com.dokku.app-name=sha-$APP" "--change" "LABEL $DOKKU_CONTAINER_LABEL=")
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "dokku/$APP:$CONTENT_SHA" >/dev/null
"$DOCKER_BIN" rm "$CID" &>/dev/null || true
"$DOCKER_BIN" rmi "$IMAGE:apt" &>/dev/null || true
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
}

hook-apt-builder-create-dokku-image "$@"
27 changes: 27 additions & 0 deletions builder-dokku-image
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
export DOCKER_BIN=${DOCKER_BIN:="docker"}
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"

hook-apt-builder-dokku-image() {
declare BUILDER_TYPE="$1" APP="$2" SOURCECODE_WORK_DIR="$3"
local IMAGE="dokku/$APP"
local CONTENT_SHA

if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
return
fi

CONTENT_SHA="$(fn-apt-fetch-sha "$SOURCECODE_WORK_DIR")"
if [[ -z "$CONTENT_SHA" ]]; then
return
fi

if [[ "$("$DOCKER_BIN" images --quiet "$IMAGE:$CONTENT_SHA" 2>/dev/null)" != "" ]]; then
echo "$IMAGE:$CONTENT_SHA"
return
fi
}

hook-apt-builder-dokku-image "$@"
111 changes: 111 additions & 0 deletions internal-functions
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#!/usr/bin/env bash
set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
export DOCKER_BIN=${DOCKER_BIN:="docker"}
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"

fn-clean-extended-app-images() {
declare APP="$1" IMAGE="$2"
local images

# remove dangling extended app images
"$DOCKER_BIN" rmi $("$DOCKER_BIN" images --format 'dangling=true' --format "label=com.dokku.app-name=sha-$APP" --quiet) &>/dev/null || true

images="$("$DOCKER_BIN" images --filter "label=com.dokku.app-name=sha-$APP" --quiet)"
for image in $images; do
if [[ "$("$DOCKER_BIN" inspect --format '{{(index .RepoTags 0)}}' "$image" 2>/dev/null)" != "$IMAGE" ]]; then
"$DOCKER_BIN" rmi "$image" &>/dev/null || true
fi
done
}

fn-apt-fetch-sha() {
declare SOURCECODE_WORK_DIR="$1"
local APT_FILES CONTENT INJECT_PACKAGES file

if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
return
fi

APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages')
for file in "${APT_FILES[@]}"; do
if [[ -f "$SOURCECODE_WORK_DIR/$file" ]]; then
INJECT_PACKAGES=true
local file_contents=$(<$SOURCECODE_WORK_DIR/$file)
CONTENT="${CONTENT}\n${file}\n${file_contents}"
fi
done

if [[ "$INJECT_PACKAGES" != "true" ]]; then
return
fi

echo -n "$(<$PLUGIN_AVAILABLE_PATH/apt/plugin.toml)$CONTENT" | sha256sum | cut -d " " -f 1
}

fn-apt-populate-work-dir() {
declare SOURCECODE_WORK_DIR="$1" TMP_WORK_DIR="$2"
local APT_FILES file

APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages')
for file in "${APT_FILES[@]}"; do
if [[ -f "$SOURCECODE_WORK_DIR/$file" ]]; then
cp "$SOURCECODE_WORK_DIR/$file" "$TMP_WORK_DIR/$file"
fi
done
}

fn-apt-command() {
declare APP="$1" DOKKU_IMAGE="$2" DIR="$3"
cat <<EOF
# $APP $DOKKU_IMAGE
sleep 2
export DEBIAN_FRONTEND=noninteractive
if [ -f $DIR/apt-env ]; then
echo "-----> Sourcing apt env"
source $DIR/apt-env
fi
if [ -d $DIR/apt-preferences ]; then
echo "-----> Injecting apt preferences"
mv -v $DIR/apt-preferences /etc/apt/preferences.d/90customizations
fi
if [ -f $DIR/apt-sources-list ]; then
echo "-----> Using customized sources.list"
mv -v $DIR/apt-sources-list /etc/apt/sources.list
fi
if [ -f $DIR/apt-repositories ]; then
echo "-----> Updating package list"
apt-get update >/dev/null
echo "-----> Installing required apt transport packages"
apt-get install -y software-properties-common apt-transport-https
echo "-----> Installing custom apt repositories"
cat "$DIR/apt-repositories" | while read repository; do
if [ -n "\$repository" ]; then
add-apt-repository -y "\$repository"
fi
done
fi
if [ -f $DIR/apt-debconf ]; then
cat "$DIR/apt-debconf" | while read conf; do
if [ -n "\$conf" ]; then
echo \$conf | debconf-set-selections
fi
done
fi
if [ -f $DIR/apt-packages ]; then
PACKAGES=\$(cat "$DIR/apt-packages" | tr "\\n" " ")
echo "-----> Updating package list"
apt-get update >/dev/null
echo "-----> Injecting packages: \$PACKAGES"
apt-get install -y \$PACKAGES
fi
if [ -d $DIR/dpkg-packages ]; then
for pkg in $DIR/dpkg-packages/*.deb; do
echo "-----> Injecting package: \$pkg"
dpkg -i \$pkg
done
fi
rm -rf /tmp/apt
sleep 1 # wait so that docker run has not exited before docker attach
EOF
}
110 changes: 13 additions & 97 deletions pre-build-buildpack
Original file line number Diff line number Diff line change
Expand Up @@ -3,122 +3,38 @@ set -eo pipefail
[[ $DOKKU_TRACE ]] && set -x
export DOCKER_BIN=${DOCKER_BIN:="docker"}
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"

fn-clean-extended-app-images() {
declare APP="$1" IMAGE="$2"
local images

# remove dangling extended app images
"$DOCKER_BIN" rmi $("$DOCKER_BIN" images --format 'dangling=true' --format "label=com.dokku.app-name=sha-$APP" --quiet) &>/dev/null || true

images="$("$DOCKER_BIN" images --filter "label=com.dokku.app-name=sha-$APP" --quiet)"
for image in $images; do
if [[ "$("$DOCKER_BIN" inspect --format '{{(index .RepoTags 0)}}' "$image" 2>/dev/null)" != "$IMAGE" ]]; then
"$DOCKER_BIN" rmi "$image" &>/dev/null || true
fi
done
}
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"

hook-apt-pre-build-buildpack() {
declare APP="$1" SOURCECODE_WORK_DIR="$2"
local IMAGE="dokku/$APP" DIR=/app
local COMMAND CONTENT CONTENT_SHA INJECT_PACKAGES
local CID COMMAND DOCKER_COMMIT_LABEL_ARGS

if [[ -n "$SOURCECODE_WORK_DIR" ]]; then
pushd "$SOURCECODE_WORK_DIR" >/dev/null
fi

local APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages' 'dpkg-packages')
for file in "${APT_FILES[@]}"; do
if [[ -f "$file" ]]; then
INJECT_PACKAGES=true
local file_contents=$(<$file)
CONTENT="${CONTENT}\n${file}\n${file_contents}"
if [[ "$file" == "dpkg-packages" ]]; then
CONTENT="${CONTENT}$(date +%s)"
fi
fi
done
if [[ ! -f "dpkg-packages" ]]; then
return
fi

if [[ -n "$SOURCECODE_WORK_DIR" ]]; then
popd >/dev/null
fi

if [[ "$INJECT_PACKAGES" != "true" ]]; then
return
fi

COMMAND=$(
cat <<EOF
# $APP $IMAGE
sleep 2
export DEBIAN_FRONTEND=noninteractive
if [ -f $DIR/apt-env ]; then
echo "-----> Sourcing apt env"
source $DIR/apt-env
fi
if [ -d $DIR/apt-preferences ]; then
echo "-----> Injecting apt preferences"
mv -v $DIR/apt-preferences /etc/apt/preferences.d/90customizations
fi
if [ -f $DIR/apt-sources-list ]; then
echo "-----> Using customized sources.list"
mv -v $DIR/apt-sources-list /etc/apt/sources.list
fi
if [ -f $DIR/apt-repositories ]; then
echo "-----> Updating package list"
apt-get update >/dev/null
echo "-----> Installing required apt transport packages"
apt-get install -y software-properties-common apt-transport-https
echo "-----> Installing custom apt repositories"
cat "$DIR/apt-repositories" | while read repository; do
if [ -n "\$repository" ]; then
add-apt-repository -y "\$repository"
fi
done
fi
if [ -f $DIR/apt-debconf ]; then
cat "$DIR/apt-debconf" | while read conf; do
if [ -n "\$conf" ]; then
echo \$conf | debconf-set-selections
fi
done
fi
if [ -f $DIR/apt-packages ]; then
PACKAGES=\$(cat "$DIR/apt-packages" | tr "\\n" " ")
echo "-----> Updating package list"
apt-get update >/dev/null
echo "-----> Injecting packages: \$PACKAGES"
apt-get install -y \$PACKAGES
fi
if [ -d $DIR/dpkg-packages ]; then
for pkg in $DIR/dpkg-packages/*.deb; do
echo "-----> Injecting package: \$pkg"
dpkg -i \$pkg
done
fi
sleep 1 # wait so that docker run has not exited before docker attach
EOF
)
dokku_log_info1 "Creating extended app image with custom system packages"
COMMAND="$(fn-apt-command "$APP" "$IMAGE" "$DIR")"
CID=$(docker run -d "$IMAGE" /bin/bash -e -c "$COMMAND")

CONTENT_SHA="$(echo -n "$CONTENT" | sha256sum | cut -d " " -f 1)"
if [[ "$("$DOCKER_BIN" images --quiet "dokku/$APP:$CONTENT_SHA" 2>/dev/null)" != "" ]]; then
dokku_log_info1 "Compatible extended app image found, skipping system package installation"
"$DOCKER_BIN" tag "dokku/$APP:$CONTENT_SHA" "$IMAGE"
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
return
"$DOCKER_BIN" attach "$CID"
if test "$("$DOCKER_BIN" wait "$CID")" -ne 0; then
dokku_log_warn "Failure installing system packages"
return 1
fi

dokku_log_info1 "Extending app image with custom system packages"
CID=$("$DOCKER_BIN" run -d "$IMAGE" /bin/bash -e -c "$COMMAND")
local DOCKER_COMMIT_LABEL_ARGS=("--change" "LABEL org.label-schema.schema-version=1.0" "--change" "LABEL org.label-schema.vendor=dokku" "--change" "LABEL com.dokku.app-name=sha-$APP" "--change" "LABEL $DOKKU_CONTAINER_LABEL=")

"$DOCKER_BIN" attach "$CID"
test "$("$DOCKER_BIN" wait "$CID")" -eq 0
DOCKER_COMMIT_LABEL_ARGS=("--change" "LABEL org.label-schema.schema-version=1.0" "--change" "LABEL org.label-schema.vendor=dokku" "--change" "LABEL com.dokku.app-name=$APP" "--change" "LABEL $DOKKU_CONTAINER_LABEL=")
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "$IMAGE" >/dev/null
"$DOCKER_BIN" rm "$CID" &>/dev/null || true
"$DOCKER_BIN" tag "$IMAGE" "dokku/$APP:$CONTENT_SHA"
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
}

hook-apt-pre-build-buildpack "$@"

0 comments on commit 2cb9141

Please sign in to comment.