Skip to content

Commit 97602e3

Browse files
committed
fix: use new triggers for image cache management
The previous implementation of docker image cache utilization ended up reverting the codebase to the one matching the last extended app image, so the only way to ensure new code was deployed was to update a file recognized by this plugin. In the new implementation, we utilize the new builder plugin triggers to handle image caching, and always rebuild at the pre-build-buildpack phase if there exists a dpkg-packages file.
1 parent 314e6d2 commit 97602e3

4 files changed

+214
-97
lines changed

builder-create-dokku-image

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
#!/usr/bin/env bash
2+
set -eo pipefail
3+
[[ $DOKKU_TRACE ]] && set -x
4+
export DOCKER_BIN=${DOCKER_BIN:="docker"}
5+
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
6+
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"
7+
8+
hook-apt-builder-create-dokku-image() {
9+
declare BUILDER_TYPE="$1" APP="$2" SOURCECODE_WORK_DIR="$3" DOKKU_IMAGE="$4"
10+
local IMAGE="dokku/$APP" DIR=/tmp/apt
11+
local COMMAND CONTENT_SHA DOCKER_COMMIT_LABEL_ARGS DOCKER_RUN_LABEL_ARGS
12+
13+
if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
14+
dokku_log_info1 "Rebuilding extended app image due to dpkg-packages usage"
15+
return
16+
fi
17+
18+
CONTENT_SHA="$(fn-apt-fetch-sha "$SOURCECODE_WORK_DIR")"
19+
if [[ -z "$CONTENT_SHA" ]]; then
20+
return
21+
fi
22+
23+
local TMP_WORK_DIR=$(mktemp -d "/tmp/dokku-${DOKKU_PID}-${FUNCNAME[0]}.XXXXXX")
24+
trap "rm -rf '$TMP_WORK_DIR' >/dev/null" RETURN
25+
fn-apt-populate-work-dir "$SOURCECODE_WORK_DIR" "$TMP_WORK_DIR"
26+
27+
if [[ "$("$DOCKER_BIN" images --quiet "dokku/$APP:$CONTENT_SHA" 2>/dev/null)" != "" ]]; then
28+
dokku_log_info1 "Compatible extended app image found, skipping system package installation"
29+
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
30+
return
31+
fi
32+
33+
dokku_log_info1 "Creating extended app image with custom system packages"
34+
pushd "$TMP_WORK_DIR" >/dev/null
35+
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")
36+
popd >/dev/null
37+
if test "$("$DOCKER_BIN" wait "$CID")" -ne 0; then
38+
dokku_log_warn "Failure extracting apt files"
39+
return 1
40+
fi
41+
42+
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=")
43+
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "$IMAGE:apt" >/dev/null
44+
"$DOCKER_BIN" rm "$CID" &>/dev/null || true
45+
46+
COMMAND="$(fn-apt-command "$APP" "$DOKKU_IMAGE" "/tmp/apt")"
47+
DOCKER_RUN_LABEL_ARGS="--label=com.dokku.app-name=$APP"
48+
CID=$("$DOCKER_BIN" run "${DOCKER_RUN_LABEL_ARGS[@]}" $DOKKU_GLOBAL_RUN_ARGS -d "$IMAGE:apt" /bin/bash -e -c "$COMMAND")
49+
50+
"$DOCKER_BIN" attach "$CID"
51+
if test "$("$DOCKER_BIN" wait "$CID")" -ne 0; then
52+
dokku_log_warn "Failure installing system packages"
53+
return 1
54+
fi
55+
56+
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=")
57+
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "dokku/$APP:$CONTENT_SHA" >/dev/null
58+
"$DOCKER_BIN" rm "$CID" &>/dev/null || true
59+
"$DOCKER_BIN" rmi "$IMAGE:apt" &>/dev/null || true
60+
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
61+
}
62+
63+
hook-apt-builder-create-dokku-image "$@"

builder-dokku-image

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/usr/bin/env bash
2+
set -eo pipefail
3+
[[ $DOKKU_TRACE ]] && set -x
4+
export DOCKER_BIN=${DOCKER_BIN:="docker"}
5+
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"
6+
7+
hook-apt-builder-dokku-image() {
8+
declare BUILDER_TYPE="$1" APP="$2" SOURCECODE_WORK_DIR="$3"
9+
local IMAGE="dokku/$APP"
10+
local CONTENT_SHA
11+
12+
if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
13+
return
14+
fi
15+
16+
CONTENT_SHA="$(fn-apt-fetch-sha "$SOURCECODE_WORK_DIR")"
17+
if [[ -z "$CONTENT_SHA" ]]; then
18+
return
19+
fi
20+
21+
if [[ "$("$DOCKER_BIN" images --quiet "$IMAGE:$CONTENT_SHA" 2>/dev/null)" != "" ]]; then
22+
echo "$IMAGE:$CONTENT_SHA"
23+
return
24+
fi
25+
}
26+
27+
hook-apt-builder-dokku-image "$@"

internal-functions

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
#!/usr/bin/env bash
2+
set -eo pipefail
3+
[[ $DOKKU_TRACE ]] && set -x
4+
export DOCKER_BIN=${DOCKER_BIN:="docker"}
5+
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
6+
7+
fn-clean-extended-app-images() {
8+
declare APP="$1" IMAGE="$2"
9+
local images
10+
11+
# remove dangling extended app images
12+
"$DOCKER_BIN" rmi $("$DOCKER_BIN" images --format 'dangling=true' --format "label=com.dokku.app-name=sha-$APP" --quiet) &>/dev/null || true
13+
14+
images="$("$DOCKER_BIN" images --filter "label=com.dokku.app-name=sha-$APP" --quiet)"
15+
for image in $images; do
16+
if [[ "$("$DOCKER_BIN" inspect --format '{{(index .RepoTags 0)}}' "$image" 2>/dev/null)" != "$IMAGE" ]]; then
17+
"$DOCKER_BIN" rmi "$image" &>/dev/null || true
18+
fi
19+
done
20+
}
21+
22+
fn-apt-fetch-sha() {
23+
declare SOURCECODE_WORK_DIR="$1"
24+
local APT_FILES CONTENT INJECT_PACKAGES file
25+
26+
if [[ -f "$SOURCECODE_WORK_DIR/dpkg-packages" ]]; then
27+
return
28+
fi
29+
30+
APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages')
31+
for file in "${APT_FILES[@]}"; do
32+
if [[ -f "$SOURCECODE_WORK_DIR/$file" ]]; then
33+
INJECT_PACKAGES=true
34+
local file_contents=$(<$SOURCECODE_WORK_DIR/$file)
35+
CONTENT="${CONTENT}\n${file}\n${file_contents}"
36+
fi
37+
done
38+
39+
if [[ "$INJECT_PACKAGES" != "true" ]]; then
40+
return
41+
fi
42+
43+
echo -n "$(<$PLUGIN_AVAILABLE_PATH/apt/plugin.toml)$CONTENT" | sha256sum | cut -d " " -f 1
44+
}
45+
46+
fn-apt-populate-work-dir() {
47+
declare SOURCECODE_WORK_DIR="$1" TMP_WORK_DIR="$2"
48+
local APT_FILES file
49+
50+
APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages')
51+
for file in "${APT_FILES[@]}"; do
52+
if [[ -f "$SOURCECODE_WORK_DIR/$file" ]]; then
53+
cp "$SOURCECODE_WORK_DIR/$file" "$TMP_WORK_DIR/$file"
54+
fi
55+
done
56+
}
57+
58+
fn-apt-command() {
59+
declare APP="$1" DOKKU_IMAGE="$2" DIR="$3"
60+
cat <<EOF
61+
# $APP $DOKKU_IMAGE
62+
sleep 2
63+
export DEBIAN_FRONTEND=noninteractive
64+
if [ -f $DIR/apt-env ]; then
65+
echo "-----> Sourcing apt env"
66+
source $DIR/apt-env
67+
fi
68+
if [ -d $DIR/apt-preferences ]; then
69+
echo "-----> Injecting apt preferences"
70+
mv -v $DIR/apt-preferences /etc/apt/preferences.d/90customizations
71+
fi
72+
if [ -f $DIR/apt-sources-list ]; then
73+
echo "-----> Using customized sources.list"
74+
mv -v $DIR/apt-sources-list /etc/apt/sources.list
75+
fi
76+
if [ -f $DIR/apt-repositories ]; then
77+
echo "-----> Updating package list"
78+
apt-get update >/dev/null
79+
echo "-----> Installing required apt transport packages"
80+
apt-get install -y software-properties-common apt-transport-https
81+
echo "-----> Installing custom apt repositories"
82+
cat "$DIR/apt-repositories" | while read repository; do
83+
if [ -n "\$repository" ]; then
84+
add-apt-repository -y "\$repository"
85+
fi
86+
done
87+
fi
88+
if [ -f $DIR/apt-debconf ]; then
89+
cat "$DIR/apt-debconf" | while read conf; do
90+
if [ -n "\$conf" ]; then
91+
echo \$conf | debconf-set-selections
92+
fi
93+
done
94+
fi
95+
if [ -f $DIR/apt-packages ]; then
96+
PACKAGES=\$(cat "$DIR/apt-packages" | tr "\\n" " ")
97+
echo "-----> Updating package list"
98+
apt-get update >/dev/null
99+
echo "-----> Injecting packages: \$PACKAGES"
100+
apt-get install -y \$PACKAGES
101+
fi
102+
if [ -d $DIR/dpkg-packages ]; then
103+
for pkg in $DIR/dpkg-packages/*.deb; do
104+
echo "-----> Injecting package: \$pkg"
105+
dpkg -i \$pkg
106+
done
107+
fi
108+
rm -rf /tmp/apt
109+
sleep 1 # wait so that docker run has not exited before docker attach
110+
EOF
111+
}

pre-build-buildpack

+13-97
Original file line numberDiff line numberDiff line change
@@ -3,122 +3,38 @@ set -eo pipefail
33
[[ $DOKKU_TRACE ]] && set -x
44
export DOCKER_BIN=${DOCKER_BIN:="docker"}
55
source "$PLUGIN_CORE_AVAILABLE_PATH/common/functions"
6-
7-
fn-clean-extended-app-images() {
8-
declare APP="$1" IMAGE="$2"
9-
local images
10-
11-
# remove dangling extended app images
12-
"$DOCKER_BIN" rmi $("$DOCKER_BIN" images --format 'dangling=true' --format "label=com.dokku.app-name=sha-$APP" --quiet) &>/dev/null || true
13-
14-
images="$("$DOCKER_BIN" images --filter "label=com.dokku.app-name=sha-$APP" --quiet)"
15-
for image in $images; do
16-
if [[ "$("$DOCKER_BIN" inspect --format '{{(index .RepoTags 0)}}' "$image" 2>/dev/null)" != "$IMAGE" ]]; then
17-
"$DOCKER_BIN" rmi "$image" &>/dev/null || true
18-
fi
19-
done
20-
}
6+
source "$PLUGIN_AVAILABLE_PATH/apt/internal-functions"
217

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

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

31-
local APT_FILES=('apt-env' 'apt-preferences' 'apt-sources-list' 'apt-repositories' 'apt-debconf' 'apt-packages' 'dpkg-packages')
32-
for file in "${APT_FILES[@]}"; do
33-
if [[ -f "$file" ]]; then
34-
INJECT_PACKAGES=true
35-
local file_contents=$(<$file)
36-
CONTENT="${CONTENT}\n${file}\n${file_contents}"
37-
if [[ "$file" == "dpkg-packages" ]]; then
38-
CONTENT="${CONTENT}$(date +%s)"
39-
fi
40-
fi
41-
done
17+
if [[ ! -f "dpkg-packages" ]]; then
18+
return
19+
fi
4220

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

47-
if [[ "$INJECT_PACKAGES" != "true" ]]; then
48-
return
49-
fi
50-
51-
COMMAND=$(
52-
cat <<EOF
53-
# $APP $IMAGE
54-
sleep 2
55-
export DEBIAN_FRONTEND=noninteractive
56-
if [ -f $DIR/apt-env ]; then
57-
echo "-----> Sourcing apt env"
58-
source $DIR/apt-env
59-
fi
60-
if [ -d $DIR/apt-preferences ]; then
61-
echo "-----> Injecting apt preferences"
62-
mv -v $DIR/apt-preferences /etc/apt/preferences.d/90customizations
63-
fi
64-
if [ -f $DIR/apt-sources-list ]; then
65-
echo "-----> Using customized sources.list"
66-
mv -v $DIR/apt-sources-list /etc/apt/sources.list
67-
fi
68-
if [ -f $DIR/apt-repositories ]; then
69-
echo "-----> Updating package list"
70-
apt-get update >/dev/null
71-
echo "-----> Installing required apt transport packages"
72-
apt-get install -y software-properties-common apt-transport-https
73-
echo "-----> Installing custom apt repositories"
74-
cat "$DIR/apt-repositories" | while read repository; do
75-
if [ -n "\$repository" ]; then
76-
add-apt-repository -y "\$repository"
77-
fi
78-
done
79-
fi
80-
if [ -f $DIR/apt-debconf ]; then
81-
cat "$DIR/apt-debconf" | while read conf; do
82-
if [ -n "\$conf" ]; then
83-
echo \$conf | debconf-set-selections
84-
fi
85-
done
86-
fi
87-
if [ -f $DIR/apt-packages ]; then
88-
PACKAGES=\$(cat "$DIR/apt-packages" | tr "\\n" " ")
89-
echo "-----> Updating package list"
90-
apt-get update >/dev/null
91-
echo "-----> Injecting packages: \$PACKAGES"
92-
apt-get install -y \$PACKAGES
93-
fi
94-
if [ -d $DIR/dpkg-packages ]; then
95-
for pkg in $DIR/dpkg-packages/*.deb; do
96-
echo "-----> Injecting package: \$pkg"
97-
dpkg -i \$pkg
98-
done
99-
fi
100-
sleep 1 # wait so that docker run has not exited before docker attach
101-
EOF
102-
)
25+
dokku_log_info1 "Creating extended app image with custom system packages"
26+
COMMAND="$(fn-apt-command "$APP" "$IMAGE" "$DIR")"
27+
CID=$(docker run -d "$IMAGE" /bin/bash -e -c "$COMMAND")
10328

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

112-
dokku_log_info1 "Extending app image with custom system packages"
113-
CID=$("$DOCKER_BIN" run -d "$IMAGE" /bin/bash -e -c "$COMMAND")
114-
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=")
115-
116-
"$DOCKER_BIN" attach "$CID"
117-
test "$("$DOCKER_BIN" wait "$CID")" -eq 0
35+
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=")
11836
"$DOCKER_BIN" commit "${DOCKER_COMMIT_LABEL_ARGS[@]}" "$CID" "$IMAGE" >/dev/null
11937
"$DOCKER_BIN" rm "$CID" &>/dev/null || true
120-
"$DOCKER_BIN" tag "$IMAGE" "dokku/$APP:$CONTENT_SHA"
121-
fn-clean-extended-app-images "$APP" "dokku/$APP:$CONTENT_SHA"
12238
}
12339

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

0 commit comments

Comments
 (0)