Skip to content

Commit

Permalink
Merge branch 'docker' into ci
Browse files Browse the repository at this point in the history
  • Loading branch information
rpatterson committed Jun 12, 2024
2 parents 3bff1af + 67195eb commit 154d171
Show file tree
Hide file tree
Showing 40 changed files with 1,550 additions and 1,682 deletions.
1 change: 1 addition & 0 deletions .alexrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"host-hostess",
"hostesses-hosts",
"kill",
"color",
"dummy"
]
}
6 changes: 3 additions & 3 deletions .env.in
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ CI_REGISTRY_PASSWORD=${CI_REGISTRY_PASSWORD}
PROJECT_GITHUB_PAT=${PROJECT_GITHUB_PAT}

# Constants specific to this project or checkout used in variable substitutions in
# `./docker-compose*.yml`. Don't change these during the ordinary course of development:
# `./compose*.yml`. Don't change these during the ordinary course of development:
# Capture the path of the checkout directory as seen by the real host running `#
# dockerd` so that following bind volumes have the correct source paths:
CHECKOUT_DIR=${CHECKOUT_DIR}
Expand All @@ -30,6 +30,6 @@ DOCKER_GID=${DOCKER_GID}
DOCKER_DOCKER_PUSHRM_DIGEST=@sha256:812a950e5be7dca26cef33b61eb2076bfcfb6c2a8ec96c126371fc049c3b6608
DOCKER_GITLAB_RELEASE_CLI_DIGEST=@sha256:696013aea0f2a20482800ce3a77341f840d7c7ec17bd78bd555e0bd6c00e4f11
DOCKER_HADOLINT_DIGEST=@sha256:9cef74a390694cdc01dd119cbba9adac5bb6671ce67d8d79eb7ec68f497a3684
DOCKER_PANDOC_DIGEST=@sha256:336f9e79cb3132fa6ff4a497f0953a7e5b71592c16472b7c960eb774dcea9a14
DOCKER_PANDOC_DIGEST=@sha256:108fa6ae7c872fad83064c8b3841dab27b2634496acca14ef95c57694da6de52
DOCKER_REUSE_DIGEST=@sha256:a0dca4eb014908af80608c06de3470b770a9c97f91041777d0c1cfbfeb8709f7
DOCKER_VALE_DIGEST=@sha256:da6a0901858421b282aa8d935e72831c84cebf716ae4e276658e9e5d382fad20
DOCKER_VALE_DIGEST=@sha256:5e15a69cf0590ad03b275cb406156092977af7a11a7bde3b78375c14d907907f
4 changes: 4 additions & 0 deletions .vale.ini
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ RedHat.PassiveVoice = suggestion
# and there are a significant number of cases where there's no good replacement:
write-good.Weasel = warning

# False failures on `HH:MM:SS [AP]M`:
proselint.DateMidnight = warning


# Enforce all other rules not enforced by default:

Expand Down Expand Up @@ -182,3 +185,4 @@ RedHat.ProductCentricWriting = error
Microsoft.URLFormat = error
RedHat.EmDash = error
RedHat.SmartQuotes = error
alex.OCD = error
58 changes: 33 additions & 25 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ FROM buildpack-deps:stable AS base
# Defensive shell options:
SHELL ["/bin/bash", "-eu", "-o", "pipefail", "-c"]

# Avoid long re-build times, longest running layers first:

# Install operating system packages needed for the image `ENDPOINT`:
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean && \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \
>"/etc/apt/apt.conf.d/keep-cache"
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install --no-install-recommends -y "gosu=1.14-1+b6"

# Project constants:
ARG PROJECT_NAMESPACE=rpatterson
ARG PROJECT_NAME=project-structure
Expand All @@ -24,7 +36,7 @@ LABEL org.opencontainers.image.description="Project structure foundation or temp
LABEL org.opencontainers.image.licenses="MIT"
LABEL org.opencontainers.image.authors="Ross Patterson <me@rpatterson.net>"
LABEL org.opencontainers.image.vendor="rpatterson.net"
LABEL org.opencontainers.image.base.name="docker.io/library/buildpack-deps"
LABEL org.opencontainers.image.base.name="docker.io/library/buildpack-deps:stable"

ENV PROJECT_NAMESPACE="${PROJECT_NAMESPACE}"
ENV PROJECT_NAME="${PROJECT_NAME}"
Expand All @@ -34,30 +46,6 @@ WORKDIR "${HOME}"
ENTRYPOINT [ "entrypoint.sh" ]
CMD [ "bash" ]

# Support for a volume to preserve data between runs and share data between variants:
# TEMPLATE: Add other user `${HOME}/` files to preserved.
RUN mkdir -pv "${HOME}/.local/share/${PROJECT_NAME}/" && \
touch "${HOME}/.local/share/${PROJECT_NAME}/bash_history" && \
ln -snv --relative "${HOME}/.local/share/${PROJECT_NAME}/bash_history" \
"${HOME}/.bash_history"

# Put the `ENTRYPOINT` on the `$PATH`
COPY [ "./bin/entrypoint.sh", "/usr/local/bin/" ]

# Install operating system packages needed for the image `ENDPOINT`:
RUN \
rm -f /etc/apt/apt.conf.d/docker-clean && \
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \
>"/etc/apt/apt.conf.d/keep-cache"
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && \
apt-get install --no-install-recommends -y "gosu=1.14-1+b6"

# Build-time labels:
ARG VERSION=
LABEL org.opencontainers.image.version=${VERSION}


## Container image for use by end users.

Expand All @@ -67,6 +55,16 @@ FROM base AS user
# TEMPLATE: Add image setup specific to the user image, often installable packages built
# from the project.

# Position cheap or quick layers that change often as the last layers and repeat between
# image targets to avoid re-running expensive or long-running layers:

# Put the `ENTRYPOINT` on the `$PATH`
COPY [ "./bin/entrypoint.sh", "/usr/local/bin/" ]

# Build-time labels:
ARG VERSION=
LABEL org.opencontainers.image.version=${VERSION}


## Container image for use by developers.

Expand All @@ -84,3 +82,13 @@ WORKDIR "/usr/local/src/${PROJECT_NAME}/"

# TEMPLATE: Add image setup specific to the development for this project type, often at
# least installing development tools.

# Position cheap or quick layers that change often as the last layers and repeat between
# image targets to avoid re-running expensive or long-running layers:

# Put the `ENTRYPOINT` on the `$PATH`
COPY [ "./bin/entrypoint.sh", "/usr/local/bin/" ]

# Build-time labels:
ARG VERSION=
LABEL org.opencontainers.image.version=${VERSION}
121 changes: 82 additions & 39 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export DOCKER_NAMESPACE=merpatterson
export DOCKER_USER?=$(DOCKER_NAMESPACE)
# Match the same Python version available in the `./build-host/` Docker image:
# https://pkgs.alpinelinux.org/packages?name=python3&branch=edge&repo=main&arch=x86_64&maintainer=
PYTHON_SUPPORTED_MINOR=3.11
PYTHON_SUPPORTED_MINOR=3.12
# TEMPLATE: See comments towards the bottom and update.
GPG_SIGNING_KEYID=2EFF7CCE6828E359

Expand Down Expand Up @@ -282,6 +282,7 @@ DOCKER_IMAGES+=$(DOCKER_IMAGE_DOCKER)
endif
export DOCKER_PASS?=
DOCKER_COMPOSE_RUN_CMD=docker compose run --rm -T --quiet-pull
DOCKER_COMPOSE_UPGRADE=false
TEST_CODE_PREREQS=./var/log/build-pkgs.log

# Values derived from or overridden by CI environments:
Expand Down Expand Up @@ -367,13 +368,17 @@ export CI_JOB_TOKEN
CI_REGISTRY_PASSWORD?=
export CI_REGISTRY_PASSWORD

# Variables related to tools managed by `./*compose*.yml`:
DOCKER_COMPOSE_UPGRADE=false

# https://www.sphinx-doc.org/en/master/usage/builders/index.html
# Run these Sphinx builders to test the correctness of the documentation:
# <!--alex disable gals-man-->
DOCS_SPHINX_BUILDERS=html dirhtml singlehtml htmlhelp qthelp epub applehelp latex man \
texinfo text gettext linkcheck xml pseudoxml
DOCS_SPHINX_ALL_FORMATS=$(DOCS_SPHINX_BUILDERS) devhelp pdf info
# <!--alex enable gals-man-->
DOCS_SPHINX_BUILD_OPTS=
# These builders report false warnings or failures:

# Override variable values if present in `./.env` and if not overridden on the
Expand Down Expand Up @@ -447,7 +452,7 @@ $(DOCS_SPHINX_BUILDERS:%=build-docs-%): ./.tox/build/.tox-info.json \
build-docs-pdf: build-docs-latex
# TODO: Switch to a TeX Live container for SVG support.
$(MAKE) -C "./build/docs/$(<:build-docs-%=%)/" \
LATEXMKOPTS="-f -interaction=nonstopmode" all-pdf || true
LATEXMKOPTS="-f -interaction=nonstopmode" all-pdf
.PHONY: build-docs-info
## Render the Texinfo documentation into a `*.info` file.
build-docs-info: build-docs-texinfo
Expand Down Expand Up @@ -1044,10 +1049,10 @@ devel-format: ./var/log/docker-compose-network.log ./var/log/npm-install.log
.PHONY: devel-upgrade
## Update requirements, dependencies, and other external versions tracked in VCS.
devel-upgrade:
touch ./requirements/*.txt.in "./.vale.ini" ./styles/*.ini
$(MAKE) PIP_COMPILE_ARGS="--upgrade" \
touch ./requirements/*.txt.in "./.env.in.~prereq~" "./.vale.ini" ./styles/*.ini
$(MAKE) PIP_COMPILE_ARGS="--upgrade" DOCKER_COMPOSE_UPGRADE=true \
"./requirements/$(PYTHON_HOST_ENV)/build.txt" devel-upgrade-pre-commit \
devel-upgrade-js devel-upgrade-docker "./var/log/vale-rule-levels.log"
devel-upgrade-js "./.env.~out~" "./var/log/vale-rule-levels.log"
.PHONY: devel-upgrade-pre-commit
## Update VCS integration from remotes to the most recent tag.
devel-upgrade-pre-commit: ./.tox/build/.tox-info.json
Expand All @@ -1059,33 +1064,9 @@ devel-upgrade-js: ./var/log/npm-install.log
~/.nvm/nvm-exec npm outdated
.PHONY: devel-upgrade-docker
## Update the container images of development tools.
devel-upgrade-docker: $(HOST_TARGET_DOCKER) ./.env.~out~
# Define the image tag to track in `./docker-compose*.yml` in the default values for the
# `${DOCKER_*_DIGEST}` environment variables and track the locked/frozen image digests
# in `./.env.in` in VCS:
grep -vE "DOCKER_[A-Z0-9_]+_DIGEST=@.*" <"./.env.in" >"./.env.in.~upgrade~"
mv -v --backup="numbered" "./.env.in.~upgrade~" "./.env.in"
grep -vE "DOCKER_[A-Z0-9_]+_DIGEST=@.*" <"./.env" >"./.env.~upgrade~"
mv -v --backup="numbered" "./.env.~upgrade~" "./.env"
services="$$(
docker compose config --profiles | while read
do
docker compose --profile "$${REPLY}" config --services
done | sort | uniq | grep -Ev '^($(PROJECT_NAME)|build-host)'
)"
docker compose pull $${services}
for service in $${services}
do
env_var="DOCKER_$${service^^}_DIGEST"
env_var="$${env_var//-/_}"
digest="$$(
docker compose config --resolve-image-digests --format "json" \
"$${service}" |
jq -r ".services.\"$${service}\".image" | cut -d "@" -f "2-"
)"
echo "$${env_var}=@$${digest}" >>"./.env.in"
echo "$${env_var}=@$${digest}" >>"./.env"
done
devel-upgrade-docker: $(HOST_TARGET_DOCKER)
touch "./.env.in.~prereq~"
$(MAKE) DOCKER_COMPOSE_UPGRADE=true "./.env.~out~"

.PHONY: devel-upgrade-branch
## Reset an upgrade branch, commit upgraded dependencies on it, and push for review.
Expand All @@ -1108,9 +1089,9 @@ devel-upgrade-branch: ./var/log/git-fetch.log test-clean ./var/log/gpg-import.lo
"./.pre-commit-config.yaml" "./package-lock.json" "./.vale.ini"
git add "./styles/"
# Commit the upgrade changes
echo "Upgrade all requirements to the most recent versions as of" \
echo ":Upgrade: Upgrade all requirements to the most recent versions as of" \
>"./newsfragments/+upgrade-requirements.bugfix.rst"
echo "$${now}." >>"./newsfragments/+upgrade-requirements.bugfix.rst"
echo " $${now}." >>"./newsfragments/+upgrade-requirements.bugfix.rst"
git add "./newsfragments/+upgrade-requirements.bugfix.rst"
git_commit_args="--all --gpg-sign"
git commit $${git_commit_args} -m \
Expand Down Expand Up @@ -1170,6 +1151,7 @@ clean:
# TEMPLATE: Add any other prerequisites that are likely to require updating the build
# package.
./var/log/build-pkgs.log: ./var-host/log/make-runs/$(MAKE_RUN_UUID).log \
./var/log/docker-compose-network.log \
./var-docker/$(DOCKER_VARIANT)/log/build-devel.log
mkdir -pv "$(dir $(@))"
$(DOCKER_COMPOSE_RUN_CMD) $(PROJECT_NAME)-devel \
Expand Down Expand Up @@ -1276,19 +1258,80 @@ $(HOME)/.local/state/docker-multi-platform/log/host-install.log:
fi
date | tee -a "$(@)"

# Create the Docker compose network a single time under parallel make:
./var/log/docker-compose-network.log:
# Perform any initial setup needed by more than one container, such as the network and
# shared volumes:
./var/log/docker-compose-network.log: ./home/.bash_history
$(MAKE) "$(HOST_TARGET_DOCKER)" "./.env.~out~"
mkdir -pv "$(dir $(@))"
# Workaround broken interactive session detection:
docker compose pull --quiet "vale" | tee -a "$(@)"
# Create the Docker compose network a single time under parallel make:
$(DOCKER_COMPOSE_RUN_CMD) --entrypoint "true" vale | tee -a "$(@)"
# Create any mount points for bind volumes that `# dockerd` shouldn't or can't create,
# such as directory bind volumes that root shouldn't own by or file bind volumes that `#
# dockerd` shouldn't create as directories:
./home/.bash_history:
touch "$(@)"

# Local environment variables and secrets from a template:
./.env.in.~prereq~:
touch "$(@)"
./.env.in: ./.env.in.~prereq~
ifeq ($(DOCKER_COMPOSE_UPGRADE),true)
# Define the image tag to track in `./compose*.yml` in the default values for the
# `${DOCKER_*_DIGEST}` environment variables and track the locked/frozen image digests
# in `./.env.in` in VCS:
#
# If changes updated the template, prompt the user to reconcile any differences before
# upgrading image digests:
if test "$(@)" -nt "$(@:%.in=%)"
then
$(call expand_template,$(@),$(@:%.in=%))
fi
# Create a temporary `./.env` without any image digests so that `$ docker compose`
# reverts to use the image tags, for example `*:latest`:
grep -vE "DOCKER_[A-Z0-9_]+_DIGEST=@.*" <"$(@)" >"$(@).~upgrade~"
mv -v --backup="numbered" "$(@).~upgrade~" "$(@)"
if test -e "$(@:%.in=%)"
then
mv -v "$(@:%.in=%)" "$(@:%.in=%).~upgrade~"
fi
envsubst <"$(@)" >"$(@:%.in=%)"
# Pull the most recent images for the given tags:
services="$$(
docker compose config --profiles | while read
do
docker compose --profile "$${REPLY}" config --services
done | sort | uniq | grep -Ev '^($(PROJECT_NAME)|build-host)'
)"
docker compose pull $${services}
# Write the image digests for the pulled images back to the `./.env.in` template:
for service in $${services}
do
env_var="DOCKER_$${service^^}_DIGEST"
env_var="$${env_var//-/_}"
digest="$$(
docker compose config --resolve-image-digests --format "json" \
"$${service}" |
jq -r ".services.\"$${service}\".image" | cut -d "@" -f "2-"
)"
echo "$${env_var}=@$${digest}" >>"$(@)"
done
# Restore the user's possibly customized `./.env` but with the new image digests:
if test -e "$(@:%.in=%).~upgrade~"
then
grep -vE "DOCKER_[A-Z0-9_]+_DIGEST=@.*" \
<"$(@:%.in=%).~upgrade~" >"$(@:%.in=%)"
grep -E "DOCKER_[A-Z0-9_]+_DIGEST=@.*" <"$(@)" >>"$(@:%.in=%)"
fi
else
# There's nothing to change in the template if not upgrading image digests:
touch "$(@)"
endif
./.env.~out~: ./.env.in
$(call expand_template,$(<),$(@))

./README.md: README.rst
./README.md: README.rst ./var/log/docker-compose-network.log
$(MAKE) "$(HOST_TARGET_DOCKER)"
$(DOCKER_COMPOSE_RUN_CMD) "pandoc"

Expand Down Expand Up @@ -1327,7 +1370,7 @@ endif
./var/log/git-ls-files.log: ./var-host/log/make-runs/$(MAKE_RUN_UUID).log
mkdir -pv "$(dir $(@))"
git ls-files >"$(@).~new~"
if diff -u "$(@)" "$(@).~new~"
if diff --color -u "$(@)" "$(@).~new~"
then
exit
fi
Expand Down Expand Up @@ -1592,7 +1635,7 @@ then
fi
if test "$(CI)" != "true"
then
envsubst <"$(1)" | diff -u "$(2:%.~out~=%)" "-" || true
envsubst <"$(1)" | diff --color -u "$(2:%.~out~=%)" "-" || true
fi
set +x
echo "WARNING:Template $(1) changed, reconcile and \`$$ touch $(2:%.~out~=%)\`."
Expand Down
10 changes: 5 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
.. SPDX-License-Identifier: MIT
.. image:: ./docs/_static/logo-120.png
.. include-above-contents-start
.. include-before-contents-start
########################################################################################
Project Structure
Expand Down Expand Up @@ -122,9 +122,9 @@ variants. Real projects can also merge those changes.
.. _`Organize source by feature`:
https://www.seancdavis.com/posts/organize-components-by-keeping-related-files-close/

.. include-above-contents-end
.. include-before-contents-end
.. contents:: Table of Contents
.. include-below-contents-start
.. include-after-contents-start
****************************************************************************************
Expand Down Expand Up @@ -236,7 +236,7 @@ Installation

Install locally or use the Docker container image:

Local Installation
Local installation
========================================================================================

Use a package manager for the project language to install locally::
Expand All @@ -245,7 +245,7 @@ Use a package manager for the project language to install locally::
$ true "TEMPLATE: Always specific to the project type"
Docker Container Image
Docker container image
========================================================================================

The recommended way to use the container image is by using `Docker Compose`_. See `the
Expand Down
3 changes: 2 additions & 1 deletion bin/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ main() {

# Ensure the home directory in the image has the correct permissions. Change
# permissions selectively to avoid time-consuming recursion:
chown ${CHOWN_ARGS} -R "${PUID}:${PGID}" "/home/${PROJECT_NAME}/"
chown ${CHOWN_ARGS} "${PUID}:${PGID}" "/home/${PROJECT_NAME}/" \
/home/${PROJECT_NAME}/.??* /home/${PROJECT_NAME}/.local/*

# Add an unprivileged user:
if ! getent group "${PGID}" >"/dev/null"
Expand Down
Loading

0 comments on commit 154d171

Please sign in to comment.